FreeRTOS创建笔记

在ZET6中的简单FreeRTOS 

硬件平台是ARM Cortex-M3

基于STM32F103ZET6芯片

最终的代码量有55KB

为什么要指定硬件平台进行搭建OS呢?

简单来说:就是避免在一个大循环内重复进行硬件资源的占用,降低功耗,提高效率

在后面 FreeRTOS 任务切换的时候需要我们了解 Cortex-M 内核架构相关的知识,否则的话根本看不懂任务切换的过程。

关于 Cortex-M 架构的讲解在 ARM 官网上就有,不过是英文的,叫做《The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors, 3rd Edition》。

但!这本书已经有中文翻译版了,叫做《ARM Cortex-M3 与 Cortex-M4 权威指南(第三版)》,
清华大学出版社。

书上对于 Cortex-M 架构的讲解非常详细,强烈建议那些想“深入了解” Cortex-M 架构的同学看一
下,如果英语 NB 的可以直接看英文原版的, ARM 官网直接下载,完全免费的。

 RTOS 类系统有很多, 为什么要选择 FreeRTOS ?

因为free 啊,免费,还能做很多公司的软件操作系统,又多人用。

说不定是找工作面试的考点

主要特点

● FreeRTOS 的内核支持抢占式, 合作式和时间片调度。
● SafeRTOS 衍生自 FreeRTOS, SafeRTOS 在代码完整性上相比 FreeRTOS 更胜一筹。
● 提供了一个用于低功耗的 Tickless 模式。
● 系统的组件在创建时可以选择动态或者静态的 RAM, 比如任务、消息队列、信号量、
软件定时器等等。
● 已经在超过 30 种架构的芯片上进行了移植。
● FreeRTOS-MPU 支持 Corex-M 系列中的 MPU 单元, 如 STM32F103。
● FreeRTOS 系统简单、小巧、易用, 通常情况下内核占用 4k-9k 字节的空间。
● 高可移植性,代码主要 C 语言编写。
● 支持实时任务和协程(co-routines 也有称为合作式、 协同程序, 本教程均成为协程)。
● 任务与任务、 任务与中断之间可以使用任务通知、消息队列、二值信号量、数值型信
号量、 递归互斥信号量和互斥信号量进行通信和同步。
● 创新的事件组(或者事件标志)。
● 具有优先级继承特性的互斥信号量。
● 高效的软件定时器。
● 强大的跟踪执行功能。
● 堆栈溢出检测功能。
● 任务数量不限。
● 任务优先级不限。

资料下载

首先下一个资料

FreeRTOS官网  全英文的 可见英语还是很重要的

可以看见有FreeRTOS和FreeRTOS-Plus巴拉巴拉,不管,打开第一个。

 

 有Demo License Source ,也不管,但我们要用的是Source里的源码,用来移植。

建立

首先!

把这里的文件建立在你想移植的工程中,当然要建立一个文件夹把上面的所有东西复制进去

然后!

向工程分组中加入添加这两个分组

然后把复制过来的文件按上面分别添加进去

MemMang 中是跟内存管理相关的文件,里面有 5 个 c 文件: heap_1.c、 heap_2.c、heap_3.c、 heap_4.c 和 heap_5.c。

这 5 个 c 文件是五种不同的内存管理方法,就像从北京到上海你可以坐火车、坐飞机, 如果心情好的话也可以走路,反正有很多种方法, 只要能到上海就行。这里也一样的,这 5 个文件都可以用来作为FreeRTOS 的内存管理文件, 只是它们的实现原理不同, 各有利弊。 这里我们选择 heap_4.c。

其中FreeRTOS_PORTABLE中两个文件分别在portable中的MemMang和RVDS中

 当然下面头文件路径也是少不了的

好了差不多了

编译一下

八个错,非常好,为什么说好呢,因为这样下来前面操作没错

都是关于“FreeRTOSConfig.h”的问题,缺少这个头文件

记得刚刚下载文件有个Demo吧?

我找的是F103_keil的 

把FreeRTOSConfig.h找个地方复制一下,

在工程文件夹FreeRTOS/include里就行

编译一下,没错了,就是这样,要是有问题,看看漏了哪个步骤,

或者关于你的呃。。平台的FreeRTOSConfig.h没找对

好!

改一下sys.h的预处理命令

改改文件就可以用了。真的

打开它 

就在第一行不用找了

支持它一下,改个0

接下来是usart.c

改一下其中的包含头文件

#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"         //os 使用
#endi

 接下来是串口中断服务程序

有两段函数,在使用 UCOS 的时候进出中断的时候需要添加OSIntEnter()和 OSIntExit(), 使用 FreeRTOS 的话就不需要了,所以将这两行代码删除掉

void USART1_IRQHandler(void)                	
{
	u8 Res;

    //OSIntEnter(); //需要删除

	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
		{
		Res =USART_ReceiveData(USART1);
		
		if((USART_RX_STA&0x8000)==0)
			{
			if(USART_RX_STA&0x4000)
				{
				if(Res!=0x0a)USART_RX_STA=0;
				else USART_RX_STA|=0x8000;	
				}
			else 
				{	
				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;  
					}		 
				}
			}   		 
     } 

	//OSIntExit();  	 //需要删除		
								 
} 

然后是delay.c

关于SysTick_Handler()、delay_init()、和定义的具体延时的函数ms或者us

养成改完一步就编译的好习惯

 好家伙 ,为什么说好呢,因为也还在预料之中

的错误提示表示在 port.c、 delay.c 和 stm32f10x_it.c 中三个重复定义的函数:
SysTick_Handler()、 SVC_Handler()和 PendSV_Handler()。

这三个函数分别为滴答定时器中断服务函数、 SVC 中断服务函数和 PendSV 中断服务函数,将 stm32f10x_it.c 中的三个函数屏蔽掉。

它们只有简单的声明,没有实际作用。 

编译一下

 好!

到了最后时刻了

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"


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

#define TASK1_TASK_PRIO		2
#define TASK1_STK_SIZE		120
void task1_task( void * pvParameters );
TaskHandle_t Task1Task_Handler;

#define TASK2_TASK_PRIO		3
#define TASK2_STK_SIZE		120
void task2_task( void * pvParameters );
TaskHandle_t Task2Task_Handler;


TaskHandle_t StartTask_Handler;

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 	 
	delay_init();	    				//延时函数初始化 
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED

    //创建开始任务
	xTaskCreate((TaskFunction_t	) start_task,            //任务函数
				(char *			) "start_task",          //任务名称
				(uint16_t		) START_STK_SIZE,        //任务堆栈大小
				(void *			) NULL,                  //传递任务函数的参数
				(UBaseType_t	) START_TASK_PRIO,       //任务优先级
				(TaskHandle_t *	) &StartTask_Handler );  //任务句柄
	
    vTaskStartScheduler();          //开启任务调度
}

void start_task( void * pvParameters )
{
	//创建任务1
	xTaskCreate((TaskFunction_t	) task1_task,
				(char *			) "task1_task",
				(uint16_t		) TASK1_STK_SIZE,
				(void *			) NULL,
				(UBaseType_t	) TASK1_TASK_PRIO,
				(TaskHandle_t *	) &Task1Task_Handler );
				
	//创建任务2
	xTaskCreate((TaskFunction_t	) task2_task,
				(char *			) "task2_task",
				(uint16_t		) TASK2_STK_SIZE,
				(void *			) NULL,
				(UBaseType_t	) TASK2_TASK_PRIO,
				(TaskHandle_t *	) &Task2Task_Handler );
	vTaskDelete(NULL);
}

//接下来都是一些简单的任务函数
void task1_task( void * pvParameters )
{
	char task1_num=0;
	while(1)
	{
		LED0=~LED0;
        task1_num++;
        vTaskDelay(1000);
		printf("Task1 running %d!!\r\n",task1_num);
	}
}

void task2_task( void * pvParameters )
{	
	char task2_num=0;
	while(1)
	{	
        LED1=~LED1;
		task2_num++;
        vTaskDelay(1000);
		printf("Task2 running %d!!\r\n",task2_num);
		if(task2_num == 5)
		{
            printf("delete task2!!\r\n");
			vTaskDelete(NULL);	
		}
	}
}



最后可以使用串口调试助手对程序进行检验,

这里只是用简单的led灯和串口输出来检验。

当然啦,这是对自己初步学习FreeRTOS时的笔记,并不是所谓的什么教程。

就这样吧。

 

 

 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值