02

    技术2024-01-08  102

    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打印数据。

    Code下载地址

    Processed: 0.016, SQL: 9