02_FreeRTOS 任务管理
本文将介绍:
a. 创建任务
b. 任务执行
c. 挂起任务和恢复任务
d. 在一定状态停止任务一段时间
附录:
如何在STM32CubeIDE中加入printf打印
解决STM32CubeIDE 用串口printf 进入hardfault
-
配置STM32CubeIDE,把vTaskDelayUntil 设置为Enabled
-
创建任务
分三部:
2.1 创建任务ID
2.2 使用osThreadDef
定义线程
2.3 创建线程并将ID分配给任务处理程序。
参照01_FreeRTOS 任务优先级。 -
任务执行
osDelay()会让当前的线程进入阻塞模式,到时间后就会退出阻塞模式。比如Task2 中延时2s Task1 中延时1s,所以当Taks2进入阻塞状态,Task1此时优先级最高运行一次后,Task1也进入阻塞状态,过去1s后再次运行Task1。当过去2s,两个Task都退出阻塞状态,此时由于Task2的优先级要比Task1的优先级高,故开始先运行Task2。如此往复。
优先级定义部分:
/* definition and creation of Task1 */
osThreadDef(Task1, Task1_init, osPriorityNormal, 0, 512);
Task1Handle = osThreadCreate(osThread(Task1), NULL);
/* definition and creation of Task2 */
osThreadDef(Task2, Task2_init, osPriorityAboveNormal, 0, 512);
Task2Handle = osThreadCreate(osThread(Task2), NULL);
printf部分:
uint8_t indx = 0;
void send_task1(void){
printf("task1 running...\n");
}
void send_task2(void){
printf("task2 indx= %d \n ",indx ++);
}
输出结果:
- 挂起任务和恢复任务
当Task被挂起后,它一直处于挂起状态,用osThreadSuspend
函数挂起一个Task,参数是线程ID,用osThreadResume
退出挂起状态。
在Task2 入口函数加入:
void Task2_init(void const * argument)
{
/* USER CODE BEGIN Task2_init */
/* Infinite loop */
for(;;)
{
send_task2();
osDelay(2000);
if (indx==4)
{
printf ("suspending Task1Handle\n");
osThreadSuspend(Task1Handle);
}
if (indx ==7)
{
printf ("Resuming Task1Handle\n");
osThreadResume(Task1Handle);
indx = 0;
}
}
/* USER CODE END Task2_init */
}
输出结果:
- 停止任务一段时间
用 osDelayUntil (uint32_t *PreviousWakeTime, uint32_t millisec)
函数来实现,PreviousWakeTime
指向开始停止的时候。
Task入口函数:
/* USER CODE END Header_Task2_init */
void Task2_init(void const * argument)
{
/* USER CODE BEGIN Task2_init */
/* Infinite loop */
for(;;)
{
send_task2();
osDelay(2000);
if(indx == 5)
{
uint32_t PreviousWakeTime = osKernelSysTick();
osDelayUntil(&PreviousWakeTime, 4000);
}
}
/* USER CODE END Task2_init */
}
结果:
附录:
如何在STM32CubeIDE中加入打印串口printf
只需要在main.c中加入如下部分就可以实现串口printf:
// 把这部分加入主函数初始化中
/* 禁用STDOUT流的I/O 缓冲,以便在打印字符时立即发送。*/
setvbuf(stdout, NULL, _IONBF, 0);
// …
/* USER CODE BEGIN 0 */
#include "errno.h"
#include "stdio.h"
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, char* ptr, int len) {
/* 禁用STDOUT流的I/O 缓冲,以便在打印字符时立即发送。*/
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
HAL_StatusTypeDef hstatus;
hstatus = HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
if (hstatus == HAL_OK)
return len;
else
return EIO;
}
errno = EBADF;
return -1;
}
/* USER CODE END 0 */
解决STM32CubeIDE 用串口printf 进入hardfault
分析:由于给Task分配的堆栈太小。
把堆栈加大到512,并且先要在main中执行一次printf才行,否则直接Hard Fault异常。 如图:
STM32CubeIDE其他设置,进入Project->Properties,如下设置:
即可使用printf向串口1打印数据。