FreeRTOS学习笔记【二】——FreeRTOS 移植

这篇具有很好参考价值的文章主要介绍了FreeRTOS学习笔记【二】——FreeRTOS 移植。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        上一章中我们初步的了解了一下 FreeRTOS,本章就正式踏上 FreeRTOS 的学习之路, 首先
肯定是把 FreeRTOS 移植到我们所使用的平台上, 这里以 ALIENTEK 的 STM32F103 开发板为
例,本章分为如下几部分:
2.1 准备工作
2.2 FreeRTOS 移植
2.3 移植验证实验

2.1 准备工作


2.1.1 准备基础工程


        要移植 FreeRTOS,肯定需要一个基础工程, 基础工程越简单越好, 这里我们就用基础例程
中的跑马灯实验来作为基础工程。


2.1.2 FreeRTOS 系统源码


        FreeRTOS 系统源码在上一章已经详细的讲解过如何获取了, 这里我们会将 FreeRTOS 的系
统源码放到开发板光盘中去,路径为: 6, 软件资料->14, FreeRTOS 学习资料->FreeRTOS 源码。

2.2 FreeRTOS 移植


2.2.1 向工程中添加相应文件


1、 添加 FreeRTOS 源码
        在基础工程中新建一个名为 FreeRTOS 的文件夹, 如图 2.2.1.1 所示:
FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.1 新建 FreeRTOS 文件夹

        创建 FreeRTOS 文件夹以后就可以将 FreeRTOS 的源码添加到这个文件夹中, 添加完以后
如图 2.2.1.2 所示:
FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.2 添加 FreeRTOS 源码


        在 1.3.2 小节中详细的讲解过 portable 文件夹,我们只需要留下 keil、 MemMang 和 RVDS
这三个文件夹, 其他的都可以删除掉, 完成以后如图 2.2.1.3 所示:

FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.3 portable 文件夹


2、向工程分组中添加文件
        打开基础工程,新建分组 FreeRTOS_CORE 和 FreeRTOS_PORTABLE,然后向这两个分组
中添加文件,如图 2.2.1.4 所示:

FreeRTOS学习笔记【二】——FreeRTOS 移植

图 2.2.1.4 添加文件


        分组 FreeRTOS_CORE 中的文件在什么地方就不说了,打开 FreeRTOS 源码一目了然。 重
点来说说 FreeRTOS_PORTABLE 分组中的 port.c 和 heap_4.c 是怎么来的, port.c 是 RVDS 文件夹下的 ARM_CM3 中的文件, 因为 STM32F103 是 Cortex-M3 内核的, 因此要选择 ARM_CM3中的 port.c 文件。 heap_4.c 是 MemMang 文件夹中的,前面说了 MemMang 是跟内存管理相关的,里面有 5 个 c 文件: heap_1.c、 heap_2.c、 heap_3.c、 heap_4.c 和 heap_5.c。

        这 5 个 c 文件是五种不同的内存管理方法,就像从北京到上海你可以坐火车、坐飞机, 如果心情好的话也可以走路,反正有很多种方法, 只要能到上海就行。这里也一样的,这 5 个文件都可以用来作为FreeRTOS 的内存管理文件, 只是它们的实现原理不同, 各有利弊。 这里我们选择 heap_4.c,至于原因, 后面会有一章节专门来讲解 FreeRTOS 的内存管理,到时候大家就知道原因了。 这里就先选择 heap_4.c,毕竟本章的重点是 FreeRTOS 的移植。
        3、 添加相应的头文件路径
添加完 FreeRTOS 源码中的 C 文件以后还要添加 FreeRTOS 源码的头文件路径,头文件路
径如图 2.2.1.5 所示:

FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.5 FreeRTOS 头文件路径

        头文件路径添加完成以后编译一下,看看有没有什么错误, 结果会发现提示打不开
“FreeRTOSConfig.h”这个文件, 如图 2.2.1.6 所示:

 FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.6 错误提示


        这是因为缺少 FreeRTOSConfig.h 文件,这个文件在哪里找呢? 你可以自己创建,显然这不
是一个明智的做法。 我们可以找找 FreeRTOS 的官方移植工程中会不会有这个文件,打开
FreeRTOS 针对 STM32F103 的移植工程文件,文件夹是 CORTEX_STM32F103_Keil,打开以后
如图 2.2.1.7 所示:

FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.7 STM32F103 移植工程

        
        果然! 官方的移植工程中有这个文件, 我们可以使用这个文件, 但是建议大家使用我们例
程中的 FreeRTOSConf.h 文件,这个文件是 FreeRTOS 的系统配置文件,不同的平台其配置不同,
        但是我们提供的例程中的这个文件肯定是针对 ALIENTEK 开发板配置正确的。 这个文件复制到什么地方大家可以自行决定,这里我为了方便放到了 FreeRTOS 源码中的 include 文件夹下。
FreeRTOSConfig.h 是何方神圣?看名字就知道, 他是 FreeRTOS 的配置文件,一般的操作系统都有裁剪、 配置功能, 而这些裁剪及配置都是通过一个文件来完成的, 基本都是通过宏定义来完成对系统的配置和裁剪的, 关于 FreeRTOS 的配置文件 FreeRTOSConfig.h 后面也会有一章节来详细的讲解。到这里我们再编译一次, 没有错误! 如图 2.2.1.8 所示:
FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.1.8 编译结果


        如果还有错误的话大家自行根据错误类型查找和修改错误!


2.2.2 修改 SYSTEM 文件


        SYSTEM 文件夹里面的文件一开始是针对 UCOS 而编写的,所以如果使用 FreeRTOS 的话
就需要做相应的修改。本来打算让 SYSTEM 文件夹也支持 FreeRTOS, 但是这样的话会导致
SYSTEM 里面的文件太过于复杂, 这样非常不利于初学者学习, 所以这里就专门针对 FreeRTOS
修改了 SYSTEM 里面的文件。
1、 修改 sys.h 文件
        sys.h 文件修改很简单,在 sys.h 文件里面用宏 SYSTEM_SUPPORT_OS 来定义是否使用 OS,我们使用了 FreeRTOS, 所以应该将宏 SYSTEM_SUPPORT_OS 改为 1。

//0,不支持 os
//1,支持 os
#define SYSTEM_SUPPORT_OS 1 //定义系统文件夹是否支持 OS

2、 修改 usart.c 文件
        usart.c 文件修改也很简单, usart.c 文件有两部分要修改,一个是添加 FreeRTOS.h 头文件,默认是添加的 UCOS 中的 includes.h 头文件,修改以后如下:
 

//如果使用 os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" //os 使用
#endif

        另外一个就是 USART1 的中断服务函数, 在使用 UCOS 的时候进出中断的时候需要添加
OSIntEnter()和 OSIntExit(), 使用 FreeRTOS 的话就不需要了,所以将这两行代码删除掉,修改
以后如下:

void USART1_IRQHandler(void) //串口 1 中断服务程序
{
    u8 Res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        Res =USART_ReceiveData(USART1); //读取接收到的数据
        if((USART_RX_STA&0x8000)==0) //接收未完成
        {
            if(USART_RX_STA&0x4000) //接收到了 0x0d
             {
                if(Res!=0x0a)USART_RX_STA=0; //接收错误,重新开始
                else USART_RX_STA|=0x8000; //接收完成了
             }
                else //还没收到 0X0D
            {
                if(Res==0x0d)USART_RX_STA|=0x4000;
                else
                {
                    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                    USART_RX_STA++;
                    if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
                }
            }
           }
        }
}

3、修改 delay.c 文件


        delay.c 文件修改的就比较大了,因为涉及到 FreeRTOS 的系统时钟, delay.c 文件里面有 4
个函数,先来看一下函数 SysTick_Handler(),此函数是滴答定时器的中断服务函数, 代码如下:

extern void xPortSysTickHandler(void);
//systick 中断服务函数,使用 OS 时用到
void SysTick_Handler(void)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();
    }
}


        FreeRTOS 的心跳就是由滴答定时器产生的,根据 FreeRTOS 的系统时钟节拍设置好滴答定
时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用
FreeRTOS 的 API 函数 xPortSysTickHandler()。
        delay_init()是用来初始化滴答定时器和延时函数,代码如下:

        

//初始化延迟函数
//SYSTICK 的时钟固定为 AHB 时钟,基础例程里面 SYSTICK 时钟频率为 AHB/8
//这里为了兼容 FreeRTOS,所以将 SYSTICK 的时钟频率改为 AHB 的频率!
//SYSCLK:系统时钟频率
void delay_init()
{
    u32 reload;
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
    fac_us=SystemCoreClock/1000000;              //不论是否使用 OS,fac_us 都需要使用
    reload=SystemCoreClock/1000000;              //每秒钟的计数次数 单位为 M
    reload*=1000000/configTICK_RATE_HZ;          //根据 configTICK_RATE_HZ 设定溢出
     //时间 reload 为 24 位寄存器,最大值;16777216,在 72M 下,约合 0.233s 左右
    fac_ms=1000/configTICK_RATE_HZ;               //代表 OS 可以延时的最少单位
    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;      //开启 SYSTICK 中断
    SysTick->LOAD=reload;                         //每 1/configTICK_RATE_HZ 秒中断一次
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;       //开启 SYSTICK
}

        前面我们说了 FreeRTOS 的系统时钟是由滴答定时器提供的,那么肯定要根据 FreeRTOS 的
系统时钟节拍来初始化滴答定时器了, delay_init()就是来完成这个功能的。 FreeRTOS 的系统时
钟节拍由宏 configTICK_RATE_HZ 来设置,这个值我们可以自由设置,但是一旦设置好以后我
们就要根据这个值来初始化滴答定时器,其实就是设置滴答定时器的中断周期。 在基础例程中
滴答定时器的时钟频率设置的是 AHB 的 1/8,这里为了兼容 FreeRTOS 将滴答定时器的时钟频
率改为了 AHB,也就是 72MHz!这一点一定要注意!
接下来的三个函数都是延时的,代码如下:

//延时 nus
//nus:要延时的 us 数.
//nus:0~204522252(最大值即 2^32/fac_us@fac_us=168)
void delay_us(u32 nus)
{
    u32 ticks;
    u32 told,tnow,tcnt=0;
    u32 reload=SysTick->LOAD; //LOAD 的值
    ticks=nus*fac_us; //需要的节拍数
    told=SysTick->VAL; //刚进入时的计数器值
    while(1)
    {
        tnow=SysTick->VAL;
        if(tnow!=told)
        {
            //这里注意一下 SYSTICK 是一个递减的计数器就可以了.
            if(tnow<told)tcnt+=told-tnow;
            else tcnt+=reload-tnow+told;
            told=tnow;
            if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
        }
    };
}
//延时 nms,会引起任务调度
//nms:要延时的 ms 数
//nms:0~65535
void delay_ms(u32 nms)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        if(nms>=fac_ms) //延时的时间大于 OS 的最少时间周期
        {
            vTaskDelay(nms/fac_ms); //FreeRTOS 延时
        }
        nms%=fac_ms; //OS 已经无法提供这么小的延时了,
        //采用普通方式延时
    }
    delay_us((u32)(nms*1000)); //普通方式延时
}
//延时 nms,不会引起任务调度
//nms:要延时的 ms 数
void delay_xms(u32 nms)
{
    u32 i;
    for(i=0;i<nms;i++) delay_us(1000);
}


        delay_us()是 us 级延时函数, delay_ms 和 delay_xms()都是 ms 级的延时函数, delay_us()和delay_xms()不会导致任务切换。 delay_ms()其实就是对 FreeRTOS 中的延时函数 vTaskDelay()的简单封装,所以在使用 delay_ms()的时候就会导致任务切换。
        delay.c 修改完成以后编译一下,会提示如图 2.2.2.1 所示错误:

FreeRTOS学习笔记【二】——FreeRTOS 移植

 图 2.2.2.1 错误提示

        图 2.2.2.1 的错误提示表示在 port.c、 delay.c 和 stm32f10x_it.c 中三个重复定义的函数:
SysTick_Handler()、 SVC_Handler()和 PendSV_Handler(),这三个函数分别为滴答定时器中断服
务函数、 SVC 中断服务函数和 PendSV 中断服务函数,将 stm32f10x_it.c 中的三个函数屏蔽掉,

如图 2.2.2.2 所示:

FreeRTOS学习笔记【二】——FreeRTOS 移植

图 2.2.2.2 屏蔽函数
 

         再次编译代码,应该没有错误了,如果还是错误的话自行根据错误类型修改!至此, SYSTEM
文件夹就修改完成了。

2.3 移植验证实验


2.3.1 实验程序设计


1、实验目的
        编写简单的 FreeRTOS 应用代码,测试 FreeRTOS 的移植是否成功。鉴于大家还没正式学习
FreeRTOS, 可以直接将本实验代码复制粘贴到自己的移植工程中。
2、实验设计
        本实验设计四个任务: start_task()、 led0_task ()、 led1_task ()和 float_task(),这四个任务的任务功能如下:
start_task():用来创建其他三个任务。
led0_task ():控制 LED0 的闪烁,提示系统正在运行。
led1_task ():控制 LED1 的闪烁。
float_task():简单的浮点测试任务,用于测试 STM32F4 的 FPU 是否工作正常。
3、实验工程
        FreeRTOS 实验 2-1 FreeRTOS 移植实验。
4、实验程序与分析
●任务设置

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数
#define LED0_TASK_PRIO 2 //任务优先级
#define LED0_STK_SIZE 50 //任务堆栈大小
TaskHandle_t LED0Task_Handler; //任务句柄
void led0_task(void *p_arg); //任务函数
#define LED1_TASK_PRIO 3 //任务优先级
#define LED1_STK_SIZE 50 //任务堆栈大小
TaskHandle_t LED1Task_Handler; //任务句柄
void led1_task(void *p_arg); //任务函数
● main()函数
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
    delay_init(); //延时函数初始化
    uart_init(115200); //初始化串口
    LED_Init(); //初始化 LED
    //创建开始任务
    xTaskCreate((TaskFunction_t )start_task, //任务函数
    (const char* )"start_task", //任务名称
    (uint16_t )START_STK_SIZE, //任务堆栈大小
    (void* )NULL, //传递给任务函数的参数
    (UBaseType_t )START_TASK_PRIO, //任务优先级
    (TaskHandle_t* )&StartTask_Handler); //任务句柄
    vTaskStartScheduler(); //开启任务调度
}

● 任务函数
 

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); //进入临界区
    //创建 LED0 任务
    xTaskCreate((TaskFunction_t )led0_task,
    (const char* )"led0_task",
    (uint16_t )LED0_STK_SIZE,
    (void* )NULL,
    (UBaseType_t )LED0_TASK_PRIO,
    (TaskHandle_t* )&LED0Task_Handler);
    //创建 LED1 任务
    xTaskCreate((TaskFunction_t )led1_task,
    (const char* )"led1_task",
    (uint16_t )LED1_STK_SIZE,
    (void* )NULL,
    (UBaseType_t )LED1_TASK_PRIO,
    (TaskHandle_t* )&LED1Task_Handler);
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL(); //退出临界区
}
//LED0 任务函数
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}
//LED1 任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

        测试代码中创建了 3 个任务: LED0 测试任务、 LED1 测试任务和浮点测试任务,它们的任务函数分别为: led0_task()、 led1_task()。 led0_task()和 led1_task()任务很简单,就是让 LED0 和LED1 周期性闪烁。

2.3.2 实验程序运行结果分析


        编译并下载代码到 STM32F103 开发板中,下载进去以后会看到 LED0 和 LED1 开始闪烁,
LED0 均匀闪烁,那是因为我们在 LED0 的任务代码中设置好的 LED0 亮 500ms,灭 500ms。
LED1 亮的时间短,灭的时间长,这是因为在 LED1 的任务代码中设置好的亮 200ms,灭 800ms。文章来源地址https://www.toymoban.com/news/detail-467659.html

到了这里,关于FreeRTOS学习笔记【二】——FreeRTOS 移植的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32移植freertos报错keil

    *** Using Compiler \\\'V5.06 update 7 (build 960)\\\', folder: \\\'d:Keil_v5ARMARMCCBin\\\' compiling main.c... .USERFreeRTOSConfig.h(79): error:  #130: expected a \\\"{\\\"       extern uint32_t SystemCoreClock; .FreeRTOSportableportmacro.h(210): warning:  #12-D: parsing restarts here after previous syntax error   { .FreeRTOSportableportmacro.h(215): error:

    2024年02月10日
    浏览(44)
  • KEIL环境stm32移植FreeRTOS

    准备工作:keil软件,一份点灯代码,FreeRTOS源码。 1.FreeRTOS源码下载 直接在官网下载    FreeRTOS - Free RTOS Source Code Downloads, the official FreeRTOS zip file release download 2.解压资源 打开FreeRTOS文件夹 会用到的是Demo文件夹和Source文件夹。 Demo文件夹里面就是 FreeRTOS的相关例程,里面有各

    2024年02月03日
    浏览(40)
  • 【GD32/STM32】FreeRtos移植

    ​ (1)下载FreeRtos源码包 ​ FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions ​ (2)将源文件添加至工程 ​ (3)将GD32中的三个中断交由FreeRtos接管 ​ (4)配置管理FreeRTOS.h文件 ​ (5)FreeRtos基本使用方法 源码包结构 1.Demo中存放的

    2024年01月20日
    浏览(40)
  • STM32FreeRTOS操作系统移植

    移植好的FreeRTOS模板: 链接:https://pan.baidu.com/s/1_87VQAWXUl4jTqSCZ0MFjw?pwd=dw52  提取码:dw52 1.在工程中新建FreeRTOS文件夹 2.把源码source里面的文件全部粘贴进FreeRTOS文件夹中  3.在portable文件中只保留一下文件,其余删除  4.新建如下两个文件夹  5.在FreeRTOS_CODE目录下添加以下文件

    2024年02月08日
    浏览(46)
  • STM32移植FreeRTOS操作系统

    一、FreeRTOS源码下载 (1)移植钱得准备前菜对吧,我们先来去官网瞄一瞄 网址:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions 第一步:点击下载FreeRTOS 第二步:选择版本下载(我选择稳定版本) 注:我们下载的稳定版本不包含DEMO例

    2024年01月17日
    浏览(41)
  • STM32F407 移植 FreeRTOS

    本实验是基于正点原子 STM32F407ZG 探索者开发板完成的,所以需要一个STM32F407ZG 探索者开发板 用于移植的基础工程(下面会讲) FreeRTOS源码(下面会讲) 本实验所有用到的代码:基于正点原子STM32F407的FreeRTOS移植工程.zip 1.1 移植前准备 1.1.1 基础工程 由于后续需要用到 LED、

    2024年02月08日
    浏览(70)
  • STM32 CubeMX LwIP + freertOS 移植

    开发板: 官方 STM32F746  MCU型号:STM32F746NGH 网卡型号:LAN8742A  原理图如下 先用裸机测试LAN8742A的网卡驱动 使用CubeMX创建工程 系统时钟和时基定时器如下 无系统LWIP协议栈设置,静态IP地址,关闭DHCP 生产代码,下载进开发板。开发板网口与电脑网口通过网线直连,设置电脑本

    2024年01月16日
    浏览(87)
  • FreeRTOS学习笔记—任务创建和删除

    🎀 文章作者:二土电子 🌸 关注文末公众号获取其他资料和工程文件! 🐸 期待大家一起学习交流! FreeRTOS 的任务创建和删除相关的API函数有下面几个 xTaskCreate() 使用动态的方法创建一个任务 xTaskCreateStatic() 使用静态的方法创建一个任务 xTaskCreateRestricted() 创建一个使用 M

    2024年02月12日
    浏览(36)
  • PaddleOCR学习笔记2-初步识别服务

    今天初步实现了网页,上传图片,识别显示结果到页面的服务。后续再完善。 采用flask + paddleocr+ bootstrap快速搭建OCR识别服务。 代码结构如下: 模板页面代码文件如下: upload.html : result.html :  主要视图代码文件如下: 启动flask应用,测试结果如下:

    2024年02月09日
    浏览(39)
  • 野火霸道-V2+3.2寸屏+FreeRTOS+LVGL移植

    摘要 基于野火霸道-V2+3.2寸屏的开发板,下载器为STLINK 分为两个版本,FreeRTOS和裸机版本 裸机准备 lvgl v8.2版本的源码 野火的《触摸画板-3.2寸》与《基本定时器》的代码例程 移植 将基本定时器代码移植到触摸画板-3.2寸的例程中,实现LED的正常反转 将lvgl的源码移植到工程里

    2024年02月03日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包