全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

实时操作系统FreeRTOS移植教程

时间:2022-06-08 09:23

人气:

作者:admin

标签: STM32  FreeRTOS 

导读:Free 即免费的,RTOS 全称是 Real Time Operating System,中文就是实时操作系统。注意,RTOS 不是指某一个确定的系统,而是指一类系统。比如 uC/OS,FreeRTOS,RTX,RT-Thread 等这些都是 RTOS 类操作...

1.FreeRTOS简介

Free 即免费的,RTOS 全称是 Real Time Operating System,中文就是实时操作系统。注意,RTOS 不是指某一个确定的系统,而是指一类系统。比如 uC/OS,FreeRTOS,RTX,RT-Thread 等这些都是 RTOS 类操作系统。
FreeRTOS 是 RTOS 系统的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,当然,FreeRTOS 不仅局限于在微控制器中使用。但从文件数量上来看 FreeRTOS 要比uC/OSII 和 uC/OSIII 小的多。
FreeRTOS特点

  • FreeRTOS 的内核支持抢占式,合作式和时间片调度。
  • 提供了一个用于低功耗的 Tickless 模式。
  • 系统的组件在创建时可以选择动态或者静态的 RAM,比如任务、消息队列、信号量、软件定时器等等。
  • FreeRTOS 系统简单、小巧、易用,通常情况下内核占用 4k-9k 字节的空间。
  • 高可移植性,代码主要 C 语言编写。
  • 高效的软件定时器、强大的跟踪执行功能、堆栈溢出检测功能。
  • 任务数量不限。

FreeRTOS源码下载:FreeTOS源码下载地址

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

2.FreeRTOS移植

1.打开下载好的FreeRTOS文件夹,我们发现会有两个FreeRTOS的文件夹,我们这里以最基本的源码作为移植示例。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

2.打开FreeRTOS/Source,此文件夹中保存的即为FreeRTOS源码,接下来我们找一个简洁的工程移植FreeRTOS系统。将Source复制到我们要移植的工程中。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

3.在要移植的工程中创建FreeRTOS文件夹。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

4.将源码复位到该文件夹中。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

5.删除不需要的文件:在portable中只保留下面两个文件夹即可。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

RVDS中只保留ARM_CM3文件

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

6.打开工程,添加.c文件到工程中,添加头文件路径。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

在官方的参考例程里面我们发现有这个,将这个文件拷贝到我们要移植的工程下。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

存放路径可以随便选择,只要在KEIL中添加好相应路径即可。重新编译工程。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70pYYBAGKW5TeAcmWDAACm8hFxmyM000.png

7.提供系统心跳值函数。

#include "FreeRTOS.h"					//FreeRTOS使用		  
#include "task.h" 
extern void xPortSysTickHandler(void);
/*****************滴答定时器初始化******************/
void SysTick_Init(void)
{
	SysTick->CTRL&=~(1<<2);//外部时钟源9MHZ
	SysTick->CTRL|=1<<1;//开中断
	SysTick->VAL=0;
	SysTick->LOAD=9000*configTICK_RATE_HZ;//1s
	SysTick->CTRL|=1<<0;//使能定时器
}
/*滴答定时器中断,为FreeRTOS提供节拍数*/
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
	{
		xPortSysTickHandler();
	}
}
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

在FreeRTOSconfig.h中设置相应的宏

/*FreeRTOS与软件定时器相关配置*/
#define configUSE_TIMERS	 1       //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY	 (configMAX_PRIORITIES-1)  //软件定时器优先级
#define configTIMER_QUEUE_LENGTH		 5   //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH	 (configMINIMAL_STACK_SIZE*2)    //软件定时器任务堆栈大小
#define INCLUDE_xTaskGetSchedulerState     1   
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70

8.延时函数修改

(1)可以直接调用FreeRTOS中提供的延时函数,不过调用该函数会在延时时会进行任务切换,若不想在延时中进行任务切换,则可调用下面的模拟延时函数。通过设置宏FreeRTOS_OS。

/**************微妙延时函数*************/
void Delay_Us(int time)
{
	#ifdef FreeRTOS_OS
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
	ticks=time*9; 						//需要的节拍数 
	told=SysTick->VAL;        //刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;
		if(tnow!=told)	
		{
			if(tnow=ticks)break;			//时间超过/等于要延迟的时间,则退出.
		}
	}
	#else
	int i,j;
	for(i=0;i

(2)微妙延时函数

/**************微妙延时函数*************/
void Delay_Us(int time)
{
	#ifdef FreeRTOS_OS
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
	ticks=time*9; 						//需要的节拍数 
	told=SysTick->VAL;        //刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;
		if(tnow!=told)	
		{
			if(tnow=ticks)break;			//时间超过/等于要延迟的时间,则退出.
		}
	}
	#else
	int i,j;
	for(i=0;i

9.任务设置模板

#define START_TASK_PRIO 1        //任务优先级
#define START_STK_SIZE 128       //任务堆栈大小
TaskHandle_t StartTask_Handler;   //任务句柄
void start_task(void *pvParameters);//任务函数

#define LED0_TASK_PRIO 3     //任务优先级
#define LED0_STK_SIZE 50     //任务堆栈大小
TaskHandle_t LED0Task_Handler; //任务句柄
void LED0_task(void);         //任务函数

#define key_TASK_PRIO 2     //任务优先级
#define key_STK_SIZE 50      //任务堆栈大小
TaskHandle_t keyTask_Handler; //任务句柄
void key_task(void);          //任务函数

int main()
{
	SysTick_Init();
	Beep_Init();
	Led_Init();
	Key_Init();
	Usartx_Init(USART1,115200,72);
	TIMx_Init(TIM2,72,20*1000);
	printf("USART1初始化完成\r\n");
	
	//创建任务
	xTaskCreate( (TaskFunction_t)start_task,//任务函数
								(const char *)"start_task",//任务名称
								 (uint16_t)START_STK_SIZE,//堆栈大小
									NULL,           //传递给任务函数的参数
								 (UBaseType_t)START_TASK_PRIO,//任务优先级
								 (TaskHandle_t *)&StartTask_Handler);//任务句柄
		vTaskStartScheduler();     //开启任务调度
}

10.任务函数

/*开始任务函数*/
void start_task(void *pvParameters)
{
	taskENTER_CRITICAL();  //进入临界区
	//创建LED0任务
	xTaskCreate( (TaskFunction_t  )LED0_task,//任务函数
								(const char    *)"start_task",//任务名称
								 (uint16_t)LED0_STK_SIZE,//堆栈大小
									NULL,           //传递给任务函数的参数
								 (UBaseType_t   )LED0_TASK_PRIO,//任务优先级
								 (TaskHandle_t *)&LED0Task_Handler);//任务句柄

	xTaskCreate(  (TaskFunction_t )key_task,//任务函数
								(const char    *)"KEYt_task",//任务名称
								(uint16_t )key_STK_SIZE,//堆栈大小
								NULL,           //传递给任务函数的参数
								(UBaseType_t    )key_TASK_PRIO,//任务优先级
								(TaskHandle_t  *)&keyTask_Handler);//任务句柄
	vTaskDelete(StartTask_Handler); //删除开始任务	
	taskEXIT_CRITICAL();            //退出临界区						
}

11.任务执行

void LED0_task(void)
{
	while(1)
	{
		LED1=!LED1;
		vTaskDelay(500);
	}
}
void key_task(void)//任务函数
{
	u8 key=0;
	while(1)
	{
		key=Key_Scan();
		if(key)
		{
			printf("key=%d\n",key);
		}
		vTaskDelay(10);
	}
}


温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信