根据正点原子官方书籍学习FreeRTOS【第二天,第三天】

2.1 FreeRTOS移植

  2.1.1 移植准备

  准备一个用以移植的基础工程和FreeRTOS源码。

1.基础工程,正点原子开发文档中以标准例程-HAL库的内存管理的基础工程进行移植。所以我们直接去找基础工程。

首先去往网盘,资料查找在第一章已经说明。

下载好后如图所示

2 FreeROTS源码,昨天已经下载好了 如图所示

 在做好移植准备后 就可以开始我们的移植过程了。

2.1.2 开始移植

①在基础工程的 Middlewares 文件夹中新建一个 FreeRTOS 子文件夹,如图所示

要将 FreeRTOS 的源代码添加到刚刚新建的 FreeRTOS 子文件中

全选复制 去刚刚新建的FreeRTOS下复制

打开基础工程,新建两个文件分组,分别为 Middlewares/FreeRTOS_CORE

Middlewares/FreeRTOS_PORT,如图所示
然后新建两个文件夹并重命名
重命名后如图所示
Middlewares/FreeRTOS_CORE 分组用于存放 FreeRTOS 的内核 C 源码文件 如图:
添加后如图所示
Middlewares/FreeRTOS_PORT 分组用于存放 FreeRTOS 内核的移植文件需要添加两类文
件到这个分组,分别为 heap_x.c port 文件。如图
不同的开发板,所使用的 port 文件是不同的,我们用stm32f103所以去对应的文件夹下寻找,各位可根据自己的开发板型号自行寻找。
添加后如图所示
③添加头文件路径
接下来添加 FreeRTOS 源码的头文件路径,需要添加两个头文件路径,毋庸置疑,其中一
个头文件路径就是 FreeRTOS/include ,另外一个头文件路径为 port 文件的路径,根据表 2.1.2.4
中不同类型开发板与 port 文件的对应关系进行添加即可
④添加   FreeRTOSConfig.h 文件
正点原子给了三种途径获取,我们不加以讲解,直接去demo文件中获取
我就放在User目录下

2.1.3 修改SYSTEM文件

①sys.h 文件的修改很简单,在 sys.h 文件中使用了宏 SYS_SUPPORT_OS 来定义是否支持 OS
因为要支持 FreeRTOS ,因此应当将宏 SYS_SUPPORT_OS 定义为 1,如图
②删除usart.c文件中的OSINtEnter()和OSIntExit()

接下来 usart.c 要修改的第二个地方就是导入的头文件,因为在串口的中断服务函数当中已
经删除了 µC/OS 的相关代码,并且也没有使用到 FreeRTOS 的相关代码,因此将 usart.c 中包含
的关于 OS 的头文件删除
③delay文件修改 
分为三个步骤:删除适用于 µC/OS 但不适用于 FreeRTOS 的相关代码、添加
FreeRTOS 的相关代码、修改部分内容。
一共需要删除 1 个全局变量、 6 个宏定义、 3 个函数,这些要删除的代码在使用 µC/OS
时候会使用到,但是在使用 FreeRTOS 的时候无需使用
一个全局变量
6个宏定义
三个函数
全部删掉,然后 添加 FreeRTOS 的相关代码
需要在 delay.c 文件中使用 extern 关键字导入一个 FreeRTOS 函数
system最后要修改的内容包括两个,分别是包含头文件和 4 个函数
首先来看需要修改的 4 个函数,分别是 SysTick_Handler()delay_init()delay_us()
delay_ms()
首先是SysTick_Handler函数改为
void SysTick_Handler(void)
{ HAL_IncTick();
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) /* OS开始跑了,才执行正常的调度处理 */
    {
        xPortSysTickHandler();
    }
}
如图
然后是函 数 delay_init() ,主要用于初始化 SysTick,要修改的部分主要为 SysTick 的重装载值以及删除不用的代码,和文档上略微有所出入

void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS /* 如果需要支持OS. */
    uint32_t reload;
#endif
    SysTick->CTRL = 0;                                          /* 清Systick状态,以便下一步重设,如果这里开了中断会关闭其中断 */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);   /* SYSTICK使用内核时钟源8分频,因systick的计数器最大值只有2^24 */

    g_fac_us = sysclk / 8;                                      /* 不论是否使用OS,g_fac_us都需要使用,作为1us的基础时基 */
#if SYS_SUPPORT_OS                                              /* 如果需要支持OS. */
    reload = sysclk / 8;                                        /* 每秒钟的计数次数 单位为M */
    reload *= 1000000 / configTICK_RATE_HZ;                     /* 根据delay_ostickspersec设定溢出时间
                                                                 * reload为24位寄存器,最大值:16777216,在9M下,约合1.86s左右
                                                                 */
    SysTick->CTRL |= 1 << 1;                                    /* 开启SYSTICK中断 */
    SysTick->LOAD = reload;                                     /* 每1/delay_ostickspersec秒中断一次 */
    SysTick->CTRL |= 1 << 0;                                    /* 开启SYSTICK */
#endif
}

借鉴的是能跑的示例工程 按照文档上的会报错如图

修改后如图

函数 delay_us() 用于微秒级的 CPU 忙延时原本的函数 delay_us()延时的前后加入了自定义函数 delay_osschedlock()和 delay_osschedunlock()用于锁定和解锁 µC/OS 的任务调度器,以此来
让延时更加准确。在 FreeRTOS 中可以不用加入这两个函数,但是要注意的是,这会让函数delay_us()的微秒级延时的精度有所下降,修改后如图。
void delay_us(uint32_t nus)
{
    uint32_t ticks;
 uint32_t told, tnow, tcnt = 0;
 uint32_t reload = SysTick->LOAD;
 /* 删除适用于 μC/OS 用于锁定任务调度器的自定义函数 */
 ticks = nus * g_fac_us;
 told = SysTick->VAL;
 while (1)
 {
 tnow = SysTick->VAL;
 if (tnow != told)
 {
 if (tnow < told)
 {
 tcnt += told - tnow;
 }
 else
 {
 tcnt += reload - tnow + told;
 }
 told = tnow;
 if (tcnt >= ticks)
 {
 break;
 }
 }
 }
}

和示例文件略有出入 在此标记一下。

函数 delay_ms() 用于毫秒级的 CPU 忙延时,原本的函数 delay_ms() 会判断 µC/OS 是否运
行,如果 µC/OS 正在运行的话,就使用 µC/OS OS 延时进行毫秒级的延时,否则就调用函数
delay_us() 进行毫秒级的 CPU 忙延时。在 FreeRTOS 中,可以将函数 delay_ms()定义为只进行
CPU 忙延时,当需要 OS 延时的时候,调用 FreeRTOS 提供的 OS 延时函数 vTaskDelay() (在下
文讲解 FreeRTOS 时间管理的时候会对此函数进行分析)进行系统节拍级延时,函数 delay_ms()
修改后的代码如下所示:
void delay_ms(uint16_t nms)
{
    
 uint32_t i;
 
 for (i=0; i<nms; i++)
 {
 delay_us(1000);
 }
}
函数到这就修改完成了。
现在去修改头文件
根据上述步骤的修改, delay.c 文件中使用到了 FreeRTOS 的相关函数,因此就需要在 delay.c
文件中包含 FreeRTOS 的相关头文件,并且移除掉原本存在的 µC/OS 相关头文件。
修改前
修改后
到这system文件修改完成

2.1.4 修改中断相关文件

正点原子教程如图所示

我们首先要找到对应的文件,我使用的是F1系列的 
进入到文件中,先导入头文件
导入头文件后 将 HAL 库提供的这三个中断服务函数注释掉,这里采用宏开关的方式让 HAL 库中的这三个中断服务函数不加入编译。如图所示
最后 根据自己板子型号选择文件
我使用的stmf103的板子,流程如下
修改4U为4即可。

2.1.5 可选修改流程

①修改工程名。

②移除USMART组件

③添加定时器驱动

但是去到移植好的BSP库中发现还有SRAM文件所以直接复制两个到我们的移植文件夹下

到这我们就完成了环境的修改 接下来我们通过添加应用程序来测试是否移植成功。

2.1.6 添加应用程序

一修改,二添加。

①首先修改mian.c文件

/**
******************************************************************************
* @file
main.c
* @author
正点原子团队 (ALIENTEK)
* @version
V1.4
* @date
2022-01-04
* @brief
FreeRTOS 实验
* @license
Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
******************************************************************************
* @attention
*
* 实验平台 : 正点原子 STM32F103 开发板
* 在线视频 :www.yuanzige.com
* 技术论坛 :www.openedv.com
* 公司网址 :www.alientek.com
* 购买地址 :openedv.taobao.com
*
******************************************************************************
*/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"
int main ( void )
{
HAL_Init ();
/* 初始化 HAL */
sys_stm32_clock_init ( RCC_PLL_MUL9 ); /* 设置时钟 , 72Mhz */
delay_init ( 72 );
/* 延时初始化 */
usart_init ( 115200 );
/* 串口初始化为 115200 */
led_init ();
/* 初始化 LED */
lcd_init ();
/* 初始化 LCD */
key_init ();
/* 初始化按键 */
sram_init ();
/* SRAM 初始化 */
my_mem_init ( SRAMIN );
/* 初始化内部 SRAM 内存池 */
my_mem_init ( SRAMEX );
/* 初始化外部 SRAM 内存池 */
freertos_demo ();
/* 运行 FreeRTOS 例程 */
}
②添加 freertos_demo.c文件和freertos_demo.h文件
即可建立.c文件
/**
******************************************************************************
* @file main.c
* @author 正点原子团队(ALIENTEK)
* @version V1.4
* @date 2022-01-04
* @brief FreeRTOS 移植实验
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
******************************************************************************
* @attention
*
* 实验平台:正点原子 战舰 F103 开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
******************************************************************************
*/
#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
/*FreeRTOS********************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/*****************************************************************************/
/*FreeRTOS 配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */
/*****************************************************************************/
/* LCD 刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = { WHITE, BLACK, BLUE, RED,
 MAGENTA, GREEN, CYAN, YELLOW,
 BROWN, BRRED, GRAY};
/**
* @brief FreeRTOS 例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
 lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
 lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS Porting", RED);
 lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
 
 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();
}/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
 taskENTER_CRITICAL(); /* 进入临界区 */
 /* 创建任务 1 */
 xTaskCreate((TaskFunction_t )task1,
 (const char* )"task1",
 (uint16_t )TASK1_STK_SIZE,
 (void* )NULL,
 (UBaseType_t )TASK1_PRIO,
 (TaskHandle_t* )&Task1Task_Handler);
 /* 创建任务 2 */
 xTaskCreate((TaskFunction_t )task2,
 (const char* )"task2",
 (uint16_t )TASK2_STK_SIZE,
 (void* )NULL,
 (UBaseType_t )TASK2_PRIO,
 (TaskHandle_t* )&Task2Task_Handler);
 vTaskDelete(StartTask_Handler); /* 删除开始任务 */
 taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
 uint32_t task1_num = 0;
 
 while(1)
 {
 lcd_clear(lcd_discolor[++task1_num % 14]); /* 刷新屏幕 */
 lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
 lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS Porting", RED);
 lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
 LED0_TOGGLE(); /* LED0 闪烁 */
 vTaskDelay(1000); /* 延时 1000ticks */}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
 float float_num = 0.0;
 
 while(1)
 {
 float_num += 0.01f; /* 更新数值 */
 printf("float_num: %0.4f\r\n", float_num); /* 打印数值 */
 vTaskDelay(1000); /* 延时 1000ticks */
 }
配置如下内容
代码示意可去官方文档查看 或后续我的博客
添加Freertos_demo.h文件
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H
void freertos_demo(void);
#endif
为.h代码文件内容。
到此为止,移植内容结束 接下来我们        将进行移植实验来判断是否移植成功

2.2 FreeRTOS移植实验

其实正点原子就是对我们之前的行为载入开发板的代码和原理做一个解释,有兴趣的可以去查看官方文档的讲解或者我的后续补充。

就可以编译代码了

2.3bug解决

我出现了两个问题

1第一个问题是无法打开freertos_demo.h文件 是因为没有将头文件路径配置

2第二个问题是必须将FreeRTOS.h放在task.h路径前

首先我们发现task路径在FreeRTOS的子目录include里,所以我们可以把它放在FreeRTOS子目录下。重新配置头文件路径即可。
3 第三个问题就是
经查找是FreeRTOS.h文件中
将0改成1即可 但此后不报错屏幕常亮 只给串口发送一次数据
怀疑是task进程配置问题 后续继续解决
  • 30
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
正点原子(DFRobot)是一个提供电子开发平台和教育资源的公司,而FreeRTOS是一个开源的实时操作系统。正点原子FreeRTOS是基于FreeRTOS内核进行封装和优化的版本。它提供了一系列内核控制函数,用于管理任务、调度器、时间片等核心功能。这些内核控制函数由FreeRTOS内核所使用,一般情况下应用层程序不直接使用这些函数。在FreeRTOS官网上可以找到这些内核控制函数的详细说明和用法。其中,delay_init()函数用于根据FreeRTOS的系统时钟节拍来初始化滴答定时器,以设置滴答定时器的中断周期。滴答定时器是FreeRTOS提供的用于刷新系统时间和进行任务调度的定时器。需要注意的是,滴答定时器的时钟频率在正点原子FreeRTOS中被设置为AHB的频率,一般为72MHz。而系统时钟节拍由宏configTICK_RATE_HZ来设置,用户可以根据需求自由设置其值。值得提醒的是,FreeRTOS还提供了一些仅供系统内核使用的函数,用户应用程序一般不应直接调用这些API函数。这些API函数被称为系统内核控制函数,可以用于实现内核的管理和控制功能。在学习FreeRTOS中的内核控制函数时,可以参考相关的文档和教程,深入了解每个函数的功能和使用方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [正点原子FreeRTOS(上)](https://blog.csdn.net/zhuguanlin121/article/details/124237033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值