打印
[其他ST产品]

STM32中的FreeRTOS-#1(入门)

[复制链接]
楼主: grfqq325
手机看帖
扫描二维码
随时随地手机跟帖
21
grfqq325|  楼主 | 2022-12-31 22:45 | 只看该作者 回帖奖励 |倒序浏览
CubeMX生成代码虽然很方便,但是不足之处在于缺乏灵活性。比如在CubeMX中更改已创建的任务的入口函数名称后,重新生成代码,自己在原任务函数中编写的代码会被全部清除。也就是说,任务一旦创建,入口函数名称便不便于更改(后续版本可能会优化这个问题)。

使用特权

评论回复
22
grfqq325|  楼主 | 2022-12-31 22:46 | 只看该作者
下面我们手动创建一个自定义的任务。创建一个新的Task,需要遵循一些步骤,如下所示:

(1)为任务定义一个ThreadID(线程ID,相当于人的身份*号)。一旦创建,这个变量将存储任务的唯一ID。稍后,所有操作都将需要这个ID。

使用特权

评论回复
23
grfqq325|  楼主 | 2022-12-31 22:47 | 只看该作者
/* USER CODE END Variables */
osThreadId myTask03Handle;        // 定义任务3句柄,仿照软件生成的代码去写

使用特权

评论回复
24
grfqq325|  楼主 | 2022-12-31 22:47 | 只看该作者
定义任务的入口函数。这是任务函数,以后这个任务的代码将被写在里面。注意,Free RTOS中的任务不是设计来处理任何返回值的。因此,入口函数应该里面应该包含一个无限循环(for或者while),整个程序都应该在这个循环中编写。

使用特权

评论回复
25
grfqq325|  楼主 | 2022-12-31 22:48 | 只看该作者
//  任务实现 不要忘了在前面写上本函数的声明
void StartTask03 (void const * argument)
{
     while (1)
     {
         // do something
         osDelay (1000);  // 1 sec delay
     }
}

使用特权

评论回复
26
grfqq325|  楼主 | 2022-12-31 22:49 | 只看该作者
在在**MX_FREERTOS_Init(void)**初始化函数中,我们需要创建任务(类似于PC编程里面的对象实例化)。

使用特权

评论回复
27
grfqq325|  楼主 | 2022-12-31 22:50 | 只看该作者
osThreadDef(myTask03, StartTask03, osPriorityBelowNormal, 0, 128);
myTask03Handle = osThreadCreate(osThread (myTask03), NULL);

使用特权

评论回复
28
grfqq325|  楼主 | 2022-12-31 22:53 | 只看该作者
在FreeRTOS原生函数中这个地方只需要一行代码,但是在CMSIS封装的库中,这里有两行代码,作用一样。细节可以查看osThreadDef和osThreadCreate两个宏。

使用特权

评论回复
29
grfqq325|  楼主 | 2022-12-31 22:53 | 只看该作者
osThreadDef是一个宏,本质是定义一个结构体变量,并将括号内的参数,即任务的名称、入口函数、优先级、实例和堆栈大小,给这个新结构体变量赋值。

使用特权

评论回复
30
grfqq325|  楼主 | 2022-12-31 22:54 | 只看该作者
osThreadCreate也是一个宏,用于在定义任务后,顾名思义,给任务创建线程,并将任务的ID分配给myTask03Handle。

使用特权

评论回复
31
grfqq325|  楼主 | 2022-12-31 22:55 | 只看该作者
在FreeRTOS中处理优先级

截止目前,我们知道了如何使用RTOS进行多任务处理。但随之而来的是一些问题。在上述示波器波形里面,可以看到,LED-0的引脚总是比LED-1优先翻转,那如果想让LED-1的引脚优先翻转该怎么办?

使用特权

评论回复
32
grfqq325|  楼主 | 2022-12-31 22:55 | 只看该作者
再者,假设我们希望所有三个任务同时通过UART1发送一些数据该怎么做?

使用特权

评论回复
33
grfqq325|  楼主 | 2022-12-31 22:56 | 只看该作者
当我们编写程序这样做时,结果将不完全相同。相反,串口发送将以这样一种方式进行: 一个任务将在1秒内发送数据,而另一个任务将在另一秒内发送数据,以此类推。

使用特权

评论回复
34
grfqq325|  楼主 | 2022-12-31 22:57 | 只看该作者
当我们试图在具有相同优先级的任务之间使用共享资源时,就会发生这种情况。第二个任务必须等待第一个任务完成它的执行,然后只有控制进入它。同样地,第三个任务将等待第二个任务完成。即,任务不能相互打断,只能排队执行

使用特权

评论回复
35
grfqq325|  楼主 | 2022-12-31 22:57 | 只看该作者
因为延时1ms对于串口输出来说时间太短,所以在开始下面的步骤前,请先把任务函数内的延时均改为1000ms,即 osDelay (1); -> osDelay (1000);

使用特权

评论回复
36
grfqq325|  楼主 | 2022-12-31 22:58 | 只看该作者
为了避免这些情况,我们对不同的任务使用不同的优先级。这意味着我们必须重新定义主要功能中的任务优先级(仅修改优先级即可)。

使用特权

评论回复
37
grfqq325|  楼主 | 2022-12-31 22:59 | 只看该作者
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

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

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  osThreadDef(myTask03, StartTask03, osPriorityBelowNormal, 0, 128);
  myTask03Handle = osThreadCreate(osThread (myTask03), NULL);
  /* USER CODE END RTOS_THREADS */

使用特权

评论回复
38
grfqq325|  楼主 | 2022-12-31 22:59 | 只看该作者
重定向printf函数,用于串口输出:
#include <stdio.h>        // 引用头文件
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}

使用特权

评论回复
39
grfqq325|  楼主 | 2022-12-31 23:00 | 只看该作者
在各任务实现函数中,添加如下代码:
// 任务1
printf("Task1 is going");
// 任务2
printf("Task2 is going");
// 任务3
printf("Task3 is going");

使用特权

评论回复
40
grfqq325|  楼主 | 2022-12-31 23:01 | 只看该作者
现在Task2的优先级最高,高于默认任务,Task3的优先级最低。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则