硬汉嵌入式论坛

 找回密码
 立即注册
查看: 7764|回复: 6
收起左侧

[FreeRTOS教程] 第5章 FreeRTOS操作系统移植(MDK版)

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2016-8-12 14:43:25 | 显示全部楼层 |阅读模式
第5章       FreeRTOS操作系统移植(MDK版)


      本章教程将为大家介绍基于MDK的FreeRTOS操作系统移植。移植工作比较简单,只需要用户添加需要的源码文件,不需要做任何的底层工作,再添加三个宏定义即可。
      本章教程含Cortex-M3内核的STM32F103的移植和Cortex-M4内核的STM32F407以及F429的移植。
    5.1 移植前准备工作说明
    5.2 STM32F103移植FreeRTOS系统
    5.3 STM32F407移植FreeRTOS系统
    5.4 STM32F429移植FreeRTOS系统
    5.5         总结



5.1  移植前准备工作说明

1.     本章节的IDE开发环境使用MDK,用MDK4.7X或者MDK5.XX均可,保证支持STM32F103,F407和F429即可(不可以使用MDK4.7X以下版本,一方面是不支持F429,另外就是FreeRTOS V8.2.3要用到C代码中嵌套汇编代码,MDK4.7X以下版本是不支持的)。
2.     找一个简单的工程,最好是跑马灯之类的,越简单越好,我们就在这个简单的工程上面移植即可。
3.     大家使用的简单工程里面不能有SysTick,PendSV和SVC三个系统中断的使用,因为FreeRTOS系统要使用这三个中断。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-12 14:51:33 | 显示全部楼层
5.2   STM32F103移植FreeRTOS系统

5.2.1      FreeRTOS操作系统移植

    首先准备好一个简单的裸机工程模板,工程模板的制作就不做讲解了,这里的重点是教大家移植FreeRTOS系统。准备好的工程模板如下图5.1所示(大家也可以制作其它任意的工程模板,不限制):
5.1.jpg
图5.1 工程模板

    准备好工程模板后,就可以开始移植了。首先要做的就是将所有需要的源码文件放到工程模板里面。下面分六步和大家进行说明,当然,不限制必须使用下面的方法添加源码到工程,只要将需要的文件添加到工程模板即可。
第1步:从网址https://sourceforge.net/projects/freertos/files/FreeRTOS/V8.2.3/ 下载V8.2.3版本,这个是8.X系列里面最高版本了,9.0版本还处于测试阶段,我们暂不使用。

FreeRTOSV8.2.3.zip和FreeRTOSV8.2.3.exe内容是一样的,只是后缀为exe的压缩率更高些。下载后解压出来。
5.2.jpg

第2步:在工程模板创建FreeRTOS文件夹
5.3.jpg

第3步:添加源码文件到相应文件夹
(1)将FreeRTOSV8.2.3软件包中路径:FreeRTOSV8.2.3\\FreeRTOS\\Source里面如下所有文件
    5.4.jpg

复制到刚刚创建的FreeRTOS文件夹下。
(2)文件夹User中还需要添加如下文件:
5.5.jpg

文件FreeRTOSConfig.h文件在FreeRTOSV8.2.3软件包中的中的路径:FreeRTOSV8.2.3\\FreeRTOS\\Demo\\CORTEX_STM32F103_Keil,其实就是官方整理好的配置文件。
(3):将源码文件添加到MDK的工程项目中,添加后的效果如下:
5.6.jpg

    其中heap_4.c文件路径: FreeRTOS\\Source\\portable\\MemMang
    port.c和portmacro.h文件的路径:FreeRTOS\\Source\\portable\\RVDS\\ARM_CM3,由于STM32F103是M3内核的,所以移植文件也要添加M3内核的。


第4步:新创建一个includes.h文件,将所有的头文件都集中到这个头文件下。
    这样做的好处是引用头文件的时候,只添加这个头文件就可以了。includes.h文件放在了User文件夹中。然后再将这个文件也添加到MDK工程项目中(将.h文件添加到工程的好处是方便查看和修改)
5.7.jpg

    Includes.h文件中的内容如下:
  1. /*
  2. *********************************************************************************************************
  3. *
  4. *    模块名称 : 头文件汇总
  5. *    文件名称 : includes.h
  6. *    版    本 : V1.0
  7. *    说    明 : 当前使用头文件汇总
  8. *
  9. *    修改记录 :
  10. *        版本号    日期        作者     说明
  11. *        V1.0    2015-08-02  Eric2013   首次发布
  12. *
  13. *    Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */
  17. #ifndef  __INCLUDES_H__
  18. #define  __INCLUDES_H__
  19. /*
  20. *********************************************************************************************************
  21. *                                         标准库
  22. *********************************************************************************************************
  23. */
  24. #include  <stdarg.h>
  25. #include  <stdio.h>
  26. #include  <stdlib.h>
  27. #include  <math.h>
  28. /*
  29. *********************************************************************************************************
  30. *                                         其它库
  31. *********************************************************************************************************
  32. */
  33. /*
  34. *********************************************************************************************************
  35. *                                           OS
  36. *********************************************************************************************************
  37. */
  38. #include "FreeRTOS.h"
  39. #include "task.h"
  40. #include "queue.h"
  41. #include "croutine.h"
  42. /*
  43. *********************************************************************************************************
  44. *                                           宏定义
  45. *********************************************************************************************************
  46. */
  47. /*
  48. *********************************************************************************************************
  49. *                                        APP / BSP
  50. *********************************************************************************************************
  51. */
  52. #include  <bsp.h>
  53. #endif
  54. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
第5步:添加相应的头文件路径,在原来工程模板的基础上新添加的两个路径:
5.8.jpg

第6步:最后一步,同时也是最重要的一步,修改FreeRTOSConfig.h配置文件(用户根据自己的配置进行修改,不修改也是没问题的我们这里进行修改主要是为了方便初学者学习),主要修改了以下两个方面:
    (1)添加宏定义__NVIC_PRIO_BITS,STM32系列产品优先级仅使用4位。
    (2)修改优先级相关的几个宏定义,具体修改了哪个可以对比原始文件查看。
    修改后在这个文件的末尾加上Systick,PendSV和SVC中断函数的宏定义,目的是将FreeRTOS移植文件port.c文件里面的中断服务程序映射到CMSIS定义的标准名称,这样就不需要用户去修改工程启动代码中这几个中断的名字了,很方便就实现了两个函数的统一。(移植过uCOS-II或者III的用户,对于这个问题估计深有体会,因为uCOS要修改启动文件,其实采用这里的方式更方便
  1. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  2. standard names. */
  3. #define vPortSVCHandler     SVC_Handler
  4. #define xPortPendSVHandler  PendSV_Handler
  5. #define xPortSysTickHandler SysTick_Handler
复制代码
其中vPortSVCHandler,xPortPendSVHandler和xPortSysTickHandler是在port.c文件里面定义的。SVC_Handler,PendSV_Handler和SysTick_Handler在startup_stm32f10x_hd.s文件里面进行了定义。
下面是FreeRTOSConfig.h配置文件的完整内容:
  1. #ifndef FREERTOS_CONFIG_H
  2. #define FREERTOS_CONFIG_H
  3. /*-----------------------------------------------------------
  4. * Application specific definitions.
  5. *
  6. * These definitions should be adjusted for your particular hardware and
  7. * application requirements.
  8. *
  9. * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
  10. * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
  11. *
  12. * See http://www.freertos.org/a00110.html.
  13. *----------------------------------------------------------*/
  14. #define configUSE_PREEMPTION         1
  15. #define configUSE_IDLE_HOOK          0
  16. #define configUSE_TICK_HOOK          0
  17. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 72000000 )  
  18. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  19. #define configMAX_PRIORITIES         ( 5 )
  20. #define configMINIMAL_STACK_SIZE      ( ( unsigned short ) 128 )
  21. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  22. #define configMAX_TASK_NAME_LEN      ( 16 )
  23. #define configUSE_TRACE_FACILITY      0
  24. #define configUSE_16_BIT_TICKS       0
  25. #define configIDLE_SHOULD_YIELD      1
  26. /* Co-routine definitions. */
  27. #define configUSE_CO_ROUTINES            0
  28. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  29. /* Set the following definitions to 1 to include the API function, or zero
  30. to exclude the API function. */
  31. #define INCLUDE_vTaskPrioritySet          1
  32. #define INCLUDE_uxTaskPriorityGet         1
  33. #define INCLUDE_vTaskDelete               1
  34. #define INCLUDE_vTaskCleanUpResources      0
  35. #define INCLUDE_vTaskSuspend              1
  36. #define INCLUDE_vTaskDelayUntil           1
  37. #define INCLUDE_vTaskDelay                1
  38. /* Cortex-M specific definitions. */
  39. #ifdef __NVIC_PRIO_BITS
  40.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  41.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  42. #else
  43.      #define configPRIO_BITS              4        /* 15 priority levels */
  44. #endif
  45. /* The lowest interrupt priority that can be used in a call to a "set priority"
  46. function. */
  47. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       0x0f
  48. /* The highest interrupt priority that can be used by any interrupt service
  49. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  50. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  51. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  52. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
  53. /* Interrupt priorities used by the kernel port layer itself.  These are generic
  54. to all Cortex-M ports, and do not rely on any particular library functions. */
  55. #define configKERNEL_INTERRUPT_PRIORITY        ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  56. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
  57. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
  58. #define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  59.    
  60. /* Normal assert() semantics without relying on the provision of an assert.h
  61. header file. */
  62. #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
  63.    
  64. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  65. standard names. */
  66. #define vPortSVCHandler SVC_Handler
  67. #define xPortPendSVHandler PendSV_Handler
  68. #define xPortSysTickHandler SysTick_Handler
  69. #endif /* FREERTOS_CONFIG_H */
复制代码
    至此,FreeRTOS的移植工作就完成了,剩下就是系统配置和应用了。其中系统配置,会在第7章专门进行讲解。

5.2.2     FreeRTOS操作系统应用实例

    FreeRTOSConfig.h配置文件里面几个重要选项说明:
1、#define configUSE_PREEMPTION        1
    使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 72000000 )   
    系统主频72MHz。
3、#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
    系统时钟节拍1KHz,即1ms。
4、#define configMAX_PRIORITIES          ( 5 )
       定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
5、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
    定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
---------------------------------------------------------------------------------------------------
      经过上面的移植和配置之后,在main.c文件中添加如下代码,代码中简单地创建了四个用户任务:
vTaskTaskUserIF任务:接口消息处理,这里用作LED闪烁。
AppTaskLED任务    :LED闪烁。
vTaskMsgPro 任务  :消息处理,这里用作LED闪烁。
AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现LED闪烁。
  1. #include "includes.h"
  2. /*
  3. **********************************************************************************************************
  4.                                                    函数声明
  5. **********************************************************************************************************
  6. */
  7. static void vTaskTaskUserIF(void *pvParameters);
  8. static void vTaskLED(void *pvParameters);
  9. static void vTaskMsgPro(void *pvParameters);
  10. static void vTaskStart(void *pvParameters);
  11. static void AppTaskCreate (void);
  12. /*
  13. **********************************************************************************************************
  14.                                                    变量声明
  15. **********************************************************************************************************
  16. */
  17. static TaskHandle_t xHandleTaskUserIF = NULL;
  18. static TaskHandle_t xHandleTaskLED = NULL;
  19. static TaskHandle_t xHandleTaskMsgPro = NULL;
  20. static TaskHandle_t xHandleTaskStart = NULL;
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: main
  24. *    功能说明: 标准c程序入口。
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. int main(void)
  30. {
  31.      /*
  32.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  33.        这样做的好处是:
  34.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  35.        2. 保证系统正常启动,不受别的中断影响。
  36.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  37.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  38.        和cpsie i是等效的。
  39.      */
  40.      __set_PRIMASK(1);
  41.    
  42.      /* 硬件初始化 */
  43.      bsp_Init();
  44.    
  45.      /* 创建任务 */
  46.      AppTaskCreate();
  47.    
  48.     /* 启动调度,开始执行任务 */
  49.     vTaskStartScheduler();
  50.      /*
  51.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  52.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  53.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  54.      */
  55.      while(1);
  56. }
  57. /*
  58. *********************************************************************************************************
  59. *    函 数 名: vTaskTaskUserIF
  60. *    功能说明: 接口消息处理,这里用作LED闪烁
  61. *    形    参: pvParameters 是在创建该任务时传递的形参
  62. *    返 回 值: 无
  63. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  64. *********************************************************************************************************
  65. */
  66. static void vTaskTaskUserIF(void *pvParameters)
  67. {
  68.     while(1)
  69.     {
  70.          bsp_LedToggle(1);
  71.          vTaskDelay(100);
  72.      }
  73. }
  74. /*
  75. *********************************************************************************************************
  76. *    函 数 名: vTaskLED
  77. *    功能说明: LED闪烁
  78. *    形    参: pvParameters 是在创建该任务时传递的形参
  79. *    返 回 值: 无
  80. *   优 先 级: 2
  81. *********************************************************************************************************
  82. */
  83. static void vTaskLED(void *pvParameters)
  84. {
  85.     while(1)
  86.     {
  87.          bsp_LedToggle(2);
  88.         vTaskDelay(200);
  89.     }
  90. }
  91. /*
  92. *********************************************************************************************************
  93. *    函 数 名: vTaskMsgPro
  94. *    功能说明: 信息处理,这里是用作LED闪烁   
  95. *    形    参: pvParameters 是在创建该任务时传递的形参
  96. *    返 回 值: 无
  97. *   优 先 级: 3
  98. *********************************************************************************************************
  99. */
  100. static void vTaskMsgPro(void *pvParameters)
  101. {
  102.     while(1)
  103.     {
  104.          bsp_LedToggle(3);
  105.         vTaskDelay(300);
  106.     }
  107. }
  108. /*
  109. *********************************************************************************************************
  110. *    函 数 名: vTaskStart
  111. *    功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
  112. *    形    参: pvParameters 是在创建该任务时传递的形参
  113. *    返 回 值: 无
  114. *   优 先 级: 4
  115. *********************************************************************************************************
  116. */
  117. static void vTaskStart(void *pvParameters)
  118. {
  119.     while(1)
  120.     {
  121.          /* LED闪烁 */
  122.          bsp_LedToggle(4);
  123.         vTaskDelay(400);
  124.     }
  125. }
  126. /*
  127. *********************************************************************************************************
  128. *    函 数 名: AppTaskCreate
  129. *    功能说明: 创建应用任务
  130. *    形    参: 无
  131. *    返 回 值: 无
  132. *********************************************************************************************************
  133. */
  134. static void AppTaskCreate (void)
  135. {
  136.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  137.                  "vTaskUserIF",     /* 任务名    */
  138.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  139.                  NULL,              /* 任务参数  */
  140.                  1,                 /* 任务优先级*/
  141.                  &xHandleTaskUserIF );  /* 任务句柄  */
  142.    
  143.    
  144.      xTaskCreate( vTaskLED,           /* 任务函数  */
  145.                  "vTaskLED",         /* 任务名    */
  146.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  147.                  NULL,               /* 任务参数  */
  148.                  2,                  /* 任务优先级*/
  149.                  &xHandleTaskLED ); /* 任务句柄  */
  150.    
  151.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  152.                  "vTaskMsgPro",           /* 任务名    */
  153.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  154.                  NULL,                    /* 任务参数  */
  155.                  3,                       /* 任务优先级*/
  156.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  157.    
  158.    
  159.      xTaskCreate( vTaskStart,             /* 任务函数  */
  160.                  "vTaskStart",            /* 任务名    */
  161.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  162.                  NULL,                    /* 任务参数  */
  163.                  4,                       /* 任务优先级*/
  164.                  &xHandleTaskStart );   /* 任务句柄  */
  165. }
  166. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
除了创建的4个用户任务以外,还有空闲任务,这个任务是系统创建的。至此,FreeRTOS的工程就可以运行了,可以看到4个LED在闪烁。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-12 15:00:24 | 显示全部楼层
5.3  STM32F407移植FreeRTOS系统


5.3.1     FreeRTOS操作系统移植

    首先准备好一个简单的裸机工程模板,工程模板的制作就不做讲解了,这里的重点是教大家移植FreeRTOS系统。准备好的工程模板如下图5.2所示(大家也可以制作其它任意的工程模板,不限制):
5.9.jpg
图5.2 工程模板

    准备好工程模板后,就可以开始移植了。首先要做的就是将所有需要的源码文件放到工程模板里面。下面分六步为大家进行说明,当然,不限制必须使用下面的方法添加源码到工程,只要将需要的文件添加到工程模板即可。
第1步:从网址https://sourceforge.net/projects/freertos/files/FreeRTOS/V8.2.3/ 下载V8.2.3版本,这个是8.X系列里面最高版本了,9.0版本还处于测试阶段,我们暂不使用。

FreeRTOSV8.2.3.zip和FreeRTOSV8.2.3.exe内容是一样的,只是后缀为exe的压缩率更高些。下载后解压出来。
5.10.jpg

第2步:在工程模板创建FreeRTOS文件夹
5.11.jpg

第3步:添加源码文件到相应文件夹
(1)将FreeRTOSV8.2.3软件包中路径:FreeRTOSV8.2.3\\FreeRTOS\\Source里面如下所有文件
5.12.jpg

    复制到刚刚创建的FreeRTOS文件夹下。
(2)文件夹User中还需要添加如下文件:
5.13.jpg

    文件FreeRTOSConfig.h文件在FreeRTOSV8.2.3软件包中的中的路径:FreeRTOSV8.2.3\\FreeRTOS\\Demo\\CORTEX_M4F_STM32F407ZG-SK,其实就是官方整理好的配置文件。
第3步:将源码文件添加到MDK的工程项目中,添加后的效果如下:
5.14.jpg

    其中heap_4.c文件路径:FreeRTOS\\Source\\portable\\MemMang
    port.c和portmacro.h文件的路径:FreeRTOS\\ Source\\portable\\RVDS\\ARM_CM4F,由于STM32F407是M4内核的,所以移植文件也要添加M4内核的。
第4步:新创建一个includes.h文件,将所有的头文件都集中到这个头文件下。
    这样做的好处是引用头文件的时候,只添加这个头文件就可以了。includes.h文件放在了User文件夹中。然后再将这个文件也添加到MDK工程项目中(将.h文件添加到工程的好处是方便查看和修改)
5.15.jpg

    Includes.h文件中的内容如下:/*
  1. /*
  2. *********************************************************************************************************
  3. *
  4. *    模块名称 : 头文件汇总
  5. *    文件名称 : includes.h
  6. *    版    本 : V1.0
  7. *    说    明 : 当前使用头文件汇总
  8. *
  9. *    修改记录 :
  10. *        版本号    日期        作者     说明
  11. *        V1.0    2015-08-02  Eric2013   首次发布
  12. *
  13. *    Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */
  17. #ifndef  __INCLUDES_H__
  18. #define  __INCLUDES_H__
  19. /*
  20. *********************************************************************************************************
  21. *                                         标准库
  22. *********************************************************************************************************
  23. */
  24. #include  <stdarg.h>
  25. #include  <stdio.h>
  26. #include  <stdlib.h>
  27. #include  <math.h>
  28. /*
  29. *********************************************************************************************************
  30. *                                         其它库
  31. *********************************************************************************************************
  32. */
  33. /*
  34. *********************************************************************************************************
  35. *                                           OS
  36. *********************************************************************************************************
  37. */
  38. #include "FreeRTOS.h"
  39. #include "task.h"
  40. #include "queue.h"
  41. #include "croutine.h"
  42. /*
  43. *********************************************************************************************************
  44. *                                           宏定义
  45. *********************************************************************************************************
  46. */
  47. /*
  48. *********************************************************************************************************
  49. *                                        APP / BSP
  50. *********************************************************************************************************
  51. */
  52. #include  <bsp.h>
  53. #endif
  54. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
第5步:添加相应的头文件路径,在原来工程模板的基础上新添加的两个路径:
5.16.jpg

第6步:最后一步,同时也是最重要的一步,修改FreeRTOSConfig.h配置文件(用户根据自己的配置进行修改,不修改也是没问题的我们这里进行修改主要是为了方便初学者学习),主要修改了以下两个方面:
    (1)添加宏定义__NVIC_PRIO_BITS,STM32系列产品优先级仅使用4位。
    (2)修改优先级相关的几个宏定义,具体修改了哪个可以对比原始文件查看。
    修改后在这个文件的末尾加上Systick,PendSV和SVC中断函数的宏定义,目的是将FreeRTOS移植文件port.c文件里面的中断服务程序映射到CMSIS定义的标准名称,这样就不需要用户去修改工程启动代码中这几个中断的名字了,很方便就实现了两个函数的统一。(移植过uCOS-II或者III的用户,对于这个问题估计深有体会,因为uCOS要修改启动文件,其实采用这里的方式更方便
  1. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  2. standard names. */
  3. #define vPortSVCHandler     SVC_Handler
  4. #define xPortPendSVHandler  PendSV_Handler
  5. #define xPortSysTickHandler SysTick_Handler
复制代码
其中vPortSVCHandler,xPortPendSVHandler和xPortSysTickHandler是在port.c文件里面定义的。SVC_Handler,PendSV_Handler和SysTick_Handler在startup_stm32f10x_hd.s文件里面进行了定义。
下面是FreeRTOSConfig.h配置文件的完整内容:
  1. #ifndef FREERTOS_CONFIG_H
  2. #define FREERTOS_CONFIG_H
  3. /*-----------------------------------------------------------
  4. * Application specific definitions.
  5. *
  6. * These definitions should be adjusted for your particular hardware and
  7. * application requirements.
  8. *
  9. * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
  10. * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
  11. *
  12. * See http://www.freertos.org/a00110.html.
  13. *----------------------------------------------------------*/
  14. #define configUSE_PREEMPTION         1
  15. #define configUSE_IDLE_HOOK          0
  16. #define configUSE_TICK_HOOK          0
  17. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  18. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  19. #define configMAX_PRIORITIES         ( 5 )
  20. #define configMINIMAL_STACK_SIZE      ( ( unsigned short ) 128 )
  21. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  22. #define configMAX_TASK_NAME_LEN      ( 16 )
  23. #define configUSE_TRACE_FACILITY      0
  24. #define configUSE_16_BIT_TICKS       0
  25. #define configIDLE_SHOULD_YIELD      1
  26. /* Co-routine definitions. */
  27. #define configUSE_CO_ROUTINES            0
  28. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  29. /* Set the following definitions to 1 to include the API function, or zero
  30. to exclude the API function. */
  31. #define INCLUDE_vTaskPrioritySet          1
  32. #define INCLUDE_uxTaskPriorityGet         1
  33. #define INCLUDE_vTaskDelete               1
  34. #define INCLUDE_vTaskCleanUpResources      0
  35. #define INCLUDE_vTaskSuspend              1
  36. #define INCLUDE_vTaskDelayUntil           1
  37. #define INCLUDE_vTaskDelay                1
  38. /* Cortex-M specific definitions. */
  39. #ifdef __NVIC_PRIO_BITS
  40.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  41.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  42. #else
  43.      #define configPRIO_BITS              4        /* 15 priority levels */
  44. #endif
  45. /* The lowest interrupt priority that can be used in a call to a "set priority"
  46. function. */
  47. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       0x0f
  48. /* The highest interrupt priority that can be used by any interrupt service
  49. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  50. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  51. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  52. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
  53. /* Interrupt priorities used by the kernel port layer itself.  These are generic
  54. to all Cortex-M ports, and do not rely on any particular library functions. */
  55. #define configKERNEL_INTERRUPT_PRIORITY        ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  56. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
  57. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
  58. #define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  59.    
  60. /* Normal assert() semantics without relying on the provision of an assert.h
  61. header file. */
  62. #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
  63.    
  64. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  65. standard names. */
  66. #define vPortSVCHandler SVC_Handler
  67. #define xPortPendSVHandler PendSV_Handler
  68. #define xPortSysTickHandler SysTick_Handler
  69. #endif /* FREERTOS_CONFIG_H */
复制代码
    至此,FreeRTOS的移植工作就完成了,剩下就是系统配置和应用了。其中系统配置,会在第7章专门进行讲解。

5.3.2     FreeRTOS操作系统应用实例


    FreeRTOSConfig.h配置文件里面几个重要选项说明:
1、#define configUSE_PREEMPTION        1
    使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
    系统主频168MHz。
3、#define configTICK_RATE_HZ                     ( ( TickType_t ) 1000 )
    系统时钟节拍1KHz,即1ms。
4、#define configMAX_PRIORITIES          ( 5 )
    定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
5、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
    定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
---------------------------------------------------------------------------------------------------
    经过上面的移植和配置之后,在main.c文件中添加如下代码,代码中简单的创建了四个用户任务:
vTaskTaskUserIF任务:接口消息处理,这里用作LED闪烁。
AppTaskLED任务    :LED闪烁。
vTaskMsgPro 任务  :消息处理,这里用作LED闪烁。
AppTaskStart任务  :启动任务,也是最高优先级任务,这里实现LED闪烁。
  1. #include "includes.h"
  2. /*
  3. **********************************************************************************************************
  4.                                                    函数声明
  5. **********************************************************************************************************
  6. */
  7. static void vTaskTaskUserIF(void *pvParameters);
  8. static void vTaskLED(void *pvParameters);
  9. static void vTaskMsgPro(void *pvParameters);
  10. static void vTaskStart(void *pvParameters);
  11. static void AppTaskCreate (void);
  12. /*
  13. **********************************************************************************************************
  14.                                                    变量声明
  15. **********************************************************************************************************
  16. */
  17. static TaskHandle_t xHandleTaskUserIF = NULL;
  18. static TaskHandle_t xHandleTaskLED = NULL;
  19. static TaskHandle_t xHandleTaskMsgPro = NULL;
  20. static TaskHandle_t xHandleTaskStart = NULL;
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: main
  24. *    功能说明: 标准c程序入口。
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. int main(void)
  30. {
  31.      /*
  32.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  33.        这样做的好处是:
  34.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  35.        2. 保证系统正常启动,不受别的中断影响。
  36.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  37.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  38.        和cpsie i是等效的。
  39.      */
  40.      __set_PRIMASK(1);
  41.    
  42.      /* 硬件初始化 */
  43.      bsp_Init();
  44.    
  45.      /* 创建任务 */
  46.      AppTaskCreate();
  47.    
  48.     /* 启动调度,开始执行任务 */
  49.     vTaskStartScheduler();
  50.      /*
  51.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  52.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  53.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  54.      */
  55.      while(1);
  56. }
  57. /*
  58. *********************************************************************************************************
  59. *    函 数 名: vTaskTaskUserIF
  60. *    功能说明: 接口消息处理,这里用作LED闪烁
  61. *    形    参: pvParameters 是在创建该任务时传递的形参
  62. *    返 回 值: 无
  63. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  64. *********************************************************************************************************
  65. */
  66. static void vTaskTaskUserIF(void *pvParameters)
  67. {
  68.     while(1)
  69.     {
  70.          bsp_LedToggle(1);
  71.          vTaskDelay(100);
  72.      }
  73. }
  74. /*
  75. *********************************************************************************************************
  76. *    函 数 名: vTaskLED
  77. *    功能说明: LED闪烁
  78. *    形    参: pvParameters 是在创建该任务时传递的形参
  79. *    返 回 值: 无
  80. *   优 先 级: 2
  81. *********************************************************************************************************
  82. */
  83. static void vTaskLED(void *pvParameters)
  84. {
  85.     while(1)
  86.     {
  87.          bsp_LedToggle(2);
  88.         vTaskDelay(200);
  89.     }
  90. }
  91. /*
  92. *********************************************************************************************************
  93. *    函 数 名: vTaskMsgPro
  94. *    功能说明: 信息处理,这里是用作LED闪烁   
  95. *    形    参: pvParameters 是在创建该任务时传递的形参
  96. *    返 回 值: 无
  97. *   优 先 级: 3
  98. *********************************************************************************************************
  99. */
  100. static void vTaskMsgPro(void *pvParameters)
  101. {
  102.     while(1)
  103.     {
  104.          bsp_LedToggle(3);
  105.         vTaskDelay(300);
  106.     }
  107. }
  108. /*
  109. *********************************************************************************************************
  110. *    函 数 名: vTaskStart
  111. *    功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
  112. *    形    参: pvParameters 是在创建该任务时传递的形参
  113. *    返 回 值: 无
  114. *   优 先 级: 4
  115. *********************************************************************************************************
  116. */
  117. static void vTaskStart(void *pvParameters)
  118. {
  119.     while(1)
  120.     {
  121.          /* LED闪烁 */
  122.          bsp_LedToggle(4);
  123.         vTaskDelay(400);
  124.     }
  125. }
  126. /*
  127. *********************************************************************************************************
  128. *    函 数 名: AppTaskCreate
  129. *    功能说明: 创建应用任务
  130. *    形    参: 无
  131. *    返 回 值: 无
  132. *********************************************************************************************************
  133. */
  134. static void AppTaskCreate (void)
  135. {
  136.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  137.                  "vTaskUserIF",     /* 任务名    */
  138.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  139.                  NULL,              /* 任务参数  */
  140.                  1,                  /* 任务优先级*/
  141.                  &xHandleTaskUserIF );  /* 任务句柄  */
  142.    
  143.    
  144.      xTaskCreate( vTaskLED,           /* 任务函数  */
  145.                  "vTaskLED",         /* 任务名    */
  146.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  147.                  NULL,               /* 任务参数  */
  148.                  2,                  /* 任务优先级*/
  149.                  &xHandleTaskLED ); /* 任务句柄  */
  150.    
  151.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  152.                  "vTaskMsgPro",           /* 任务名    */
  153.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  154.                  NULL,                    /* 任务参数  */
  155.                  3,                       /* 任务优先级*/
  156.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  157.    
  158.    
  159.      xTaskCreate( vTaskStart,             /* 任务函数  */
  160.                  "vTaskStart",            /* 任务名    */
  161.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  162.                  NULL,                    /* 任务参数  */
  163.                  4,                       /* 任务优先级*/
  164.                  &xHandleTaskStart );   /* 任务句柄  */
  165. }
  166. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
除了创建的4个用户任务以外,还有空闲任务,这个任务是系统创建的。至此,FreeRTOS的工程就可以运行了。可以看到4个LED在闪烁。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-12 15:08:15 | 显示全部楼层
5.4  STM32F429移植FreeRTOS系统


5.4.1     FreeRTOS操作系统移植

    首先准备好一个简单的裸机工程模板,工程模板的制作就不做讲解了,这里的重点是教大家移植FreeRTOS系统。准备好的工程模板如下图5.3所示(大家也可以制作其它任意的工程模板,不限制):
5.17.jpg
图5.3 工程模板

    准备好工程模板后,就可以开始移植了。首先要做的就是将所有需要的源码文件放到工程模板里面。下面分六步和大家进行说明,当然,不限制必须使用下面的方法添加源码到工程,只要将需要的文件添加到工程模板即可。
第1步:从网址https://sourceforge.net/projects/freertos/files/FreeRTOS/V8.2.3/ 下载V8.2.3版本,这个是8.X系列里面最高版本了,9.0版本还处于测试阶段,我们暂不使用。
5.18.jpg

FreeRTOSV8.2.3.zip和FreeRTOSV8.2.3.exe内容是一样的,只是后缀为exe的压缩率更高些。下载后解压出来。
第2步:在工程模板创建FreeRTOS文件夹
5.19.jpg

第3步:添加源码文件到相应文件夹
(1)将FreeRTOSV8.2.3软件包中路径:FreeRTOSV8.2.3\\FreeRTOS\\Source里面如下所有文件
5.20.jpg

    复制到刚刚创建的FreeRTOS文件夹下。
(2)文件夹User中还需要添加如下文件:
5.21.jpg

    文件FreeRTOSConfig.h文件在FreeRTOSV8.2.3软件包中的中的路径:
    FreeRTOSV8.2.3\\ FreeRTOS\\Demo\\CORTEX_M4F_STM32F407ZG-SK,其实就是官方整理好的配置文件(官方没有F429的例子,使用F407的即可,配置是相同的)。
第3步:将源码文件添加到MDK的工程项目中
    添加后的效果如下:
5.22.jpg

    其中heap_4.c文件路径:FreeRTOS\\Source\\portable\\MemMang
    port.c和portmacro.h文件的路径:FreeRTOS\\ Source\\portable\\RVDS\\ARM_CM4F,由于STM32F429是M4内核的,所以移植文件也要添加M4内核的。
第4步:新创建一个includes.h文件,将所有的头文件都集中到这个头文件下。
    这样做的好处是引用头文件的时候,只添加这个头文件就可以了。includes.h文件放在了User文件夹中。然后再将这个文件也添加到MDK工程项目中(将.h文件添加到工程的好处是方便查看和修改)
5.23.jpg

    Includes.h文件中的内容如下:/*
  1. /*
  2. *********************************************************************************************************
  3. *
  4. *    模块名称 : 头文件汇总
  5. *    文件名称 : includes.h
  6. *    版    本 : V1.0
  7. *    说    明 : 当前使用头文件汇总
  8. *
  9. *    修改记录 :
  10. *        版本号    日期        作者     说明
  11. *        V1.0    2015-08-02  Eric2013   首次发布
  12. *
  13. *    Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */
  17. #ifndef  __INCLUDES_H__
  18. #define  __INCLUDES_H__
  19. /*
  20. *********************************************************************************************************
  21. *                                         标准库
  22. *********************************************************************************************************
  23. */
  24. #include  <stdarg.h>
  25. #include  <stdio.h>
  26. #include  <stdlib.h>
  27. #include  <math.h>
  28. /*
  29. *********************************************************************************************************
  30. *                                         其它库
  31. *********************************************************************************************************
  32. */
  33. /*
  34. *********************************************************************************************************
  35. *                                           OS
  36. *********************************************************************************************************
  37. */
  38. #include "FreeRTOS.h"
  39. #include "task.h"
  40. #include "queue.h"
  41. #include "croutine.h"
  42. /*
  43. *********************************************************************************************************
  44. *                                           宏定义
  45. *********************************************************************************************************
  46. */
  47. /*
  48. *********************************************************************************************************
  49. *                                        APP / BSP
  50. *********************************************************************************************************
  51. */
  52. #include  <bsp.h>
  53. #endif
  54. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
第5步:添加相应的头文件路径,在原来工程模板的基础上新添加的两个路径:
5.24.jpg

第6步:最后一步,同时也是最重要的一步,修改FreeRTOSConfig.h配置文件(用户根据自己的配置进行修改,不修改也是没问题的我们这里进行修改主要是为了方便初学者学习),主要修改了以下两个方面:
(1)添加宏定义__NVIC_PRIO_BITS,STM32系列产品优先级仅使用4位。
(2)修改优先级相关的几个宏定义,具体修改了哪个可以对比原始文件查看。
    修改后在这个文件的末尾加上Systick,PendSV和SVC中断函数的宏定义,目的是将FreeRTOS移植文件port.c文件里面的中断服务程序映射到CMSIS定义的标准名称,这样就不需要用户去修改工程启动代码中这几个中断的名字了,很方便就实现了两个函数的统一。(移植过uCOS-II或者III的用户,对于这个问题估计深有体会,因为uCOS要修改启动文件,其实采用这里的方式更方便
  1. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  2. standard names. */
  3. #define vPortSVCHandler     SVC_Handler
  4. #define xPortPendSVHandler  PendSV_Handler
  5. #define xPortSysTickHandler SysTick_Handler
复制代码
其中vPortSVCHandler,xPortPendSVHandler和xPortSysTickHandler是在port.c文件里面定义的。SVC_Handler,PendSV_Handler和SysTick_Handler在startup_stm32f10x_hd.s文件里面进行了定义。
下面是FreeRTOSConfig.h配置文件的完整内容:
  1. #ifndef FREERTOS_CONFIG_H
  2. #define FREERTOS_CONFIG_H
  3. /*-----------------------------------------------------------
  4. * Application specific definitions.
  5. *
  6. * These definitions should be adjusted for your particular hardware and
  7. * application requirements.
  8. *
  9. * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
  10. * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
  11. *
  12. * See http://www.freertos.org/a00110.html.
  13. *----------------------------------------------------------*/
  14. #define configUSE_PREEMPTION         1
  15. #define configUSE_IDLE_HOOK          0
  16. #define configUSE_TICK_HOOK          0
  17. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  18. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  19. #define configMAX_PRIORITIES         ( 5 )
  20. #define configMINIMAL_STACK_SIZE      ( ( unsigned short ) 128 )
  21. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  22. #define configMAX_TASK_NAME_LEN      ( 16 )
  23. #define configUSE_TRACE_FACILITY      0
  24. #define configUSE_16_BIT_TICKS       0
  25. #define configIDLE_SHOULD_YIELD      1
  26. /* Co-routine definitions. */
  27. #define configUSE_CO_ROUTINES            0
  28. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  29. /* Set the following definitions to 1 to include the API function, or zero
  30. to exclude the API function. */
  31. #define INCLUDE_vTaskPrioritySet          1
  32. #define INCLUDE_uxTaskPriorityGet         1
  33. #define INCLUDE_vTaskDelete               1
  34. #define INCLUDE_vTaskCleanUpResources      0
  35. #define INCLUDE_vTaskSuspend              1
  36. #define INCLUDE_vTaskDelayUntil           1
  37. #define INCLUDE_vTaskDelay                1
  38. /* Cortex-M specific definitions. */
  39. #ifdef __NVIC_PRIO_BITS
  40.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  41.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  42. #else
  43.      #define configPRIO_BITS              4        /* 15 priority levels */
  44. #endif
  45. /* The lowest interrupt priority that can be used in a call to a "set priority"
  46. function. */
  47. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       0x0f
  48. /* The highest interrupt priority that can be used by any interrupt service
  49. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  50. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  51. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  52. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
  53. /* Interrupt priorities used by the kernel port layer itself.  These are generic
  54. to all Cortex-M ports, and do not rely on any particular library functions. */
  55. #define configKERNEL_INTERRUPT_PRIORITY        ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  56. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
  57. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
  58. #define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
  59.    
  60. /* Normal assert() semantics without relying on the provision of an assert.h
  61. header file. */
  62. #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
  63.    
  64. /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
  65. standard names. */
  66. #define vPortSVCHandler SVC_Handler
  67. #define xPortPendSVHandler PendSV_Handler
  68. #define xPortSysTickHandler SysTick_Handler
  69. #endif /* FREERTOS_CONFIG_H */
复制代码
    至此,FreeRTOS的移植工作就完成了,剩下就是系统配置和应用了。其中系统配置,会在第7章专门进行讲解。

5.4.2     FreeRTOS操作系统应用实例


    FreeRTOSConfig.h配置文件里面几个重要选项说明:
1、#define configUSE_PREEMPTION        1
    使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )  
    系统主频168MHz。
3、#define configTICK_RATE_HZ                     ( ( TickType_t ) 1000 )
    系统时钟节拍1KHz,即1ms。
5、#define configMAX_PRIORITIES          ( 5 )
    定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
6、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
    定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
---------------------------------------------------------------------------------------------------
    经过上面的移植和配置之后,在main.c文件中添加如下代码,代码中简单的创建了四个用户任务:
vTaskTaskUserIF任务:接口消息处理,这里用作LED闪烁。
AppTaskLED任务 :LED闪烁。
vTaskMsgPro任务:消息处理,这里用作LED闪烁。
AppTaskStart任务:启动任务,也是最高优先级任务,这里实现LED闪烁。
  1. #include "includes.h"
  2. /*
  3. **********************************************************************************************************
  4.                                                    函数声明
  5. **********************************************************************************************************
  6. */
  7. static void vTaskTaskUserIF(void *pvParameters);
  8. static void vTaskLED(void *pvParameters);
  9. static void vTaskMsgPro(void *pvParameters);
  10. static void vTaskStart(void *pvParameters);
  11. static void AppTaskCreate (void);
  12. /*
  13. **********************************************************************************************************
  14.                                                    变量声明
  15. **********************************************************************************************************
  16. */
  17. static TaskHandle_t xHandleTaskUserIF = NULL;
  18. static TaskHandle_t xHandleTaskLED = NULL;
  19. static TaskHandle_t xHandleTaskMsgPro = NULL;
  20. static TaskHandle_t xHandleTaskStart = NULL;
  21. /*
  22. *********************************************************************************************************
  23. *    函 数 名: main
  24. *    功能说明: 标准c程序入口。
  25. *    形    参: 无
  26. *    返 回 值: 无
  27. *********************************************************************************************************
  28. */
  29. int main(void)
  30. {
  31.      /*
  32.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  33.        这样做的好处是:
  34.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  35.        2. 保证系统正常启动,不受别的中断影响。
  36.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  37.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  38.        和cpsie i是等效的。
  39.      */
  40.      __set_PRIMASK(1);
  41.    
  42.      /* 硬件初始化 */
  43.      bsp_Init();
  44.    
  45.      /* 创建任务 */
  46.      AppTaskCreate();
  47.    
  48.     /* 启动调度,开始执行任务 */
  49.     vTaskStartScheduler();
  50.      /*
  51.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  52.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  53.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  54.      */
  55.      while(1);
  56. }
  57. /*
  58. *********************************************************************************************************
  59. *    函 数 名: vTaskTaskUserIF
  60. *    功能说明: 接口消息处理,这里用作LED闪烁
  61. *    形    参: pvParameters 是在创建该任务时传递的形参
  62. *    返 回 值: 无
  63. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  64. *********************************************************************************************************
  65. */
  66. static void vTaskTaskUserIF(void *pvParameters)
  67. {
  68.     while(1)
  69.     {
  70.          bsp_LedToggle(1);
  71.          vTaskDelay(100);
  72.      }
  73. }
  74. /*
  75. *********************************************************************************************************
  76. *    函 数 名: vTaskLED
  77. *    功能说明: LED闪烁
  78. *    形    参: pvParameters 是在创建该任务时传递的形参
  79. *    返 回 值: 无
  80. *   优 先 级: 2
  81. *********************************************************************************************************
  82. */
  83. static void vTaskLED(void *pvParameters)
  84. {
  85.     while(1)
  86.     {
  87.          bsp_LedToggle(2);
  88.         vTaskDelay(200);
  89.     }
  90. }
  91. /*
  92. *********************************************************************************************************
  93. *    函 数 名: vTaskMsgPro
  94. *    功能说明: 信息处理,这里是用作LED闪烁   
  95. *    形    参: pvParameters 是在创建该任务时传递的形参
  96. *    返 回 值: 无
  97. *   优 先 级: 3
  98. *********************************************************************************************************
  99. */
  100. static void vTaskMsgPro(void *pvParameters)
  101. {
  102.     while(1)
  103.     {
  104.         bsp_LedToggle(3);
  105.         vTaskDelay(300);
  106.     }
  107. }
  108. /*
  109. *********************************************************************************************************
  110. *    函 数 名: vTaskStart
  111. *    功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
  112. *    形    参: pvParameters 是在创建该任务时传递的形参
  113. *    返 回 值: 无
  114. *   优 先 级: 4
  115. *********************************************************************************************************
  116. */
  117. static void vTaskStart(void *pvParameters)
  118. {
  119.     while(1)
  120.     {
  121.          /* LED闪烁 */
  122.         bsp_LedToggle(4);
  123.         vTaskDelay(400);
  124.     }
  125. }
  126. /*
  127. *********************************************************************************************************
  128. *    函 数 名: AppTaskCreate
  129. *    功能说明: 创建应用任务
  130. *    形    参: 无
  131. *    返 回 值: 无
  132. *********************************************************************************************************
  133. */
  134. static void AppTaskCreate (void)
  135. {
  136.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  137.                  "vTaskUserIF",     /* 任务名    */
  138.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  139.                  NULL,              /* 任务参数  */
  140.                  1,                 /* 任务优先级*/
  141.                  &xHandleTaskUserIF );  /* 任务句柄  */
  142.    
  143.    
  144.      xTaskCreate( vTaskLED,           /* 任务函数  */
  145.                  "vTaskLED",         /* 任务名    */
  146.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  147.                  NULL,               /* 任务参数  */
  148.                  2,                  /* 任务优先级*/
  149.                  &xHandleTaskLED ); /* 任务句柄  */
  150.    
  151.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  152.                  "vTaskMsgPro",           /* 任务名    */
  153.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  154.                  NULL,                    /* 任务参数  */
  155.                  3,                       /* 任务优先级*/
  156.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  157.    
  158.    
  159.      xTaskCreate( vTaskStart,             /* 任务函数  */
  160.                  "vTaskStart",            /* 任务名    */
  161.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  162.                  NULL,                    /* 任务参数  */
  163.                  4,                       /* 任务优先级*/
  164.                  &xHandleTaskStart );   /* 任务句柄  */
  165. }
  166. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码
除了创建的4个用户任务以外,还有空闲任务,这个任务是系统创建的。至此,FreeRTOS的工程就可以运行了,可以看到4个LED在闪烁。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-8-12 15:10:57 | 显示全部楼层
5.5  总结

    本章节为大家讲解了FreeRTOS的移植方法,移植比较简单。另一个重要内容是系统文件配置,在教程的第7章会为大家详细讲解这一部分。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
发表于 2016-9-18 11:33:55 | 显示全部楼层
受益匪浅啊。。[s:151]
回复

使用道具 举报

3

主题

13

回帖

22

积分

新手上路

积分
22
发表于 2019-4-20 21:39:54 | 显示全部楼层
讲的挺详细的,让我这个初学者一看就能懂个大概
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-27 23:56 , Processed in 0.214138 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表