你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32使用HAL库手动移植FreeRTOS10.4.1

[复制链接]
STMCU小助手 发布时间:2022-4-10 19:56
(一)裸机工程创建
使用STM32CubeMX创建裸机工程:

这里我是用的芯片是STM32F103RBT6,时钟主频为72MHz,配置时钟树:

[HJAIVR6Y8OGG98AS[H.png

配置调试串口1:

M8_G2}7WA8CT@ZUVG}0@R`0.png

配置两个LED灯:

20201010162500610.png

由于FreeRTOS使用系统嘀嗒定时器当作心跳,HAL库也使用了这个定时器当作超时计数用,FreeRTOS和HAL库不能同时使用SysTick定时器,所在在这里将HAL库的定时器改为其他的定时器,我改成了定时器4:

ZW]AZRZ6{KK3FJ9V~Y{}D~Q.png

配置中断,注意这里一定要选择组4,也就是全部为抢占优先级:

ANO~JLI_}E$E1]8B6U78I[X.png

输出工程:

20201010162753196.png
20201010162833214.png


(二)移植FreeRTOS

解压FreeRTOS源码包有如下文件结构:

7L$%8]J0YCQ2N2IE`HG1PJN.png

在Keil工程目录下新建FreeRTOS文件夹用于存放freertos的源码。

拷贝FreeRTOS/Source/文件夹内的以下文件,放入keil工程目录FreeRTOS文件夹内,效果如下图:

2~65A5@GXSM$QGGM2S885GU.png

在Keil中将FreeRTOS源码加入到工程内:

0]DPJOU3QX3U0ZAN46OSQ04.png

打开stm32f1xx_it.c文件,在头部添加FreeRTOS的三个函数导入:
  1. extern void xPortPendSVHandler(void);
  2. extern void xPortSysTickHandler(void);
  3. extern void vPortSVCHandler(void);
复制代码

3DC746)588]2)A%~F[L%ERS.png

在函数SVC_Handler中添加函数调用:

20201010165147723.png

在函数PendSV_Handler中添加函数调用:

20201010165237842.png

在函数SysTick_Handler中添加函数调用:

O[VQ{YF9{KZOLWVE[9O(OGN.png

新建一个名为FreeRTOSConfig.h的文件,这是FreeRTOS的配置文件,这里我贴一个我配置的:

  1. #ifndef FREERTOS_CONFIG_H__
  2. #define FREERTOS_CONFIG_H__

  3. /*

  4. */

  5. // 设置为1使用抢占式,为0使用时间片轮转调度。
  6. #define configUSE_PREEMPTION                    1

  7. // 设置为1使能低功耗tickless模式,为0保持系统节拍(tick)中断一直运行。
  8. #define configUSE_TICKLESS_IDLE                 0

  9. // 系统时钟主频
  10. #define configCPU_CLOCK_HZ                      72000000

  11. // 系统节拍中断的频率,即1s进中断的次数,配置为1000就是一秒进1000次中断,系统节拍就是1s。
  12. #define configTICK_RATE_HZ                      1000

  13. // 任务最大优先级,对于STM32来说最大不要超过32
  14. #define configMAX_PRIORITIES                    32

  15. // 任务最小栈大小
  16. #define configMINIMAL_STACK_SIZE                64

  17. // FreeRTOR堆空间大小
  18. #define configTOTAL_HEAP_SIZE                   8192

  19. // 任务名称最大长度
  20. #define configMAX_TASK_NAME_LEN                 16

  21. // 系统节拍计数器的变量类型,即定义portTickType是表示16位变量还是32位变量。
  22. #define configUSE_16_BIT_TICKS                  0

  23. // 设置为1允许任务调度,为0不允许(时间片耗尽才让出CPU使用权),该参数抢占式方式下才生效
  24. #define configIDLE_SHOULD_YIELD                 1

  25. // 设置是否使用互斥量
  26. #define configUSE_MUTEXES                       1

  27. // 设置是否使用递归互斥量
  28. #define configUSE_RECURSIVE_MUTEXES             0

  29. // 设置是否使用计数信号量
  30. #define configUSE_COUNTING_SEMAPHORES           0

  31. // 设置可以记录的队列和信号量的最大数目
  32. #define configQUEUE_REGISTRY_SIZE               10

  33. // 是否使用空闲钩子函数
  34. #define configUSE_IDLE_HOOK                     0

  35. // 是否使用TICK嘀嗒钩子函数
  36. #define configUSE_TICK_HOOK                     0

  37. // 是否使用栈溢出检查
  38. #define configCHECK_FOR_STACK_OVERFLOW          0

  39. // 是否使用内存申请失败钩子函数
  40. #define configUSE_MALLOC_FAILED_HOOK            0

  41. // 是否使用软件定时器
  42. #define configUSE_TIMERS                        1

  43. // 设置软件定时器服务/守护进程的优先级
  44. #define configTIMER_TASK_PRIORITY               3

  45. // 设置软件定时器命令队列的长度
  46. #define configTIMER_QUEUE_LENGTH                10

  47. // 设置软件定时器服务/守护进程任务的堆栈深度
  48. #define configTIMER_TASK_STACK_DEPTH            configMINIMAL_STACK_SIZE

  49. // STM32的最低优先级
  50. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15

  51. // 能够在中断服务函数中安全调用FreeRTOS API的中断最低优先级
  52. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1

  53. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << 4 )
  54. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << 4 )


  55. // 将以下定义设置为1以包含API函数,或设置为0排除API函数
  56. #define INCLUDE_vTaskPrioritySet                1
  57. #define INCLUDE_uxTaskPriorityGet               1
  58. #define INCLUDE_vTaskDelete                     1
  59. #define INCLUDE_vTaskSuspend                    1
  60. #define INCLUDE_xResumeFromISR                  1
  61. #define INCLUDE_vTaskDelayUntil                 1
  62. #define INCLUDE_vTaskDelay                      1
  63. #define INCLUDE_xTaskGetSchedulerState          1
  64. #define INCLUDE_xTaskGetCurrentTaskHandle       1
  65. #define INCLUDE_uxTaskGetStackHighWaterMark     0
  66. #define INCLUDE_xTaskGetIdleTaskHandle          0
  67. #define INCLUDE_xTimerGetTimerDaemonTaskHandle  0
  68. #define INCLUDE_pcTaskGetTaskName               0
  69. #define INCLUDE_eTaskGetState                   0
  70. #define INCLUDE_xEventGroupSetBitFromISR        1
  71. #define INCLUDE_xTimerPendFunctionCall          0

  72. #endif  /* FREERTOS_CONFIG_H__ */
复制代码

修改main.c文件,添加头文件:

  1. #include "FreeRTOSConfig.h"
  2. #include "FreeRTOS.h"
  3. #include "task.h"
复制代码

这里我创建了三个任务,任务一为led1灯每间隔500ms闪烁一次,任务二led2每间隔300ms闪烁一次,任务三为串口每隔1s打印一次helloworld。


  1. void led1_task(void* arg)
  2. {
  3.     while(1)
  4.     {
  5.         HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
  6.         vTaskDelay(500);
  7.     }
  8. }

  9. void led2_task(void* arg)
  10. {
  11.     while(1)
  12.     {
  13.         HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_2);
  14.         vTaskDelay(300);
  15.     }
  16. }

  17. void print_task(void* arg)
  18. {
  19.     while(1)
  20.     {
  21.         HAL_UART_Transmit(&huart1, (uint8_t *)"HelloWorld\r\n", 12, 100);
  22.         vTaskDelay(1000);
  23.     }
  24. }

  25. int main(void)
  26. {
  27.     HAL_Init();
  28.     SystemClock_Config();
  29.     MX_GPIO_Init();
  30.     MX_USART1_UART_Init();

  31.         // xTaskCreate函数参数说明:
  32.         // 1、任务入口函数
  33.         // 2、任务名称
  34.         // 3、堆栈大小,单位word
  35.         // 4、传递给任务的参数
  36.         // 5、任务优先级
  37.         // 6、任务句柄
  38.         
  39.         // 创建任务led1灯任务
  40.     xTaskCreate(led1_task, "led1_task", 64, NULL, 3, NULL);
  41.         
  42.         // 创建任务led2灯任务
  43.         xTaskCreate(led2_task, "led2_task", 64, NULL, 4, NULL);
  44.         
  45.         // 创建串口打印任务
  46.     xTaskCreate(print_task, "print_task", 128, NULL, 5, NULL);

  47.         // 启动任务调度
  48.     vTaskStartScheduler();

  49.     while (1)
  50.     {
  51.     }
  52. }
复制代码

到此,移植完毕!

总结:移植FreeRTOS还是相对简单的,主要是配置文件FreeRTOSConfig.h的配置,每个宏定义所代表的意思需要好好查阅!



收藏 评论0 发布时间:2022-4-10 19:56

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版