FreeRTOS移植STM32超详细(以STM32F103ZE为例)

这篇具有很好参考价值的文章主要介绍了FreeRTOS移植STM32超详细(以STM32F103ZE为例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我刚学FreeROTS时想移植到STM32,找了网上很多资料,但大多都不是很完整,于是我把我自己的移植过程分享出来,供大家参考。

我们以STM32F103ZE,正点原子的跑马灯实验为例,

准备工作:

跑马灯实验工程

FreeRTOS文件源码(可在官方下载)

 文章来源地址https://www.toymoban.com/news/detail-475211.html

FreeRTOS移植STM32超详细(以STM32F103ZE为例)FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

第一步  移植文件到工程

首先在工程目录新建一个名为FreeRTOS的文件夹

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

然后打开从FreeRTOS官方下载的文件中路径为FreeRTOSv202212.01\FreeRTOS中的Source

文件夹

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

将里面的文件全部复制到工程目录的FreeRTOS文件夹 

 FreeRTOS移植STM32超详细(以STM32F103ZE为例)

为了更加简洁,我们新建一个Source文件夹,将外面的.c文件放进去 

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 回到官方下载的FreeRTOS文件中,在Demo文件夹中找到对应的内核

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

打开文件夹复制里面的FreeRTOSCongic.h文件放到工程文件FreeRTOS文件夹中的include目录里

FreeRTOS移植STM32超详细(以STM32F103ZE为例) 

这是我们的文件移植已经完成了

到目前为止FreeRTOS源码被我们分成三部分

① include目录

② portable目录

③ source目录

包含的是FreeRTOS核心功能源文件及头文件 .c和.h,这两部分的文件是通用的,基本不需要修改,需要移植修改的目录,这与编译器和所使用的CPU有关,属于RTOS硬件接口层。

Portable目录是系统和硬件的桥梁,所以我们下一步就要在Portable文件夹中找到自己MCU与编译环境的文件

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

 只需要保留这三个文件夹,其余的可删除

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

第二步 工程文件添加

打开工程,新建一个名为 FreeRTOS_COR 的组,把Source目录的全部文件添加进去

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

然后再新建一个名为 FreeRTOS_PORTABLE 的组,添加Portable目录中的MemMang文件夹中的heap4.c(这是重要的内存管理文件)

FreeRTOS移植STM32超详细(以STM32F103ZE为例) 

 再添加portable->RVDS->AMR_CM3中的port文件

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 最终是这样的

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

 然后添加它们的头文件

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 编译发现没有错误

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

③文件的配置

虽然没有错误了,但还有些步骤要做

先把FreeRTOSConfig.h文件添加进工程

 FreeRTOS移植STM32超详细(以STM32F103ZE为例)

然后在FreeRTOSConfig.h中添加

#define xPortPendSVHandler   PendSV_Handler

#define vPortSVCHandler   SVC_Handler

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

编译,发现有重复定义的错误 

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

 解决方法:进入对应的文件stm32f1xx_it.c屏蔽重复的3个函数

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 把 SysTick_Handler中断函数也注释了,因为我们等下要在delay文件里建立新的中断函数

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

再次编译已发现没有错误了

最后还需进行一些配置

将以下代码替换delay.c中的代码

#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h"					//ucos 使用	  
#endif

#if SYSTEM_SUPPORT_RTOS
#include "includes.h"

#define OS_TICKS_PER_SEC	configTICK_RATE_HZ	
#define OSRunning			xSchedulerRunning

#endif
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//使用SysTick的普通计数模式对延迟进行管理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/2
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.2修改说明
//修正了中断中调用出现死循环的错误
//防止延时不准确,采用do while结构!

//V1.3修改说明
//增加了对UCOSII延时的支持.
//如果使用ucosII,delay_init会自动设置SYSTICK的值,使之与ucos的TICKS_PER_SEC对应.
//delay_ms和delay_us也进行了针对ucos的改造.
//delay_us可以在ucos下使用,而且准确度很高,更重要的是没有占用额外的定时器.
//delay_ms在ucos下,可以当成OSTimeDly来用,在未启动ucos时,它采用delay_us实现,从而准确延时
//可以用来初始化外设,在启动了ucos之后delay_ms根据延时的长短,选择OSTimeDly实现或者delay_us实现.

//V1.4修改说明 20110929
//修改了使用ucos,但是ucos未启动的时候,delay_ms中中断无法响应的bug.
//V1.5修改说明 20120902
//在delay_us加入ucos上锁,防止由于ucos打断delay_us的执行,可能导致的延时不准。
// 	 

static u8  fac_us=0;//us延时倍乘数			   
static u16 fac_ms=0;//ms延时倍乘数,在ucos下,代表每个节拍的ms数


   void SysTickInit()
{
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8,HCLK = 72MHZ
	fac_us=SystemCoreClock/8000000;				//为系统时钟的1/8  ,计算9次,9
	fac_ms=(u16)fac_us*1000;	
}
	void SysTick_Handler(void)
{
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
       xPortSysTickHandler();
    }
}	   
//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
	u32 reload;
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); 
	fac_us=SYSCLK;							//不论是否使用OS,fac_us都需要使用
	reload=SYSCLK;							//每秒钟的计数次数 单位为M	   
	reload*=1000000/configTICK_RATE_HZ;		//根据configTICK_RATE_HZ设定溢出时间
											//reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右	
	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数.		    								   
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的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864 

			 

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.h同理

#ifndef __DELAY_H
#define __DELAY_H 			   
#include "sys.h"  
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//使用SysTick的普通计数模式对延迟进行管理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/2
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.2修改说明
//修正了中断中调用出现死循环的错误
//防止延时不准确,采用do while结构!

//V1.3修改说明
//增加了对UCOSII延时的支持.
//如果使用ucosII,delay_init会自动设置SYSTICK的值,使之与ucos的TICKS_PER_SEC对应.
//delay_ms和delay_us也进行了针对ucos的改造.
//delay_us可以在ucos下使用,而且准确度很高,更重要的是没有占用额外的定时器.
//delay_ms在ucos下,可以当成OSTimeDly来用,在未启动ucos时,它采用delay_us实现,从而准确延时
//可以用来初始化外设,在启动了ucos之后delay_ms根据延时的长短,选择OSTimeDly实现或者delay_us实现.

//V1.4修改说明 20110929
//修改了使用ucos,但是ucos未启动的时候,delay_ms中中断无法响应的bug.
//V1.5修改说明 20120902
//在delay_us加入ucos上锁,防止由于ucos打断delay_us的执行,可能导致的延时不准。
// 	 	 
void delay_init(u8 SYSCLK);
void delay_ms(u32 nms);
void delay_us(u32 nus);
void delay_xms(u32 nms);
void SysTickInit();
#endif






























再次编译提示“xTaskGetSchedulerState”没有定义

 

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 

我们只需在FReeRTOS.h中加上这句定义就行了

#define INCLUDE_xTaskGetSchedulerState          1

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

 再次编译0错误

这样移植工作就完成了

加上主程序,实现点灯实验

#include "stm32f10x.h"
#include "delay.h"    
#include "usart.h"
#include "LED.H"
/* FreeRTOS头文件 */
#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 *pvParameters);    //任务函数
 
#define LED1_TASK_PRIO        3                    //任务优先级
#define LED1_STK_SIZE         50              //任务栈大小    
TaskHandle_t LED1Task_Handler;            //任务句柄
void led1_task(void *pvParameters);    //任务函数
 
 
static int TaskRun1,TaskRun2;  //用来观察任务运行

void BoardInit(void)  //设置初始化环境
{
    SysTickInit();   //系统时钟配置
	delay_init(72);  //延迟函数配置
	LED_Init();
    uart_init(115200);
}
 
 
//开始任务任务函数
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();            //退出临界区
}
 

int main(void)
{    
//  BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
    BoardInit();   //设置初始化环境
    printf("Welcome to FreeRTOS,CoreClock:%d\r\n",SystemCoreClock);
     
    //创建开始任务
    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();                                                     //开启任务调度   
}
 
//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
		TaskRun1=1;
		TaskRun2=0;
		LED0=~LED0;
		printf("Task1Running\n");
        vTaskDelay(500);
    }
}   
 
//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
		TaskRun1=0;
		TaskRun2=1;
		LED1=~LED1;
		printf("Task2Running\n");
        vTaskDelay(800);
    }
}

FreeRTOS移植STM32超详细(以STM32F103ZE为例)

成功点亮! 

 

到了这里,关于FreeRTOS移植STM32超详细(以STM32F103ZE为例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 学习OSAL并移植到STM32F103开发板上

    代码参考出处:https://github.com/mcuwty/osal.git 我在此此基础上做了整理,移植到了stm32f103上:demo链接: https://pan.baidu.com/s/1WoL8QCnicxO11hdeh4uh2Q 提取码: wsn3 参考资料: 学习笔记(二)——BLE协议栈OSAL - 知乎 (zhihu.com)   OSAL:即操作系统抽象层,它并不是一个传统意义上的操作系统

    2024年03月26日
    浏览(60)
  • STM32F103RCT6 -- 基于FreeRTOS 的USART1 串口通讯

    使用 FreeRTOS 提供的队列(Queue)机制来实现数据的接收和发送 TX - PA9 RX - PA10 波特率:9600 数据位:8bit 校验位:无 停止位:1bit 数据格式: RX: 55 AA 06 00 06 31 02 24 01 FC 80 TX: 55 AA 06 00 06 32 01 24 01 B8 70 55 AA – 帧头 06 - 数据字节数,不包括帧头,不包括校验位 00 06 – 模块 31 02 24

    2024年02月16日
    浏览(14)
  • STM32---stm32f103c8t6与stm32f103zet6之间的代码移植转换

    目录 一、将c8t6转换为zet6 1、修改启动文件 2、修改芯片 3、将MD修改为HD  4、下载器的修改 5、修改完成,编译成功  二、将zet6转换为c8t6 最终结果如下:   将STM32F103C8改为STM32F103ZE   基本相同,反向即可。    

    2024年02月06日
    浏览(21)
  • 初步了解STM32的学习笔记(以STM32F103C8T6为例)

      STM32F103C8T6属于主流系列STM32F1 内核是ARM Cortex-Mex3 主频为72Hz RAM:20K(SRAM) ROM:64K(Flash) 封装:LQFP48 供电:2~3.6V(一般为3.3) (注意:以前51用的是5V,而USB也是5V,所以直接插上,而stm32会加上一个稳压芯片,让电压为3.3V) (所有图都是用的是B站上整理过的)  表里面

    2024年02月05日
    浏览(22)
  • 【STM32 IAP技术实现】适合小白“食用”(以STM32F103C8T6为例)

      想必大家对 单片机烧录 一词都不陌生,就是将程序下载到我们的板子(MCU)里面。常见的烧录方法有用Keil下载,或者是编译出Hex文件通过烧录软件(上位机例如:muisp、flymcu)、烧录器软件(例如:J-LINK、ST-LINK)烧录,从程序的角度来看通过烧录,它被“更新”了。

    2024年02月03日
    浏览(18)
  • 用keil的时候没有安装对应MCU的库,以STM32F103F为例

    安装keil的时候没有用到这个芯片就没有安装对应的库。重新安装之后遇到的几个坑: 打开keil显示没有这个型号,解决方法是安装对应的库。STM32F103F要安装Keil.STM32F1xx_DFP.2.4.1.pack。 安装完库之后,点击Option for target,查看一下Device里面有没有对应型号的MCU可以选择。 确认安装

    2024年02月10日
    浏览(30)
  • 全网最简单的stm32f103c8t6移植ucosiii教程(附移植好的工程)

       最近在做一个机器人项目,需要使用到stm32f103c8t6核心板。考虑程序中的多任务特性,因此决定使用ucosiii用于多任务管理。ucosiii移植可能对于一些嵌入式老鸟来说,可能是信手拈来,但是对于很多新手特别是刚入门的小白来说还是有一定的难度的。尤其是全网的移植教程

    2024年02月16日
    浏览(17)
  • MDK Keil5 创建Stm32工程-理论篇(这里以Stm32F103Zet6为例)

    整个工程可以粗略的划分为几个文件夹: BSP 底层驱动比如GPIOTimer等驱动文件 CMSIS 内核相关的文件 Firmware 生成的固件下载文件 Mycode 用户编写的相关文件,主要编写的文件都在这个文件夹里 Project 工程文件 startup 芯片启动文件 STM32F10x_FWLib 标准库文件 USER 主函数等文件 readm

    2023年04月24日
    浏览(49)
  • 正点原子stmf103zet6代码移植为stm32f103c8t6(库函数版)

    目录 1、打开正点原子的工程模板template, 点击魔术棒  2、 修改芯片型号 为stm32f103c8

    2024年02月01日
    浏览(26)
  • 【U8G2库移植到STM32F103C8T6上】

    最近在B站上刷到了一位up主设计的oled丝滑界面WouoUI,一个优雅得比较像话的UI框架,128 * 64 经过询问,得知up用的是U8G2库,U8G2多用于arduino编译器上,但是我们学校常用的是stm32。 所以经过一段时间的研究,我将U8G2库移植到了stm32f103c8t6上进行使用。 关于U8G2的使用,可以参考

    2024年02月11日
    浏览(17)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包