[其他ST产品] 基于FreeRTOS的STM32多任务程序

[复制链接]
1284|23
 楼主| 大鹏2365 发表于 2022-12-31 23:06 | 显示全部楼层 |阅读模式
材料准备

STM32指南者开发板(包括USB串口转换线、所需软件及驱动)

7499663b04fdbbfebd.png


评论

———————————————— 版权声明:本文为CSDN博主「秋雯」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_51109735/article/details/110501560  发表于 2022-12-31 23:10
 楼主| 大鹏2365 发表于 2022-12-31 23:07 | 显示全部楼层
FreeRTOS是什么

我们看一下FreeRTOS的名字,可以分为两部分:Free和RTOS, Free 就是免费的、自由的、不受约束的意思,RTOS全称是Real Time Operating System,中文名就是实时操作系统。可以看出FreeROTS就是一个免费的RTOS类系统。这里要注意,RTOS不是指某-一个确定的系统,而是指一类系统。比如UCOS,FreeRTOS, RTX,RT-Thread 等这些都是RTOS类操作系统。
 楼主| 大鹏2365 发表于 2022-12-31 23:10 | 显示全部楼层
操作系统允许多个任务同时运行,这个叫做多任务,实际上,一个处理器核心在某一时刻只能运行一个任务。操作系统中任务调度器的责任就是决定在某一时刻究竟运行哪个任务,任务调度在各个任务之间的切换非常快!这就给人们造成了同一时刻有多个任务同时运行的错觉。操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分配同样的运行时间,时间到了就轮到下一个任务,Unix 操作系统就是这样的。RTOS 的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的,实时环境中要求操作系统必须对某一个事件做出实时的响应,因此系统任务调度器的行为必须是可预测的。像FreeRTOS这种传统的RTOS类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根据此优先级来决定下一刻应该运行哪个任务。
 楼主| 大鹏2365 发表于 2022-12-31 23:11 | 显示全部楼层
FreeRTOS是RTOS系统的- -种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,当然了,FreeRTOS不仅局限于在微控制器中使用。但从文件数量上来看FreeRTOS 要比UCOSII和UCOSIII小的多。
 楼主| 大鹏2365 发表于 2022-12-31 23:12 | 显示全部楼层
FreeRTOS移植到STM32上(MDK开发环境)

嫌麻烦跳到 程序编写 模块,不需要手动移植
 楼主| 大鹏2365 发表于 2022-12-31 23:13 | 显示全部楼层
下载FreeRTOS源代码

官网下载或者向你万能的老师要

2.前期准备

把FreeRTOS\Source\portable\RVDS目录下的ARM_CM3文件夹拷贝到FreeRTOS\Source\portable\Keil目录下
2210763b051789ec75.png
 楼主| 大鹏2365 发表于 2022-12-31 23:13 | 显示全部楼层
 楼主| 大鹏2365 发表于 2022-12-31 23:16 | 显示全部楼层
把FreeRTOS\Demo\CORTEX_STM32F103_IAR的FreeRTOSConfig.h文件拷贝到FreeRTOS\Source下
3323763b051af29011.png
3095263b051b6b3fc3.png
对源文件的处理就完成了
 楼主| 大鹏2365 发表于 2022-12-31 23:18 | 显示全部楼层
手动移植RreeRTOS

建立或打开一个MDK工程
5709063b0528e7bf19.png
 楼主| 大鹏2365 发表于 2022-12-31 23:18 | 显示全部楼层
添加FreeRTOS源文件
6676763b052c81ea49.png
 楼主| 大鹏2365 发表于 2022-12-31 23:19 | 显示全部楼层
源文件清单路径如下:
FreeRTOS\Source\list.c
FreeRTOS\Source\tasks.c
FreeRTOS\Source\portable\MemMang\heap_4.c
FreeRTOS\Source\FreeRTOSConfig.h
FreeRTOS\Source\event_groups.c
FreeRTOS\Source\croutine.c
FreeRTOS\Source\queue.c
FreeRTOS\Source\timers.c
FreeRTOS\Source\portable\Keil\ARM_CM3\port.c
 楼主| 大鹏2365 发表于 2022-12-31 23:19 | 显示全部楼层
添加头文件路径如下
3408863b05306ab048.png
 楼主| 大鹏2365 发表于 2022-12-31 23:20 | 显示全部楼层
修改stm32f10x_it.c文件:
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url]  This function handles SVCall exception.
  3.   * @param  None
  4.   * @retval None
  5.   */
  6. void SVC_Handler(void)
  7. {
  8. }

  9. /**
  10.   * @brief  This function handles Debug Monitor exception.
  11.   * @param  None
  12.   * @retval None
  13.   */
  14. void DebugMon_Handler(void)
  15. {
  16. }

  17. /**
  18.   * @brief  This function handles PendSVC exception.
  19.   * @param  None
  20.   * @retval None
  21.   */
  22. void PendSV_Handler(void)
  23. {
  24. }

  25. /**
  26.   * @brief  This function handles SysTick Handler.
  27.   * @param  None
  28.   * @retval None
  29.   */
  30. void SysTick_Handler(void)
  31. {
  32. }
 楼主| 大鹏2365 发表于 2022-12-31 23:21 | 显示全部楼层
此时FreeRTOS的手动移植基本完成,可以编写多任务程序了。
8576463b0536058c74.png
 楼主| 大鹏2365 发表于 2022-12-31 23:22 | 显示全部楼层
程序的编写

任务要求: 在STM32下完成一个基于FreeRTOS的多任务程序,执行2个周期性task,task1,每间隔500ms闪烁(变化)一次LED;task2,每间隔2000ms,向串口发送一次指令数据“helloworld!";
 楼主| 大鹏2365 发表于 2022-12-31 23:23 | 显示全部楼层
由于手动移植操作较为麻烦,而且很容易出现各种疑难杂症,因此我采用在野火官网下载已经移植好的系统,看看 RTOS里面的 API 使用说明,然后调用这些 API 实现自己想要的功能。
这种方式简单粗暴,不用关心底层的移植,这是最简单快速的入门方法。
此方法各有利弊,如果是做产品,好处是可以快速的实现功能,将产品推向市场,赢得先机。
弊端是当程序出现问题的时候,因对这个RTOS 不够了解,会导致调试困难,焦头烂额,一筹莫展。如果是学习,那么只会简单的调用 API,那是不可取的,我们应该深入的学习其中一款 RTOS。
如想深入了解的请自行移植并解决那些疑难杂症
 楼主| 大鹏2365 发表于 2022-12-31 23:23 | 显示全部楼层
程序如下
main.c
  1. #include "FreeRTOS.h"
  2. #include "task.h"
  3. #include "bsp_led.h"
  4. #include "bsp_usart.h"
  5. static TaskHandle_t AppTaskCreate_Handle = NULL;
  6. static TaskHandle_t LED1_Task_Handle = NULL;
  7. static TaskHandle_t LED2_Task_Handle = NULL;
  8. static void AppTaskCreate(void);

  9. static void LED1_Task(void* pvParameters);
  10. static void LED2_Task(void* pvParameters);

  11. static void BSP_Init(void);
  12. int main(void)
  13. {       
  14.   BaseType_t xReturn = pdPASS;
  15.   BSP_Init();

  16.   xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  
  17.                         (const char*    )"AppTaskCreate",
  18.                         (uint16_t       )512,
  19.                         (void*          )NULL,
  20.                         (UBaseType_t    )1,
  21.                         (TaskHandle_t*  )&AppTaskCreate_Handle);        
  22.   if(pdPASS == xReturn)
  23.     vTaskStartScheduler();
  24.   else
  25.     return -1;  
  26.   
  27.   while(1);     
  28. }

  29. static void AppTaskCreate(void)
  30. {
  31.   BaseType_t xReturn = pdPASS;
  32.   
  33.   taskENTER_CRITICAL();           
  34.   xReturn = xTaskCreate((TaskFunction_t )LED1_Task,
  35.                         (const char*    )"LED1_Task",
  36.                         (uint16_t       )512,
  37.                         (void*          )NULL,       
  38.                         (UBaseType_t    )2,          
  39.                         (TaskHandle_t*  )&LED1_Task_Handle);
  40.   if(pdPASS == xReturn)
  41.     printf("´´½¨LED1_TaskÈÎÎñ³É¹¦!\r\n");
  42.   xReturn = xTaskCreate((TaskFunction_t )LED2_Task,
  43.                         (const char*    )"LED2_Task",
  44.                         (uint16_t       )512,  
  45.                         (void*          )NULL,       
  46.                         (UBaseType_t    )3,            
  47.                         (TaskHandle_t*  )&LED2_Task_Handle);
  48.   if(pdPASS == xReturn)
  49.     printf("´´½¨LED2_TaskÈÎÎñ³É¹¦!\r\n");
  50.   
  51.   vTaskDelete(AppTaskCreate_Handle);
  52.   
  53.   taskEXIT_CRITICAL();         
  54. }
  55. static void LED1_Task(void* parameter)
  56. {       
  57.     while (1)
  58.     {
  59.         LED1_ON;
  60.         vTaskDelay(500);  
  61.         printf("LED1_Task Running,LED1_ON\r\n");
  62.         
  63.         LED1_OFF;     
  64.         vTaskDelay(500);                         
  65.         printf("LED1_Task Running,LED1_OFF\r\n");
  66.     }
  67. }
  68. static void LED2_Task(void* parameter)
  69. {       
  70.     while (1)
  71.     {

  72.         vTaskDelay(2000);  
  73.         printf("hello windows !! \r\n");
  74.     }
  75. }
  76. static void BSP_Init(void)
  77. {
  78.         NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
  79.         LED_GPIO_Config();
  80.         USART_Config();
  81. }

 楼主| 大鹏2365 发表于 2022-12-31 23:24 | 显示全部楼层
9337263b05414c9764.png
编译后烧录到stm32上
 楼主| 大鹏2365 发表于 2022-12-31 23:25 | 显示全部楼层
运行结果

这次采用的是stm32指南者开发板,用起来和核心板有些不同,主要是不需要ST-Link接口,转而使用串口进行程序的烧录,此时就需要下载一个串口驱动和串口工具软件,具体操作步骤移步 STM32串口通信
 楼主| 大鹏2365 发表于 2022-12-31 23:27 | 显示全部楼层
打开野火多功能调试助手,结果如下,运行成功
6334563b054edc77a6.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

702

帖子

0

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