FreeRTOS实时操作系统在Cortex-M3上的移植过程

目录
  • 1. FreeRTOS下载包的文件结构
  • 2. 移植前的一些准备
  • 3.移植过程
    • 3.1 添加RTOS核心代码
    • 3.2 添加头文件路径
    • 3.3 编写FreeRTOSConfig.h文件
    • 3.4 编写一些钩子函数
    • 3.5 检查硬件
    • 3.6 挂接中断
    • 3.7 建立第一个任务Task
    • 3.8 设置节拍时钟
    • 3.9设置中断优先级相关宏
    • 3.10 设置其它宏
    • 3.11 创建任务
  • 4. 小结

1. FreeRTOS下载包的文件结构

在FreeRTOS官方网站可以下载到最新版的FreeRTOS包,我这里使用的是V8.2.3版本。

下载包内的总文件数量多的令人生畏,但文件结构却很简洁。《FreeRTOS入门指南》一文的第3节详细描述了下载包文件结构,我们这里只是简单提一下。

下载包根目录下包含两个子目录: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的内存管理,后续《FreeRTOS内存管理》一文中会详细介绍FreeRTOS内存管理的特性和用法,《FreeRTOS内存管理分析》一文会从源码级别分析FreeRTOS内存管理的具体实现,这里不用多纠结,你也可以快速的浏览一下这两篇文章,里面或许有许多不懂的,但不要着急,先放过它们。

FreeRTOS文件夹下的Demo文件夹中还包括各种演示例程,涉及多种架构的处理器以及多种编译器。FreeRTOS/Demo/Common/Minimal文件夹下的演示例程代码中,绝大部分对所有移植硬件接口都是适用的。FreeRTOS/Demo/Common/Full文件夹下的代码属于历史遗留代码,仅用于PC移植层。

2. 移植前的一些准备

一块具有Cortex-M3微处理器的硬件板子,并且保证板子可以正常运转。下载FreeRTOS程序包(《FreeRTOS历史版本更新记录》一文中有下载地址,这是我在CSDN下载频道做的镜像文件。如果你能忍受下载网速慢,也可以去官方网站下载。)下载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文件,在这个基础上进行修改。详细的配置说明将在后续《FreeRTOS内核配置说明》一文中给出,这里依然不必纠结。

3.4 编写一些钩子函数

如果你在FreeRTOSConfig.h中设置了configUSE_TICK_HOOK=1,则必须编写voidvApplicationTickHook( void )函数。该函数利用时间片中断,可以很方便的实现一个定时器功能。详见后续文章《FreeRTOS内核配置说明》有关宏configUSE_TICK_HOOK一节。

如果你在FreeRTOSConfig.h中设置了configCHECK_FOR_STACK_OVERFLOW=1或=2,则必须编写voidvApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )函数,该函数用于检测堆栈溢出,详见后续文章《FreeRTOS内核配置说明》有关宏configCHECK_FOR_STACK_OVERFLOW一节。

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     vPortSVCHandler
         DCD     PendSV_Handler         换成:   DCD     xPortPendSVHandler
         DCD     SysTick_Handler        换成:   DCD     xPortSysTickHandler

3.7 建立第一个任务Task

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

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

FreeRTOS的任务以及编写格式将在后续文章《FreeRTOS任务概述》一文中详述,这里只是一个很简单的任务,先有有大体印象。这里面有一个API函数vTaskDelay(),这个函数用于延时,具体用法将在后续文章《FreeRTOS任务控制》一文中详细介绍,延时函数代码级分析将在《FreeRTOS高级篇10---系统节拍时钟分析》。这里不必在意太多的未知情况,因为后面会一点点将这些未知空间探索一遍的。

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中:

后续文章《FreeRTOS内核配置说明》会详细介绍这些宏的含义,对于Cortex-M内核,后续文章《Cortex-M内核使用FreeRTOS特别注意事项》一文,会讲述这些宏与硬件的联系,那个时候你一定会清楚这些宏所定义的数字会对你的硬件产生什么影响的。现在,我们只需要知道他们很重要就足够了,没人能一口吃成胖子。

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);

关于详细的创建任务API函数,会在后续文章《FreeRTOS任务创建和删除》一文中介绍。

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发送一个指定的字符。

回头看一下移植过程,FreeRTOS移植到Cortex-M3硬件是多么的简单,这一方面归功于FreeRTOS的设计师已经为移植做了大量工作,同时,新一代的Cortex-M3硬件也为操作系统增加了一些列便利特性,比如SysTick定时器和全新的中断及异常。

但是移植成功也只是万里长征的第一步,因为这只是最简单的应用。我们还不清楚FreeRTOS背后的机理、调度算法的面貌、甚至连信号量也都没有涉及。就本文的移植过程来看,我们也刻意忽略了很多细节,比如FreeRTOSConfig.h文件中的宏都有什么意义?改动后对RTOS有何影响?比如FreeRTOS任务API的细节、调度API的细节,再比如FreeRTOS的内存如何分配?如何进行堆栈溢出检查等等。

所以,先不要沾沾自喜,曲折的道路还远没到来呢。

接下来的很多篇文章会围绕这个最简单的移植例程做详细的讲解,要把本篇文章中刻意隐藏的细节一一拿出来。这要一直持续到我们介绍队列、信号量、互斥量等通讯机制为止。

希望大家以后多多支持我们!

(0)

相关推荐

  • FreeRTOS实时操作系统内核配置说明

    目录 1.configUSE_PREEMPTION 2.configUSE_PORT_OPTIMISED_TASK_SELECTION 3.configUSE_TICKLESS_IDLE 4.configUSE_IDLE_HOOK 5.configUSE_MALLOC_FAILED_HOOK 6.configUSE_TICK_HOOK 7.configCPU_CLOCK_HZ 8.configTICK_RATE_HZ 9.configMAX_PRIORITIES 10.configMINIMAL

  • FreeRTOS实时操作系统特点介绍

    目录 1.什么是FreeRTOS? 2.为什么择 选择 FreeRTOS ? 3.FreeRTOS 特点 FreeRTOS资料与源码下载 FreeRTOS源码文件介绍 1.什么是FreeRTOS? Free 即免费的,RTOS 全称是 Real Time Operating System,中文就是实时操作系统.注意,RTOS 不是指某一个确定的系统,而是指一类系统.比如 uC/OS,FreeRTOS,RTX,RT-Thread 等这些都是 RTOS 类操作系统. 操作系统允许多个任务同时运行,这

  • freertos实时操作系统临界段保护开关中断及进入退出

    目录 中断的基础知识 嵌套: 优先级: 中断的悬起与解悬: 咬尾中断Tail‐Chaining: 晚到的高优先级异常: 进入临界段和退出临界段 中断的基础知识 嵌套: 嵌套向量中断控制器 NVIC(Nested Vectored Interrupt Controller与内核是紧耦合的.提供如下的功能:可嵌套中断支持.向量中断支持.动态优先级调整支持.中断延迟大大缩短. 中断可屏蔽. 所有的外部中断和绝大多数系统异常均支持可嵌套中断.异常都可以被赋予不同的优先级,当前优先级被存储在 xPSR的专

  • FreeRTOS实时操作系统临界段保护场合示例

    目录 临界段保护场合 非中断场合 中断场合 临界段保护场合 FreeRTOS中临界段保护有2种场合,中断和非中断,通过关中断(或者关部分中断)来实现临界保护. 非中断场合 task.h 中 #define taskENTER_CRITICAL()portENTER_CRITICAL() #define taskEXIT_CRITICAL()portEXIT_CRITICAL() portmacro.h中 #define portENTER_CRITICAL()vPortEnterCritical

  • FreeRTOS实时操作系统结构示例

    目录 1.查找相关文档页 2.获取RTOS源代码 3.FreeRTOS源码目录结构 移植层目录举例: 演示例程目录举例: 4.编译工程 5.运行演示例程 FreeRTOS可以被移植到很多不同架构的处理器和编译器.每一个RTOS移植都附带一个已经配置好的演示例程,可以方便快速启动开发.更好的是,每个演示例程都附带一个说明网页,提供如何定位RTOS演示工程源代码.如何编译演示例程.如何配置硬件平台的全部信息. 演示例程说明网页还提供基本的RTOS移植细节信息,包括如何编写FreeRTOS兼容的中断服

  • FreeRTOS实时操作系统多任务管理基础知识

    目录 什么是多任务系统? FreeRTOS  任务与协程 1.任务(Task) 的特性 2.协程(Co-routine)的特性 任务状态 运行态 就绪态 阻塞态 挂起态 任务优先级 任务实现 任务控制块 任务堆栈 RTOS 系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习 RTOS 系统的工程师或者学生主要就是为了使用 RTOS 的多任务处理功能,初步上手 RTOS 系统首先必须掌握的也是任务的创建.删除.挂起和恢复等操作,由此可见任务管理的重要性. 什么是多任务系统? 回想一

  • FreeRTOS编码标准及风格指南

    目录 1.编码标准 2.命名规则 1> 变量 2> 函数 1.编码标准 FreeRTOS的核心源代码遵从MISRA编码标准指南.这个标准篇幅稍长,你可以在MISRA官方网站花少量钱买到,这里不再复制任何标准. FreeRTOS源代码不符合MISRA标准的项目如下所示: 有两个API函数有多个返回点.MISRA编码标准强制规定:一个函数在其结尾应该有单一的返回点. 指针算数运算,在创建任务时,为了兼容8.16.20.24.32位总线,不可避免的使用了指针算数运算.MISRA编码标准强制规定:指针

  • FreeRTOS实时操作系统移植操作示例指南

    目录 1.添加FreeRTOS源码 2.向工程分组中添加文件 附上delay.c和delay.h的代码 1.添加FreeRTOS源码 在基础工程中新建一个名为 FreeRTOS 的文件夹,将 FreeRTOS 的源码(source文件夹下的内容)添加到这个文件夹中 portable文件夹中,只需留下 keil.MemMang 和 RVDS这三个文件夹,其他的都可以删除掉. 2.向工程分组中添加文件 打开基础工程,新建分组 FreeRTOS_CORE 和 FreeRTOS_PORTABLE,然后向

  • freertos实时操作系统空闲任务阻塞延时示例解析

    阻塞态:如果一个任务当前正在等待某个外部事件,则称它处于阻塞态. rtos中的延时叫阻塞延时,即任务需要延时的时候,会放弃CPU的使用权,进入阻塞状态.在任务阻塞的这段时间,CPU可以去执行其它的任务(如果其它的任务也在延时状态,那么 CPU 就将运行空闲任务),当任务延时时间到,重新获取 CPU 使用权,任务继续运行. 空闲任务:处理器空闲的时候,运行的任务.当系统中没有其他就绪任务时,空闲任务开始运行,空闲任务的优先级是最低的. 空闲任务 定义空闲任务: #define portSTACK_

  • FreeRTOS操作系统的配置示例解析

    目录 1. FreeRTOSConfig.h 文件 2.  “INCLUDE_” 开始的宏 3.“config”开始的宏 FreeRTOS 的系统配置文件为 FreeRTOSConfig.h,在此配置文件中可以完成 FreeRTOS 的裁剪和配置. 1. FreeRTOSConfig.h 文件 FreeRTOS 的配置基本是通过在 FreeRTOSConfig.h 中使用“#define”这样的语句来定义宏定义实现的.在 FreeRTOS 的官方 demo 中,每个工程都有一个 FreeRTOS

随机推荐