600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【IoT】FreeRTOS 进阶:如何移植 freeRTOS 到 STM32 Cortex-M3

【IoT】FreeRTOS 进阶:如何移植 freeRTOS 到 STM32 Cortex-M3

时间:2022-02-08 15:41:12

相关推荐

【IoT】FreeRTOS 进阶:如何移植 freeRTOS 到 STM32 Cortex-M3

1、FreeRTOS 文件结构

下载包根目录下包含两个子目录:

FreeRTOS 和 FreeRTOS-Plus。

其中,FreeRTOS-Plus 文件夹中包含一些 FreeRTOS+ 组件和演示例程,重点说一下 FreeRTOS 文件夹。

FreeRTOS 文件夹下包含两个子目录:

Demo 和 Source。

其中,Demo 包含演示例程的工程文件,Source 包含实时操作系统源代码文件。

FreeRTOS 实时操作系统内核仅包含三个必要文件,此外还有三个可选文件。

RTOS 核心代码位于三个源文件中,分别是 tasks.c、queue.c 和 list.c。

这三个文件位于 FreeRTOS/Source 目录下,在同一目录下还有3个可选的文件:timers.c、event_groups.c和croutine.c,分别用于软件定时器、事件组和协程。

对于支持的处理器架构,RTOS 需要一些与处理器架构相关的代码。

可以称之为 RTOS 硬件接口层,它们位于 FreeRTOS/Source/Portable/[相应编译器]/[相应处理器架构]文件夹下。

我们这次要移植到Cortex-M3微控制,使用Keil MDK编译器,所以需要的RTOS硬件接口代码位于:

FreeRTOS\Source\portable\RVDS\ARM_CM3 文件夹下。

堆栈分配也是属于硬件接口层(移植层),在FreeRTOS/Source/portable/MemMang文件夹下具有各种类型的堆栈分配方案。

这里我们使用heap_1.c提供的堆栈分配方案。

FreeRTOS文件夹下的Demo文件夹中还包括各种演示例程,涉及多种架构的处理器以及多种编译器。

FreeRTOS/Demo/Common/Minimal文件夹下的演示例程代码中,绝大部分对所有移植硬件接口都是适用的。

FreeRTOS/Demo/Common/Full文件夹下的代码属于历史遗留代码,仅用于PC移植层。

2、移植前准备

一块具有Cortex-M3微处理器的硬件板子,并且保证板子可以正常运转。

下载 FreeRTOS 程序包;

下载 CMSIS-M3,其实主要是需要里面的core_cm3.h文件(可以去ARM官方下载,如果你安装了keil 5或比较新的Keil 4 MDK编译器,在目录:Keil\ARM\CMSIS文件夹下也可以找到)。

3、移植过程

3.1、添加 RTOS 核心代码

将tasks.c、queue.c和list.c这三个内核代码加入工程,将port.c和heap_1.c这两个与处理器相关代码加入工程。

port.c位于FreeRTOS\Source\portable\RVDS\ARM_CM3文件夹下;

heap_1.c位于FreeRTOS/Source/portable/MemMang文件夹下。

3.2、添加头文件路径

...\FreeRTOS\Source\portable\RVDS\ARM_CM3...\FreeRTOS\Source\include

3.3、编写FreeRTOSConfig.h文件

对于刚接触FreeRTOS的用户来说,最简单方法是找一个类似的Demo工程,复制该工程下的FreeRTOSConfig.h文件,在这个基础上进行修改。

3.4、编写一些钩子函数

如果你在FreeRTOSConfig.h中设置了configUSE_TICK_HOOK=1,则必须编写voidvApplicationTickHook( void )函数。

该函数利用时间片中断,可以很方便的实现一个定时器功能。

如果你在FreeRTOSConfig.h中设置了configCHECK_FOR_STACK_OVERFLOW=1或=2,则必须编写voidvApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )函数。

3.5、检查硬件

为了验证你的硬件板子是否可靠的工作,首先编写一个小程序片,比如闪烁一个LED灯或者发送一个字符等等,我们这里使用UART发送一个字符。

代码如下所示(假设你已经配置好了启动代码,并正确配置了UART):

#include"task.h"#include"queue.h"#include"list.h"#include"portable.h" #include"debug.h"int main(void){init_rtos_debug();//初始化调试串口MAP_UARTCharPut('A'); //发送一个字符while(1);}

如果硬件可以正常发送字符,说明硬件以及启动代码OK,可以进行下一步。

3.6、挂接中断

在Cortex-M3硬件下,FreeRTOS使用SysTick作为系统节拍时钟,使用SVC和PendSVC进行上下文切换。

异常中断服务代码位于port.c文件中,FreeRTOS的作者已经为各种架构的CPU写好了这些代码,可以直接拿来用,需要用户做的,仅仅是将这些异常中断入口地址挂接到启动代码中。

在startup.s中,使用IMPORT关键字声明要挂接的异常中断服务函数名,然后将:

DCD SVC_Handler换成: DCD vPortSVCHandlerDCD PendSV_Handler换成: DCD xPortPendSVHandlerDCD SysTick_Handler 换成: DCD xPortSysTickHandler

3.7、建立第一个任务Task

在步骤3.5中,我们为了测试硬件是是否能够工作,编写了一个发送字符的小函数,这里我们将把这个小函数作为我们第一个任务要执行的主要代码:

每隔1秒钟,发送一个字符。

代码如下所示:

voidvTask(void *pvParameters){while(1){MAP_UARTCharPut(0x31);vTaskDelay(1000/portTICK_RATE_MS);}}

3.8、设置节拍时钟

这里我们使用SysTick定时器作为系统的节拍时钟,设定每隔10ms产生一次节拍中断。

由于FreeRTOS对移植做了非常多的工作,以至于我们只需要在FreeRTOSConfig.h中配置好以下两个宏定义即可:

configCPU_CLOCK_HZ (/*你的硬件平台CPU系统时钟,Fcclk*/)

configTICK_RATE_HZ ((portTickType)100)

第一个宏定义CPU系统时钟,也就是CPU执行时的频率。

第二个宏定义FreeRTOS的时间片频率,这里定义为100,表明RTOS一秒钟可以切换100次任务,也就是每个时间片为10ms。

在prot.c中,函数vPortSetupTimerInterrupt()设置节拍时钟。

该函数根据上面的两个宏定义的参数,计算SysTick定时器的重装载数值寄存器,然后设置SysTick定时器的控制及状态寄存器,设置如下:

使用内核时钟源、使能中断、使能SysTick定时器。另外,函数vPortSetupTimerInterrupt()由函数vTaskStartScheduler()调用,这个函数用于启动调度器。

3.9、设置中断优先级相关宏

这里特别重要,因为涉及到中断优先级和中断嵌套。

这里先给出基于Cortex-M3硬件(lpc177x_8x系列微控制器)的一个配置例子,在FreeRTOSConfig.h中:

#ifdef __NVIC_PRIO_BITS#defineconfigPRIO_BITS __NVIC_PRIO_BITS#else#defineconfigPRIO_BITS 5 /*lpc177x_8x微处理器使用优先级寄存器的5位*/#endif/*设置内核使用的中断优先级*/#define configKERNEL_INTERRUPT_PRIORITY ( 31 << (8 - configPRIO_BITS) )/*定义RTOS可以屏蔽的最大中断优先级,大于这个优先级的中断,不受RTOS控制*/#defineconfigMAX_SYSCALL_INTERRUPT_PRIORITY ( 5<< (8 - configPRIO_BITS) )

3.10、设置其它宏

还需要在FreeRTOSConfig.h设置一些必要的宏,这些宏如下所示:

#define configUSE_PREEMPTION 1//配置为1使用抢占式内核,配置为0使用时间片#define configUSE_IDLE_HOOK 0//设置为1使用空闲钩子;设置为0不使用空闲钩子#define configMAX_PRIORITIES ( 5 ) //应用程序任务中可用优先级数目#define configUSE_TICK_HOOK 0 //就设置为1使用时间片钩子,设置为0不使用#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 ) //最小空闲堆栈#define configTOTAL_HEAP_SIZE( ( size_t ) ( 5 * 1024 ) ) //内核总共可用RAM

3.11、创建任务

调用FreeRTOS提供的API函数来创建任务,代码如下所示:

xTaskCreate(vTask,"Task1",50,NULL,1,NULL);

3.12、开启调度器

调用FreeRTOS提供的API函数来启动调度器,代码如下所示:

vTaskStartScheduler();关于详细的开启调度器API函数,会在后续文章《FreeRTOS内核控制》一文中介绍。此时的main函数代码如下所示:int main(void){init_rtos_debug();//初始化调试串口xTaskCreate(vTask,"Task1",50,NULL,1,NULL);vTaskStartScheduler();while(1); }

4、小结

最基本的FreeRTOS应用程序就已经运行起来,将硬件板子接到PC的RS232串口,可以观察到每隔一秒钟,板子都会向PC发送一个指定的字符。

refer:

/zhzht19861011/article/details/50072033

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。