FreeRTOS移植
一、获取FreeRTOS源码
1.1官网下载
进入官网直接下载
官网:https://www.freertos.org/zh-cn-cmn-s/
1.2 正点原子网盘下载
正点原子资料v10.4.6
例程git : https://gitee.com/yuan-zhenbin/freertos-code-repository.git
FreeRTOS资料网盘: http://www.openedv.com/docs/book-videos/zdyzshipin/4free/newfreertos.html
二、源码内容
名称 | 内容 |
---|---|
Free RTOS | 内核 |
Free RTOS-PLUS | 组件 |
tools | 工具 |
Github-Free RTOS-Home | Github仓库链接 |
Quick_Start_Guide | 快速入门官方指南 |
Upgrading-to-FreeRTOS-xxx | 升级指定版本文档链接 |
History | 历史更新记录 |
其他 | 其他 |
2.1 FreeRTOS内核
名称 | 描述 |
---|---|
Demo | FreeRTOS演示例程 |
License | 相关许可 |
Source | **FreeRTOS内核源码 |
Test | 公用以及移植层测试代码 |
2.1.1 Demo
支持多种芯片架构,多种不同型号芯片
2.1.2 Source
名称 | 描述 |
---|---|
include | 包含头文件✔ |
portable | 包含移植文件✔ |
croutine.c | 协程相关文件 |
event_groups.c | 事件相关文件 |
list.c | 列表相关文件✔ |
queue.c | 队列相关文件✔ |
stream_buffer.c | 流式缓冲区相关文件 |
tasks.c | 任务相关文件✔ |
timer.c | 软件定时器相关文件 |
portable文件夹
建立软件硬件的桥梁,根据硬件和编译器选择文件:这里选择Keil、MemMang、RVDS。
名称 | 描述 |
---|---|
Keil | 指向RVDS文件夹 |
RVDS | 不同内核芯片的移植文件 |
MemMang | 内存管理文件 |
三、FreeRTOS移植
3.1 准备内容
Free RTOS源码
基础工程
3.2 移植步骤
-
添加FreeRTOS源码
-
添加FreeRTOS.h
-
修改SYSTEM文件夹中的sys.c 、 delay.c 、usart.c
-
修改中断相关文件,Systick中断、 SVC中断、 PendSV中断
-
添加应用程序,验证是否成功
3.3 进行移植
3.3.1添加RTOS文件
这里选择HAL库内存管理例程作为基础工程
在Middlewares新建FreeRTOS文件夹
将FreeRTOS源码部分拷贝进文件夹
可以选择删除portable中的文件夹,这里只保留Keil、MemMang、RVDS。
3.3.2将文件添加到工程
打开基础工程,新建两个文件分组。Middlewares/FreeRTOS_CORE和Middlewares/FreeRTOS_PORT
CORE添加对应的文件
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
PORT添加对应的文件
添加头文件路径,将include和portable中对应的内核版本添加到头文件路径中
3.3.3 添加FreeRTOSConfig.h文件
裁剪不需要的功能,节约内存资源,有三种获取方式
-
用户自行缩写,
-
参考官方demo配置
-
用正点原子官方写好的
拷贝到基础工程文件的User文件夹
3.3.4 修改system文件
修改sys.h
使其支持OS
修改usart.c
Free RTOS没有 µC/OS对于中断的处理机制。删除osintenter和osintexit
删除下列代码
修改delay.c
删除35行到112
添加Free RTOS相关代码
extern void xPortSysTickHandler(void);
修改中断函数
改为
void SysTick_Handler(void)
{
uint32_t ulPreviousMask;
HAL_IncTick();
/* OS 开始跑了,才执行正常的调度处理 */
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Pend a context switch. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
}
}
修改延时初始化函数
改为
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS
uint32_t reload;
#endif
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
g_fac_us = sysclk;
#if SYS_SUPPORT_OS
reload = sysclk;
/* 使用 configTICK_RATE_HZ 计算重装载值
* configTICK_RATE_HZ 在 FreeRTOSConfig.h 中定义
*/
reload *= 1000000 / configTICK_RATE_HZ;
/* 删除不用的 g_fac_ms 相关代码 */
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
SysTick->LOAD = reload;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
#endif
}
修改微秒函数
改为
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;
}
}
}
/* 删除适用于 µC/OS 用于解锁任务调度器的自定义函数 */
}
修改毫秒函数
改为
void delay_ms(uint16_t nms)
{
uint32_t i;
for (i=0; i<nms; i++)
{
delay_us(1000);
}
}
修改头文件
/* 添加公共头文件 (FreeRTOS 需要用到) */
#include "FreeRTOS.h"
#include "task.h"
修改中断相关文件
在stm32f4xx_it.c中将HAL库提供的system,SVC,PendSV进行宏开关
导入sys.h
/* Includes --------------------------------------*/
/* 导入 sys.h 头文件 */
#include "./SYSTEM/SYS/sys.h"
将几个中断更改为条件编译
SVC
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
/* 加入宏开关 */
#if (!SYS_SUPPORT_OS)
void SVC_Handler(void)
{
}
#endif
PendSV
/**
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
/* 加入宏开关 */
#if (!SYS_SUPPORT_OS)
void PendSV_Handler(void)
{
}
#endif
SysTick
#if (!SYS_SUPPORT_OS)
void SysTick_Handler(void)
{
HAL_IncTick();
}
#endif
最后一步
FreeRTOSconfig.h中,通过该定义找到需要修改的文件,此处为stm32f429xx.h
将4U改为4
编译
还可以做的事
修改工程目标名称
移除USMART调试组件,删除main.c的引用。
添加定时器驱动
结束
烧入程序测试是否成功