FreeRTOS笔记(三)配置文件FreeRTOSConfig.h


上一文链接:FreeRTOS笔记(二)移植STM32F407

01 - FreeRTOS内核剪裁

1.1 - FreeRTOSConfig.h文件

  在上一文中,针对官方给出的STM32F407例程Demo,很容易移植了FreeRTOS到STM32F407上并成功运行。容易的原因是官方Demo中对FreeRTOS内核的配置已经完全对应了STM32F407的硬件配置,配置文件就是FreeRTOSConfig.h。
  打开官方的API手册,可以看到,第7章就是内核配置文件的描述:

  能够看到,FreeRTOSConfig.h其实就是对内核进行剪裁的配置文件,主体宏分为两部分,一部分是前缀为INCLUER_的宏,另一部分是前缀为config的宏,它们的用处文档有很详细的结束,小白简单总结如下:

1.2 - FreeRTOSConfig.h内容

  在FreeRTOSConfig.h中,我们暂时只关心一些常用内容的配置,根据官方文档,能够知道config前缀宏的映射内容,下面是部分的注释:

#define configUSE_PREEMPTION            1                               //0-协程调度,1-抢占式调度
#define configUSE_IDLE_HOOK             0                               //0-除能空闲任务的钩子函数,1-使能
#define configUSE_TICK_HOOK             0                               //0-除能时间片钩子函数,1-使能
#define configCPU_CLOCK_HZ              ( SystemCoreClock )             //设置CPU频率
#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )         //设置滴答计时器的中断频率,为HZ/1000=1ms
#define configMAX_PRIORITIES            ( 5 )                           //任务优先级是0~(configMAX_PRIORITIES-1)
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )      //设置空闲任务的堆栈大小,单位是字(4字节)
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) )    //设置系统总堆栈大小
#define configMAX_TASK_NAME_LEN         ( 10 )                          //设置任务名最大长度
#define configUSE_TRACE_FACILITY        1                               //0-除能可视化跟踪调试,1-使能
#define configUSE_16_BIT_TICKS          0                               //节拍计时器变量范围,0-16位,1-32位
#define configIDLE_SHOULD_YIELD         1                               //0-空闲任务不会让出CPU给同等优先级的任务,1-会让出CPU
#define configUSE_MUTEXES               1                               //0-除能互斥信号量,1-使能
#define configQUEUE_REGISTRY_SIZE       8                               //0-除能内核调试中查看队列和信号量数量,>0-可以注册的数量
#define configCHECK_FOR_STACK_OVERFLOW  0                               //0-除能堆栈溢出检测,1-使能
#define configUSE_RECURSIVE_MUTEXES     1                               //0-除能递归互斥信号量,1-使能
#define configUSE_MALLOC_FAILED_HOOK    0                               //0-除能malloc失败时调用的钩子函数,1-使能
#define configUSE_APPLICATION_TASK_TAG  0                               //0-除能一些应用程序钩子函数,1-使能
#define configUSE_COUNTING_SEMAPHORES   1                               //0-除能计数信号量,1-使能
#define configGENERATE_RUN_TIME_STATS   0                               //0-除能时间统计功能,1-使能

……

//硬件相关的中断位数
#ifdef __NVIC_PRIO_BITS
    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
    #define configPRIO_BITS             __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS             4        /* 15 priority levels */           
#endif

//最低优先级,一般与configPRIO_BITS对应,2^configPRIO_BITS-1
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         0xf                         

//可管理的最大优先级(设置STM的BASEPRI寄存器)
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                           

//真正的中断优先级,用于设置滴答中断等等的优先级
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

//真正的中断优先级,最大可以使用FreeRTOS-API的中断优先级
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

  FreeRTOSConfig.h前部分是一些CPU、调度算法等配置,后部分是中断配置。能够清晰观测到,只有配置了例如CPU频率、滴答时钟频率等等的硬件相关内容才能成功移植,而其它的一些例如信号量、钩子函数等等的内容是根据实际情况而定的。
  前部分的内容是硬件能运行的基本配置,而后部分的中断配置是实时嵌入式系统的需求配置,中断配置内存如下:

FreeRTOS中断配置
1、 确定逻辑上表达中断优先级数量的寄存器位数: STM32F407为4位,共16个优先级
2、 确定逻辑上最低优先级: STMF407为2^4 - 1 = 15
3、 确定逻辑上FreeRTOS可管理的最大优先级: 设置为5,意味着优先级>=5的优先级不受FreeRTOS管理和处理
4、 确定寄存器上真正的最低优先级: STM使用寄存器的高位,摒弃低位,因此需要移位
5、 确定寄存器上FreeRTOS可管理的最大优先级: 需要移位

  可管理的最大优先级描述如下:

02 - 测试剪裁内容

2.1 - 任务设计

  在此我们测试FreeRTOSConfig.h中的中断配置,可管理的最大优先级为5,也就优先级<5的中断不归FreeRTOS管理,于是设计测试程序逻辑如下:

  在上一文的工程中进行编程,先编写定时器代码,再编写任务代码。其中定时器使用通用定时器3和5,两者都是定时1s,唯一不同的是优先级,定时器3的优先级是4(超过了FreeRTOS管理的优先级),定时器5的优先级是6(可以被FreeRTOS管理)。
  定时器配置代码区别的位置如下:

// 定时器3
……
	NVIC_struct.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_struct.NVIC_IRQChannelPreemptionPriority = 0x04;	//抢占优先级4
	NVIC_struct.NVIC_IRQChannelSubPriority = 0x00;
	NVIC_struct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_struct);
……

……
// 定时器5
	NVIC_struct.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_struct.NVIC_IRQChannelPreemptionPriority = 0x06;	//抢占优先级4
	NVIC_struct.NVIC_IRQChannelSubPriority = 0x00;
	NVIC_struct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_struct);
……

/* ----------------------------中断函数---------------------------*/
void TIM5_IRQHandler(void)
{
	//溢出中断
	if(TIM_GetITStatus(TIM5,TIM_IT_Update) == SET)
	{
		printf("timer5 with priority 6 \r\n");
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
}
void TIM3_IRQHandler(void)
{
	//溢出中断
	if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
	{
		printf("timer3 with priority 4 \r\n");
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}	

  开关中断我们采用注释然后重新编辑的方式去实现,不能使用vTaskDelay()来进行间隔开关中断,因为vTaskDelay()会挂起调度器,导致不能进行任务切换,但是同时也开启了中断,不能起到关中断的作用。

/* Start 任务 */
void start_task(void *pParam)
{	
	//portDISABLE_INTERRUPTS();
	for(;;)
	{
		portDISABLE_INTERRUPTS();
		printf("satrt portDISABLE_INTERRUPTS()\r\n");
		vTaskDelay(5000);
		portENABLE_INTERRUPTS();
		printf("satrt portENABLE_INTERRUPTS()\r\n");
		vTaskDelay(5000);
	}		
}	

2.2 - 测试结果

  首先测试statr开中断(默认),运行结果如下,两个定时器都在相继输出

  然后是关闭中断,运行结果如下。只有time3在输出,因为time3优先级为4,超出了FreeRTOS配置的最大可管理优先级5,所有timer3不受管理,而time5优先级是6,在FreeRTOS中断管理优先级内,于是timer5被关闭。

03 - 总结

  • FreeRTOS内核剪裁配置文件是FreeRTOSConfig.h
  • FreeRTOSConfig.h前部分是一些CPU、调度算法等配置,后部分是中断配置
  • FreeRTOSConfig.h的中断配置使得FreeRTOS系统可以理会和不理会某些中断

猜你喜欢

转载自blog.csdn.net/Hxj_CSDN/article/details/84765125