提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:
本文是我根据正点原子教学移植后的记录贴 ,有错误欢迎指出下
提示:以下是本篇文章正文内容,下面案例可供参考
一、stm32如何创建FreeRTOS初始工程?
二、步骤
1.源码下载和库的引入
第一步先去FreeRTOS官网(https://www.freertos.org/)下载它的源代码,也可以去正点原子官方资料库里面找到。
我是直接下载了它的内核
下载第一个压缩包
压缩包下载完解压后我们需要拿到以下个文件 (其余的可以留备份后删除)
#注意 使用stm32开发板的 portable文件夹只需要留下面几个文件(其余的可以留备份后删除)
准备好以上文件后 随便打开一个正点原子的简单工程
我这边跟着学习的时候打开的是跑马灯的工程
添加这两个文件作为头文件
RVDS文件夹我选择的ARM_CM3 因为我使用的是F1系列的开发板
如果是f4系列要选择ARM_CM4F
创建两个新的分组如图所示 把需要的.c文件全部添加进去
上述都完成后 我们工程如果编译的话会报错
因为缺失了一个配置文件FreeRTOSconfig.h
推荐直接去正点原子工程内的include文件夹内直接获取,是配置过的。
放到我们自己工程里的include里,再编译就不会报错了
2.代码修改
代码如下:
修改delay.c文件,把以下代码加进去 SYSTEM_SUPPORT_OS
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" //FreeRTOS使用
#include "task.h"
#endif
stm32的标准工程都有一个usart.c的文件,把以下代码加进去
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" //ucos 使用
#endif
OSIntEnter和OSIntExti函数 我们freertos不需要 直接屏蔽掉
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
//#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
//OSIntEnter();
//#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
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;//接收数据错误,重新开始接收
}
}
}
}
//#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
//OSIntExit();
//#endif
}
delay.c 中systick中断服务函数修改成如下 头文件不要忘记引用
修改之后
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" //FreeRTOS使用
#include "task.h"
#endif
extern void xPortSysTickHandler(void);
//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler();
}
}
初始化延迟函数
configTICK_RATE_HZ这个参数是在freertosconfig.h里面设置的一般都是设置为1000 (1ms)
SysTick_CLKSource_HCLK_Div8是AHB的1/8
我们这里用的是SysTick_CLKSource_HCLK AHB
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init()
{
uint32_t 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
}
//延时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)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
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);
}
完成上述步骤后把工程中stm32f10x_it.c文件中的void SVC_Handler(void)、void PendSV_Handler(void)、void SysTick_Handler(void)这三个函数屏蔽掉,不然编译会错误。
总结
以上都按步骤做完后,freertos移植的第一步就完成了