|
楼主 |
发表于 2016-8-13 15:55:12
|
显示全部楼层
6.4 STM32F429移植FreeRTOS系统
6.4.1 FreeRTOS操作系统移植
首先准备好一个简单的裸机工程模板,工程模板的制作就不做讲解了,这里的重点是教大家移植FreeRTOS系统。准备好的工程模板如下图6.3所示(大家也可以制作其它任意的工程模板,不限制):图6.3 工程模板
准备好工程模板后,就可以开始移植了。首先要做的就是将所有需要的源码文件放到工程模板里面。下面分六步给大家进行说明,当然,不限制必须使用下面的方法添加源码到工程,只要将需要的文件添加到工程模板即可。
u 第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的压缩率更高些。下载后解压出来。
u 第2步:在工程模板创建FreeRTOS文件夹
u 第3步:添加源码文件到相应文件夹
l 将FreeRTOSV8.2.3软件包中路径:FreeRTOSV8.2.3\\FreeRTOS\\Source里面如下所有文件
复制到刚刚创建的FreeRTOS文件夹下。
l 文件夹User中还需要添加如下文件:
文件FreeRTOSConfig.h文件在FreeRTOSV8.2.3软件包中的中的路径:
FreeRTOSV8.2.3\\FreeRTOS\\Demo\\CORTEX_M4F_STM32F407ZG-SK,其实就是官方整理好的配置文件(官方没有F429的例子,使用F407的即可,配置是相同的)。
u 第3步:将源码文件添加到IAR的工程项目中,添加后的效果如下:
其中heap_4.c文件路径:FreeRTOS\\Source\\portable\\MemMang
port.c,portasm.h和portmacro.h文件的路径:FreeRTOS\\Source\\portable\\RVDS\\ARM_CM4F,由于STM32F429是M4内核的,所以移植文件也要添加M4内核的。
u 第4步:新创建一个includes.h文件,将所有的头文件都集中到这个头文件下。
这样做的好处是引用头文件的时候,只添加这个头文件就可以了。includes.h文件放在了User文件夹中。然后再将这个文件也添加到MDK工程项目中(将.h文件添加到工程的好处是方便查看和修改)
Includes.h文件中的内容如下:/*
- /*
- *********************************************************************************************************
- *
- * 模块名称 : 头文件汇总
- * 文件名称 : includes.h
- * 版 本 : V1.0
- * 说 明 : 当前使用头文件汇总
- *
- * 修改记录 :
- * 版本号 日期 作者 说明
- * V1.0 2015-08-02 Eric2013 首次发布
- *
- * Copyright (C), 2015-2020, 安富莱电子 www.armfly.com
- *
- *********************************************************************************************************
- */
-
- #ifndef __INCLUDES_H__
- #define __INCLUDES_H__
-
- /*
- *********************************************************************************************************
- * 标准库
- *********************************************************************************************************
- */
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
-
-
- /*
- *********************************************************************************************************
- * 其它库
- *********************************************************************************************************
- */
-
-
- /*
- *********************************************************************************************************
- * OS
- *********************************************************************************************************
- */
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "croutine.h"
-
-
- /*
- *********************************************************************************************************
- * 宏定义
- *********************************************************************************************************
- */
-
-
- /*
- *********************************************************************************************************
- * APP / BSP
- *********************************************************************************************************
- */
-
- #include <bsp.h>
-
-
- #endif
-
- /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码 u 第5步:添加相应的头文件路径,在原来工程模板的基础上新添加的两个路径:
C/C++选项中添加了路径后,Assembler汇编选项也是要添加路径的,这里的路径就是FreeRTOSConfig.h文件所在的路径,这么做是因为portasm.s汇编文件中有引用到这个文件。
u 第6步:最后一步,同时也是最重要的一步,修改FreeRTOSConfig.h配置文件(用户根据自己的配置进行修改,不修改也是没问题的,我们这里进行修改主要是为了方便初学者学习),主要修改了以下两个方面:
l 添加宏定义__NVIC_PRIO_BITS,STM32系列产品优先级仅使用4位。
l 修改优先级相关的几个宏定义,具体修改了哪个可以对比原始文件查看。
修改后在这个文件的末尾加上Systick,PendSV和SVC中断函数的宏定义,目的是将FreeRTOS移植文件port.c文件里面的中断服务程序映射到CMSIS定义的标准名称,这样就不需要用户去修改工程启动代码中这几个中断的名字了,很方便就实现了两个函数的统一。(移植过uCOS-II或者III的用户,对于这个问题估计深有体会,因为uCOS要修改启动文件,其实采用这里的方式更方便)
- /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
- standard names. */
- #define vPortSVCHandler SVC_Handler
- #define xPortPendSVHandler PendSV_Handler
- #define xPortSysTickHandler SysTick_Handler
复制代码 其中vPortSVCHandler,xPortPendSVHandler和xPortSysTickHandler是在port.c文件里面定义的。SVC_Handler,PendSV_Handler和SysTick_Handler在startup_stm32f10x_hd.s文件里面进行了定义。
下面是FreeRTOSConfig.h配置文件的完整内容:
- #ifndef FREERTOS_CONFIG_H
- #define FREERTOS_CONFIG_H
-
- /*-----------------------------------------------------------
- * Application specific definitions.
- *
- * These definitions should be adjusted for your particular hardware and
- * application requirements.
- *
- * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
- * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
- *
- * See http://www.freertos.org/a00110.html.
- *----------------------------------------------------------*/
-
- #define configUSE_PREEMPTION 1
- #define configUSE_IDLE_HOOK 0
- #define configUSE_TICK_HOOK 0
- #define configCPU_CLOCK_HZ ( ( unsigned long ) 168000000 )
- #define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
- #define configMAX_PRIORITIES ( 5 )
- #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
- #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) )
- #define configMAX_TASK_NAME_LEN ( 16 )
- #define configUSE_TRACE_FACILITY 0
- #define configUSE_16_BIT_TICKS 0
- #define configIDLE_SHOULD_YIELD 1
-
- /* Co-routine definitions. */
- #define configUSE_CO_ROUTINES 0
- #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
-
- /* Set the following definitions to 1 to include the API function, or zero
- to exclude the API function. */
-
- #define INCLUDE_vTaskPrioritySet 1
- #define INCLUDE_uxTaskPriorityGet 1
- #define INCLUDE_vTaskDelete 1
- #define INCLUDE_vTaskCleanUpResources 0
- #define INCLUDE_vTaskSuspend 1
- #define INCLUDE_vTaskDelayUntil 1
- #define INCLUDE_vTaskDelay 1
-
- /* Cortex-M specific definitions. */
- #ifdef __NVIC_PRIO_BITS
- /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
- #define configPRIO_BITS __NVIC_PRIO_BITS
- #else
- #define configPRIO_BITS 4 /* 15 priority levels */
- #endif
-
- /* The lowest interrupt priority that can be used in a call to a "set priority"
- function. */
- #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
-
- /* The highest interrupt priority that can be used by any interrupt service
- routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
- INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
- PRIORITY THAN THIS! (higher priorities are lower numeric values. */
- #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
-
- /* Interrupt priorities used by the kernel port layer itself. These are generic
- to all Cortex-M ports, and do not rely on any particular library functions. */
- #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
- /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
- See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
- #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
-
- /* Normal assert() semantics without relying on the provision of an assert.h
- header file. */
- #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
-
- /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
- standard names. */
- #define vPortSVCHandler SVC_Handler
- #define xPortPendSVHandler PendSV_Handler
- #define xPortSysTickHandler SysTick_Handler
-
-
- #endif /* FREERTOS_CONFIG_H */
复制代码 至此,FreeRTOS的移植工作就完成了,剩下就是系统配置和应用了。其中系统配置,会在第7章专门进行讲解。
6.4.2 FreeRTOS操作系统应用实例
FreeRTOSConfig.h配置文件里面几个重要选项说明:
u #define configUSE_PREEMPTION 1
使能抢占式调度器
u #define configCPU_CLOCK_HZ ( ( unsigned long ) 168000000 )
系统主频168MHz。
u #define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
系统时钟节拍1KHz,即1ms。
u #define configMAX_PRIORITIES ( 5 )
定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
u #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) )
定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
---------------------------------------------------------------------------------------------------
经过上面的移植和配置之后,在main.c文件中添加如下代码,代码中简单的创建了四个用户任务:
vTaskTaskUserIF任务:接口消息处理,这里用作LED闪烁。
AppTaskLED任务 :LED闪烁。
vTaskMsgPro任务:消息处理,这里用作LED闪烁。
AppTaskStart任务:启动任务,也是最高优先级任务,这里实现LED闪烁。
- #include "includes.h"
-
-
-
- /*
- **********************************************************************************************************
- 函数声明
- **********************************************************************************************************
- */
- static void vTaskTaskUserIF(void *pvParameters);
- static void vTaskLED(void *pvParameters);
- static void vTaskMsgPro(void *pvParameters);
- static void vTaskStart(void *pvParameters);
- static void AppTaskCreate (void);
-
- /*
- **********************************************************************************************************
- 变量声明
- **********************************************************************************************************
- */
- static TaskHandle_t xHandleTaskUserIF = NULL;
- static TaskHandle_t xHandleTaskLED = NULL;
- static TaskHandle_t xHandleTaskMsgPro = NULL;
- static TaskHandle_t xHandleTaskStart = NULL;
-
- /*
- *********************************************************************************************************
- * 函 数 名: main
- * 功能说明: 标准c程序入口。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- int main(void)
- {
- /*
- 在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
- 这样做的好处是:
- 1. 防止执行的中断服务程序中有FreeRTOS的API函数。
- 2. 保证系统正常启动,不受别的中断影响。
- 3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
- 在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
- 和cpsie i是等效的。
- */
- __set_PRIMASK(1);
-
- /* 硬件初始化 */
- bsp_Init();
-
- /* 创建任务 */
- AppTaskCreate();
-
- /* 启动调度,开始执行任务 */
- vTaskStartScheduler();
-
- /*
- 如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
- heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
- #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
- */
- while(1);
-
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskTaskUserIF
- * 功能说明: 接口消息处理,这里用作LED闪烁
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 1 (数值越小优先级越低,这个跟uCOS相反)
- *********************************************************************************************************
- */
- static void vTaskTaskUserIF(void *pvParameters)
- {
- while(1)
- {
- bsp_LedToggle(1);
- vTaskDelay(100);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskLED
- * 功能说明: LED闪烁
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 2
- *********************************************************************************************************
- */
- static void vTaskLED(void *pvParameters)
- {
- while(1)
- {
- bsp_LedToggle(2);
- vTaskDelay(200);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskMsgPro
- * 功能说明: 信息处理,这里是用作LED闪烁
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 3
- *********************************************************************************************************
- */
- static void vTaskMsgPro(void *pvParameters)
- {
- while(1)
- {
- bsp_LedToggle(3);
- vTaskDelay(300);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskStart
- * 功能说明: 启动任务,也就是最高优先级任务,这里用作LED闪烁
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 4
- *********************************************************************************************************
- */
- static void vTaskStart(void *pvParameters)
- {
- while(1)
- {
- /* LED闪烁 */
- bsp_LedToggle(4);
- vTaskDelay(400);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCreate
- * 功能说明: 创建应用任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void AppTaskCreate (void)
- {
- xTaskCreate( vTaskTaskUserIF, /* 任务函数 */
- "vTaskUserIF", /* 任务名 */
- 512, /* 任务栈大小,单位word,也就是4字节 */
- NULL, /* 任务参数 */
- 1, /* 任务优先级*/
- &xHandleTaskUserIF ); /* 任务句柄 */
-
-
- xTaskCreate( vTaskLED, /* 任务函数 */
- "vTaskLED", /* 任务名 */
- 512, /* 任务栈大小,单位word,也就是4字节 */
- NULL, /* 任务参数 */
- 2, /* 任务优先级*/
- &xHandleTaskLED ); /* 任务句柄 */
-
- xTaskCreate( vTaskMsgPro, /* 任务函数 */
- "vTaskMsgPro", /* 任务名 */
- 512, /* 任务栈大小,单位word,也就是4字节 */
- NULL, /* 任务参数 */
- 3, /* 任务优先级*/
- &xHandleTaskMsgPro ); /* 任务句柄 */
-
-
- xTaskCreate( vTaskStart, /* 任务函数 */
- "vTaskStart", /* 任务名 */
- 512, /* 任务栈大小,单位word,也就是4字节 */
- NULL, /* 任务参数 */
- 4, /* 任务优先级*/
- &xHandleTaskStart ); /* 任务句柄 */
- }
- /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码 除了创建的4个用户任务以外,还有空闲任务,这个任务是系统创建的。至此,FreeRTOS的工程就可以运行了,可以看到4个LED在闪烁。 |
|