0、RTOS概述

        RTOS(Real Time OS)即实时操作系统,根据各个任务的要求,进行资源(包括存储器、外设等)管理、消息管理、任务调度、异常处理等工作。在RTOS支持的系统中,每个任务均有一个优先级(类似前面章节的中断抢占优先级),RTOS根据各个任务的优先级,动态地切换各个任务,保证对实时性的要求。

        RTOS总是运行优先级最高且就绪的任务。

        实时多任务操作系统,以分时方式运行多个任务,任务之间的切换以优先级为根据。只有优先服务方式的RTOS才是真正的实时操作系统。

        使用实时操作系统还需要额外的ROM/RAM开销,2~5%的CPU额外负荷,以及内核的费用。

        使用实时操作系统的必要性:

  • 嵌入式实时操作系统提高了系统的可靠性
  • 提高了开发效率,缩短了开发周期。例如官方甚至提高网络协议栈、文件系统、图形界面(ucGUI、emWin、QT....)的支持。
  • 嵌入式实时操作系统充分发挥了32位CPU的多任务潜力(提高吞吐量,就是一个负载均衡)。

        当前RTOS已经广泛应用于各种嵌入式设备中,如智能可穿戴设备、智能家居设备等。且RTOS已成为嵌入式、物联网开发者的基础必备技能。对于应届生而言,掌握RTOS是求职应聘、参与产品项目开发的一个优势加分项

        如下所示为当前求职招聘的一些基本要求。

        市场上有各色各样的RTOS实时操作系统(UCOS、RT-Thread、FreeRTOS),FreeRTOS 最大的优势就是开源免费商业使用的话不需要用户公开源代码,也不存在任何版权问题,是当前小型嵌入式操作系统市场使用率最高的。故本文教程选用了FreeRTOS

1、下载FreeRTOS

        FreeRTOS官网链接如下:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensionsicon-default.png?t=N7T8https://www.freertos.org/

在本文档编写时,FreeRTOS最新版本为FreeRTOS 202212.01,因此本文基于此版本进行移植教程,即使后续版本更新,FreeRTOS的整体文件结构不会发生大改变,依然可以采用本文档进行指导移植操作。选择比此版本的更旧的版本移植操作也同本文大致保持一致。

下载源码后,解压打开FreeRTOS源码文件目录结构如下图所示:

2、FreeRTOS移植

        FreeRTOS文件夹下,有 DemoSource文件夹是移植过程中需要使用的,FreeRTOS文件夹下面的其它文件夹及文件可忽略。 

RTOS代码的核心包含在三个文件中:tasks.cqueue.clist.c。这三个文件位于FreeRTOS/Source目录。在该目录下还包含三个可选的文件:timers.c、event_groups.c、croutine.c、stream buffer.c,分别实现软件定时、事件组、协程功能和流式缓冲区。

FreeRTOS官方移植参考说明:Microcontrollers and compiler tool chains supported by FreeRTOS

移植步骤:

①、在KEIL工程主目录下创建FreeRTOS文件夹,然后在FreeRTOS中依次创建include、port、src文件夹,如下图所示。

②、进入下载的FreeRTOSv202212.01源码文件中,将FreeRTOSv202212.01\FreeRTOS\Source\include 的文件拷贝到KEIL工程的FreeRTOS/include中

③、进入FreeRTOSv202212.01\FreeRTOS\Source 目录,将 croutine.c、event groups.c、list.c、 queue.c、stream buffer.c、tasks.c、timers.c拷贝到KEIL工程的 FreeRTOS/src 路径。

④、进入 FreeRTOSv202212.01\FreeRTOS\Source\portable 目录,拷贝MemMang文件到KEIL工程中的FreeRTOS/port路径下。 


 

⑤、进入FreeRTOSv202212.01\FreeRTOS\Demo中,选择对应芯片的Demo例程,然后拷贝FreeRTOSConfig.h文件到 FreeRTOS/include 路径中。

本例程选择了STM32F407系列芯片进行移植,其它芯片的移植操作和本例程操作类似。

⑥进入FreeRTOSv202212.01\FreeRTOS\Source\portable\RVDS\ARM_CM4F,拷贝port.c和portmacro.h到 FreeRTOS/port 路径下。

⑦、将FreeRTOS代码添加到KEIL裸机工程设备树中。

        heap_x.c内存分配文件根据需要,只能加入一个!

⑧、打开FreeRTOSConfig.h文件,因MDK默认使用armcc编译器,需在FreeRTOSConfig.h文件中添加defined(_CC_ARM),避免源码找不到SystemCoreClock,详细添加如下:

/* Ensure stdint is only used by the compiler, and not the assembler. */
#if defined(__ICCARM__)||defined(__CC_ARM)||defined(__GNU__)
	#include <stdint.h>
	extern uint32_t SystemCoreClock;//系统时钟值168000000,在system_stm32f4xx.c中定义
#endif

⑨、编译整个工程,如果出现下面的报错信息,则需要修改FreeRTOSConfig.h对应的钩子函数的宏定义开关。

修改下面的这三个宏定义的值为0,即可解决编译报错问题。

#define configUSE_IDLE_HOOK				0	//设置为0,用户就不用自己写空闲任务
#define configUSE_TICK_HOOK				0	//宏开启的话,会导致SysTick的中断服务函数每过1ms调用一次或用户自定义
#define configCHECK_FOR_STACK_OVERFLOW	0	//栈溢出检测方法,如果使用的话,需要用户自己提供一个栈溢出处理钩子回调函数

3、编译运行FreeRTOS

        测试FreeRTOS源代码

#include "stm32f4xx.h"
#include "FreeRTOS/FreeRTOS.h"
#include "FreeRTOS/task.h"
#include <stdio.h>
#include "usart.h"

TaskHandle_t app_task1_handle = NULL;
TaskHandle_t app_task2_handle = NULL;
void app_task1(void* pvParameters);
void app_task2(void* pvParameters);

int main(void)
{
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
	//SysTick_Config(SystemCoreClock/configTICK_RATE_HZ);	//开启导致硬件错误中断
	USART1_Init(115200);
	printf("starting...\r\n");
	/* 创建app_task1任务 */
	xTaskCreate((TaskFunction_t )app_task1,  		/* 任务入口函数 */
			  (const char*    )"app_task1",			/* 任务名字 */
			  (uint16_t       )512,  				/* 任务栈大小 */
			  (void*          )NULL,				/* 任务入口函数参数 */
			  (UBaseType_t    )2, 					/* 任务的优先级 */
			  (TaskHandle_t*  )&app_task1_handle);	/* 任务控制块指针 */ 
	
	/* 创建app_task2任务 */		  
	xTaskCreate((TaskFunction_t )app_task2,  		/* 任务入口函数 */
			  (const char*    )"app_task2",			/* 任务名字 */
			  (uint16_t       )512,  				/* 任务栈大小 */
			  (void*          )NULL,				/* 任务入口函数参数 */
			  (UBaseType_t    )2, 					/* 任务的优先级 */
			  (TaskHandle_t*  )&app_task2_handle);	/* 任务控制块指针 */ 
	/* 开启任务调度 */
	vTaskStartScheduler(); 
}

void app_task1(void* pvParameters)
{
	int cnt = 0;
	for(;;)
	{
		printf("app_task1 is running %d...\r\n", cnt);
		vTaskDelay(1000);
		cnt++;
	}
}

void app_task2(void* pvParameters)
{
	int cnt = 0;
	for(;;)
	{
		printf("app_task2 is running %d...\r\n", cnt);
		vTaskDelay(1000);
		cnt++;
	}
}

工程代码编译结果

FreeRTOS程序正常运行

移植正常的FreeRTOS工程代码链接GitHub - fanghui1234/MCU_FreeRTOS

部分设备编译下载后,程序无法运行,解决方法如下:FreeRTOS移植,解决设备崩溃死机无反应(STM32)-CSDN博客

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐