赞
踩
RTOS即为操作系统。主要目的是使我们可以同时使用多个任务。
本文将介绍:
a. 使用CubeMX 设置的免费RTOS。
b. 使用RTOS的好处。
c. 在没有CubeMX情况下创建任务。
d. 使用优先级来解决一些常见的问题
设置CubeMX
1.1 由于FreeRTOS v1大多数STM32设备都支持,故选择CMSIS_V1。
1.2 转到Tasks and Queues, 注意Task name、priority和entry function即可。
1.3 新建另外一个任务Task2,修改Task name 和 entry function分别为 Task2 和 Task2_init
1.4 用RTOS的话,则不能用systick作为时基,则选用其他时基源,并且选用Serial Wire 作为debug方式
1.5 用USART1作为数据传输口用异步模式,同时打开中断
1.6 由于板子外接高速时钟,配置HSE,同样开启中断:
时钟配置,7种时钟的简介
使用RTOS的优势
多线程
创建任务
创建任务必须遵循:
3.1 定义任务的ThreadID,后续对于此任务的所有操作都需要此ID
3.2 定义任务的输入函数,这就是任务的主要函数,程序将被写入,RTOS任务是没有返回值,故入口函数是一个死循环函数。
3.3 主函数中需要先定义任务再创建任务。
osThreadDef 参数分别为:任务名称,输入函数,优先级,实例和堆栈大小。定义任务后,我们可以使用创建任务osThreadCreate,并将ID分配给Task3Handle。
FreeRTOS中的优先级
当我们尝试在优先级相同的任务之间使用共享资源时,就会发生这种情况。第二项任务必须等待第一个任务完成,然后才能完成控制。同样,第三个任务将等待第二个任务完成(任务中间有延时,就效率很低)。
可以定义任务间不同优先级,就能合理安排任务的调用。
用串口看任务优先级
注意: 当用osDelay()时,让任务阻塞,任务阻塞后,RTOS系统调用其它处于就绪状态的优先级最高的任务来执行。当使用HAL_Delay()时,HAL_Delay一直不停的调用获取系统时间的函数,直到指定的时间流逝然后退出,故其占用了全部CPU时间。
void send_task1(void){
uint8_t data[] = "task1\n";
HAL_UART_Transmit(&huart1, data, sizeof(data),500);
}
void send_task2(void){
uint8_t data[] = "task2\n";
HAL_UART_Transmit(&huart1, data, sizeof(data),500);
}
void Task1_init(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { send_task1(); HAL_Delay(1000); } /* USER CODE END 5 */ } void Task2_init(void const * argument) { /* USER CODE BEGIN Task2_init */ /* Infinite loop */ for(;;) { // 执行函数 send_task2(); HAL_Delay(1000); } /* USER CODE END Task2_init */ }
1.1 任务优先级相同时
osThreadDef(Task1, Task1_init, osPriorityNormal, 0, 128);
Task1Handle = osThreadCreate(osThread(Task1), NULL);
/* definition and creation of Task2 */
osThreadDef(Task2, Task2_init, osPriorityNormal, 0, 128);
Task2Handle = osThreadCreate(osThread(Task2), NULL);
输出结果:
说明:当定义相同优先级输出如下,调度器会让这些任务轮流执行。
1.2 当定义不同优先级输出如下:
osThreadDef(Task1, Task1_init, osPriorityNormal, 0, 128);
Task1Handle = osThreadCreate(osThread(Task1), NULL);
/* definition and creation of Task2 */
osThreadDef(Task2, Task2_init, osPriorityAboveNormal, 0, 128);
Task2Handle = osThreadCreate(osThread(Task2), NULL);
输出结果:
说明:调度器总是选择具有最高优先级的可运行任务来执行。任务 2 的优先级比任务 1高,并且总是可运行,因此任务 2 是唯一一个一直处于运行态的任务。而任务 1 不可能进入运行态,所以不可能输出字符串。这种情况我们称为任务 1 的执行时间被任务 2”饿死(starved)”了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。