文章目录
参考资料:
- 《STM32F103 FreeRTOS开发手册V1.1》
1 STM32CubeMX参数配置及其说明
1.1 FreeRTOS Mode
这里有两种选项
参考文章:FreeRTOS选项中Disable、CMSIS_V1和CMSIS_V2的区别
这里做实验使用的单片机是STM32F1系列,内核为Cortex - M3,所以选择CMSIS_V1即可。
1.2 Config parameters
1.2.1 Kernel setting
-
USE_PREEMPTION
为1时使用抢占是调度器,为0时使用协程。 -
TICK_RATE_HZ
系统时钟节拍频率,单位为HZ。值设置为1000,即周期就是1ms。 -
MAX_PRIORITIES
设置任务的优先级数量,设置好以后任务就可以使用从0到(MAX_PRIORITIES - 1)的优先级,其中0位最低优先级,(MAX_PRIORITIES - 1)为最高优先级。 -
MINIMAL_STACK_SIZE
设置空闲任务的最小任务堆栈大小,以字为单位,而不是字节。如该值设置为128 Words,那么真正的堆栈大小就是 128*4 = 512 Byte -
MAX_TASK_NAME_LEN
设置任务名最大长度 -
IDLE_SHOULD_YIELD
定义了与空闲任务(idle Task)处于同等优先级的其他用户任务的行为,当为0时空闲任务不会为其他处于同优先级的任务让出CPU使用权;当为1时空闲任务就会为处于同优先级的任务让出CPU使用权,除非没有就绪的用户任务。建议设置为0. -
USE_MUTEXES
为1时使用互斥信号量,相关的API函数会被编译。 -
USE_RECURSIVE_MUTEXES
为1时使用递归互斥信号量,相关的API函数会被编译。 -
USE_COUNTING_SEMAPHORES
为1时启用计数型信号量, 相关的API函数会被编译。 -
QUEUE_REGISTRY_SIZE
设置可以注册的队列和信号量的最大数量,在使用内核调试器查看信号量和队列的时候需要设置此宏,而且要先将消息队列和信号量进行注册,只有注册了的队列和信号量才会在内核调试器中看到,如果不使用内核调试器的话次宏设置为0即可。 -
USE_APPLICATION_TASK_TAG
为1时可以使用vTaskSetApplicationTaskTag函数。 -
ENABLE_BACKWARD_COMPATIBILITY
为1时可以使V8.0.0之前的FreeRTOS用户代码直接升级到V8.0.0之后,而不需要做任何修改。 -
USE_PORT_OPTIMISED_TASK_SELECTION
FreeRTOS有两种方法来选择下一个要运行的任务,一个是通用的方法,另外一个是特殊的方法,也就是硬件方法,使用MCU自带的硬件指令来实现。STM32有计算前导零指令吗,所以这里强制置1. -
USE_TICKLESS_IDLE
为1时使能低功耗tickless模式 -
USE_TASK_NOTIFICATIONS
为1时使用任务通知功能,相关的API函数会被编译。开启了此功能,每个任务会多消耗8个字节。 -
RECORD_STACK_HIGH_ADDRESS
为1时栈开始地址会被保存到每个任务的TCB中(假如栈是向下生长的)
1.2.2 Memory management setting
- TOTAL_HEAP_SIZE
设置堆大小,如果使用了动态内存管理,FreeRTOS在创建 task, queue, mutex, software timer or semaphore的时候就会使用heap_x.c(x为1~5)中的内存申请函数来申请内存。这些内存就是从堆ucHeap[configTOTAL_HEAP_SIZE]中申请的。
1.2.3 Hook function related definitions
钩子函数(hook)也叫回调函数(callback)
1.3 创建任务Task和队列Queue
1.3.1 创建任务Task
其中任务的堆(heap)使用计算:
FreeRTOS requires to allocate in the heap for that user task:
number of bytes = TCB size + (4 * task stack size) = 624 Bytes
Here:
TCB size = 112
task stack size = 128
1.3.2 创建队列Queue
其中队列的堆(heap)使用计算:
FreeRTOS requires to allocate in the heap for that message queue:
number of bytes = 76 + queue_storage_area = 124 Bytes
queue_storage_area (in bytes) = (element_size * nb_elements) + 16.
Here:
element_size = 2
nb_elements = 16
1.4 FreeRTOS Heap Usage
STM32CubeMX在配置完参数后会自动计算使用堆的情况
1.5 FreeRTOS时钟和HAL timebase Source
1.5.1 FreeRTOS时钟和HAL timebase 使用同一时钟源
参考文章:STM32 Cubemx FreeRTOS的timebase配置
FreeRTOS默认使用SysTick作为时钟源,而如果timebase Source也选择SysTick,如下图
则会出现如下警告
- 如果强行点击Yes
在stm32f1xx_it.c中找到如下函数,可以看出FreeRTOS 滴答时钟和HAL timebase都使用SysTick作为时钟源,强烈建议不要这样做。
void SysTick_Handler(void)
{
HAL_IncTick(); /*HAL timebase*/
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif /* INCLUDE_xTaskGetSchedulerState */
xPortSysTickHandler(); /*FreeRTOS 滴答时钟*/
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif /* INCLUDE_xTaskGetSchedulerState */
}
1.5.1 FreeRTOS时钟和HAL timebase 使用不同时钟源
选择TIM7作为HAL timebase 时钟源
- HAL timebase时钟源
在生成的工程中多出了一个时基的c文件
该文件将TIM7初始化为HAL的时基源,中断周期为1ms
在main.c文件中可以找到如下函数,
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM7) {
HAL_IncTick();
}
}
HAL timebase最明显的使用场景是 使用HAL库的延时函数 HAL_Delay
- FreeRTOS的时钟源
在cmsis_os.c文件中有如下函数
/**
* @brief Handles the tick increment
* @param none.
* @retval none.
*/
void osSystickHandler(void)
{
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif /* INCLUDE_xTaskGetSchedulerState */
xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif /* INCLUDE_xTaskGetSchedulerState */
}
在FreeRTOSConfig.h文件中可以找到如下宏定义
#define xPortSysTickHandler SysTick_Handler
转载:https://blog.csdn.net/qq_42900996/article/details/117325419