实时操作系统FreeRTOS移植教程

描述

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源码下载地址

RTOSRTOS

2.FreeRTOS移植

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

RTOS

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

RTOS

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

RTOS

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

RTOS

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

RTOS

      RVDS中只保留ARM_CM3文件

RTOS

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

RTOS

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

RTOS

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

RTOSRTOS

      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();
	}
}
RTOS

      在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   
RTOS

      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);
	}
}

 


 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分