[其他ST产品] STM32中的FreeRTOS-#1(入门)

[复制链接]
 楼主| grfqq325 发表于 2022-12-31 22:45 | 显示全部楼层
CubeMX生成代码虽然很方便,但是不足之处在于缺乏灵活性。比如在CubeMX中更改已创建的任务的入口函数名称后,重新生成代码,自己在原任务函数中编写的代码会被全部清除。也就是说,任务一旦创建,入口函数名称便不便于更改(后续版本可能会优化这个问题)。
 楼主| grfqq325 发表于 2022-12-31 22:46 | 显示全部楼层
下面我们手动创建一个自定义的任务。创建一个新的Task,需要遵循一些步骤,如下所示:

(1)为任务定义一个ThreadID(线程ID,相当于人的身份*号)。一旦创建,这个变量将存储任务的唯一ID。稍后,所有操作都将需要这个ID。
 楼主| grfqq325 发表于 2022-12-31 22:47 | 显示全部楼层
  1. /* USER CODE END Variables */
  2. osThreadId myTask03Handle;        // 定义任务3句柄,仿照软件生成的代码去写
 楼主| grfqq325 发表于 2022-12-31 22:47 | 显示全部楼层
定义任务的入口函数。这是任务函数,以后这个任务的代码将被写在里面。注意,Free RTOS中的任务不是设计来处理任何返回值的。因此,入口函数应该里面应该包含一个无限循环(for或者while),整个程序都应该在这个循环中编写。
 楼主| grfqq325 发表于 2022-12-31 22:48 | 显示全部楼层
//  任务实现 不要忘了在前面写上本函数的声明
void StartTask03 (void const * argument)
{
     while (1)
     {
         // do something
         osDelay (1000);  // 1 sec delay
     }
}
 楼主| grfqq325 发表于 2022-12-31 22:49 | 显示全部楼层
在在**MX_FREERTOS_Init(void)**初始化函数中,我们需要创建任务(类似于PC编程里面的对象实例化)。
 楼主| grfqq325 发表于 2022-12-31 22:50 | 显示全部楼层
  1. osThreadDef(myTask03, StartTask03, osPriorityBelowNormal, 0, 128);
  2. myTask03Handle = osThreadCreate(osThread (myTask03), NULL);
 楼主| grfqq325 发表于 2022-12-31 22:53 | 显示全部楼层
在FreeRTOS原生函数中这个地方只需要一行代码,但是在CMSIS封装的库中,这里有两行代码,作用一样。细节可以查看osThreadDef和osThreadCreate两个宏。
 楼主| grfqq325 发表于 2022-12-31 22:53 | 显示全部楼层
osThreadDef是一个宏,本质是定义一个结构体变量,并将括号内的参数,即任务的名称、入口函数、优先级、实例和堆栈大小,给这个新结构体变量赋值。
 楼主| grfqq325 发表于 2022-12-31 22:54 | 显示全部楼层
osThreadCreate也是一个宏,用于在定义任务后,顾名思义,给任务创建线程,并将任务的ID分配给myTask03Handle。
 楼主| grfqq325 发表于 2022-12-31 22:55 | 显示全部楼层
在FreeRTOS中处理优先级

截止目前,我们知道了如何使用RTOS进行多任务处理。但随之而来的是一些问题。在上述示波器波形里面,可以看到,LED-0的引脚总是比LED-1优先翻转,那如果想让LED-1的引脚优先翻转该怎么办?
 楼主| grfqq325 发表于 2022-12-31 22:55 | 显示全部楼层
再者,假设我们希望所有三个任务同时通过UART1发送一些数据该怎么做?
 楼主| grfqq325 发表于 2022-12-31 22:56 | 显示全部楼层
当我们编写程序这样做时,结果将不完全相同。相反,串口发送将以这样一种方式进行: 一个任务将在1秒内发送数据,而另一个任务将在另一秒内发送数据,以此类推。
 楼主| grfqq325 发表于 2022-12-31 22:57 | 显示全部楼层
当我们试图在具有相同优先级的任务之间使用共享资源时,就会发生这种情况。第二个任务必须等待第一个任务完成它的执行,然后只有控制进入它。同样地,第三个任务将等待第二个任务完成。即,任务不能相互打断,只能排队执行
 楼主| grfqq325 发表于 2022-12-31 22:57 | 显示全部楼层
因为延时1ms对于串口输出来说时间太短,所以在开始下面的步骤前,请先把任务函数内的延时均改为1000ms,即 osDelay (1); -> osDelay (1000);
 楼主| grfqq325 发表于 2022-12-31 22:58 | 显示全部楼层
为了避免这些情况,我们对不同的任务使用不同的优先级。这意味着我们必须重新定义主要功能中的任务优先级(仅修改优先级即可)。
 楼主| grfqq325 发表于 2022-12-31 22:59 | 显示全部楼层
  1.   /* definition and creation of defaultTask */
  2.   osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  3.   defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  4.   /* definition and creation of myTask02 */
  5.   osThreadDef(myTask02, StartTask02, osPriorityAboveNormal, 0, 128);
  6.   myTask02Handle = osThreadCreate(osThread(myTask02), NULL);

  7.   /* USER CODE BEGIN RTOS_THREADS */
  8.   /* add threads, ... */
  9.   osThreadDef(myTask03, StartTask03, osPriorityBelowNormal, 0, 128);
  10.   myTask03Handle = osThreadCreate(osThread (myTask03), NULL);
  11.   /* USER CODE END RTOS_THREADS */
 楼主| grfqq325 发表于 2022-12-31 22:59 | 显示全部楼层
重定向printf函数,用于串口输出:
  1. #include <stdio.h>        // 引用头文件
  2. int fputc(int ch, FILE *f)
  3. {
  4.   HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  5.   return ch;
  6. }
 楼主| grfqq325 发表于 2022-12-31 23:00 | 显示全部楼层
在各任务实现函数中,添加如下代码:
  1. // 任务1
  2. printf("Task1 is going");
  3. // 任务2
  4. printf("Task2 is going");
  5. // 任务3
  6. printf("Task3 is going");
 楼主| grfqq325 发表于 2022-12-31 23:01 | 显示全部楼层
现在Task2的优先级最高,高于默认任务,Task3的优先级最低。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部