目录
一、FreeRTOS协议栈下载
二、准备工程文件与协议代码
三、移植FreeRTOS协议栈
一、FreeRTOS协议栈下载
1、官网下载
FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensionshttps://www.freertos.org/zh-cn-cmn-s/
2、网盘下载(访问密码:1666)
二、准备工程文件与协议代码
三、移植FreeRTOS协议栈
(FreeRTOS协议栈内容请自行百度,此处只是应用)
1、将\FreeRTOSv202212.00\FreeRTOS\Source内协议代码均复制到工程文件内新建文件夹“FreeRTOS”中
2、根据需求,删除 FreeRTOS\portable 内多余文件(也可不删,只为了精简工程文件的大小),最后保留文件如下
- Keil:基于Keil使用的底层接口文件,指向RVDS
- MemMang:内存管理选择
- RVDS:底层接口文件需要实际修改的文件
- readme:内核的基本介绍
3、在工程内添加协议栈
核心文件:
来源于 FreeRTOSv202212.00\FreeRTOS\Source 的C文件
底层接口:
- port:来源于 FreeRTOSv202212.00\FreeRTOS\Source\portable\RVDS\ARM_CM3
- heap_4:来源于 FreeRTOSv202212.00\FreeRTOS\Source\portable\MemMang
4、编译
报错:缺失文件 "FreeRTOSConfig.h"
5、补充文件
从例程中直接复制 "FreeRTOSConfig.h" 使用
6、重复编译
编译通过,移植完成。
四、示例演示
1、要实际使用FreeRTOS,需要提供滴答计时器作为OS系统刷新中断
#include "HW_SysTick_Interrupt.h"
#include "stm32f10x.h"
#include "FreeRTOS.h" //os 使用
#include "task.h"extern void xPortSysTickHandler(void);static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数/* 功 能: 滴答定时器 - 初始化* 输 入: * 输 出: * 返 回:* 备 注: 此处启用中断版本,故默认使用 1/1000 = 1ms 中断*/
void HW_SysTick_Interrupt_Init(void)
{ u32 reload;SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //选择外部时钟 HCLK/8fac_us=SystemCoreClock/1000000; //为系统时钟的1/8 reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为K reload*=1000000/configTICK_RATE_HZ; //根据delay_ostickspersec设定溢出时间//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右 fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK }///* 功 能: 滴答定时 - 中断
// * 输 入:
// * 输 出:
// * 返 回:
// * 备 注: OS初始化中断1000Hz
// */
//void HW_SysTick_Interrupt_Handler(void)
//{
// if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
// {
// xPortSysTickHandler();
// }
//}/* 功 能: 延时nus* 输 入: * 输 出: * 返 回:* 备 注: */
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){ if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.} };
}/* 功 能: 延时nms* 输 入: * 输 出: * 返 回:* 备 注: */
void delay_ms(u16 nms)
{ if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) { if(nms>=fac_ms) //延时的时间大于OS的最少时间周期 { vTaskDelay(nms/fac_ms); //OS延时}nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时 }delay_us((u32)(nms*1000)); //普通方式延时
}/* 功 能: 延时nms* 输 入: * 输 出: * 返 回:* 备 注: 此处启用中断版本,故默认使用 1/1000 = 1ms 中断*/
void delay_xms(u32 nms)
{u32 i;for(i = 0;i < nms;i++)delay_us(1000);
}
编译报警
需要开启(置一)
再次编译正常
2、main函数中创建开始任务 start_task
3、开始任务(start_task)中创建其他任务
4、执行其他任务
5、设置头文件,以及配置好任务参数后,编译通过。
6、实际运行后,在 vTaskStartScheduler (开启任务调度) -> xPortStartScheduler (开启时钟) -> prvStartFirstTask (开启第一个任务) 中跳到 HardFault_Handler(硬件错误)
7、排查错误
为中断异常导致的,FreeRTOS 使用的中断如下,需要修改中断
8、修改中断方法
①、修改启动文件,直接映射到port文件中
②宏定义
需要删除 stm32f10x_it 中的中断入口,避免二定义
9、编译运行后,预期正常
项目代码(访问密码:1666)