首页 > 其他分享 >FreeRTOS应用基础(一)

FreeRTOS应用基础(一)

时间:2023-05-22 22:34:55浏览次数:53  
标签:文件 定义 FreeRTOS -- 基础 任务 应用 include

  本系列主要作为自己第一次系统学习RTOS的记录,以正点原子的STM32F103战舰,keil环境编程为例。想要达到以下目标:
  1:初步熟悉FreeRTOS的移植和使用,并迁移完成一个小型项目;
  2:以FreeRTOS为入门,了解RTOS的本质,并提升阅读源码的能力;
  本系列文章主要参考以下资料,本文仅作为汇总,并添加了一些个人理解。
  韦东山freeRTOS快速入门
  【安富莱】FreeRTOS操作系统教程-硬汉嵌入式论坛-Powered by Discuz!

RTOS

  按对外部事件的响应能力来分类,嵌入式操作系统有分时操作系统和实时操作系统。如果操作系统能使计算机系统及时的响应外部事件请求,并能控制所有实时设备和实时任务协调运行,且能在一个规定的时间内完成对事件的处理,那么这种系统就称为实时操作系统(RTOS)。
  按时间的正确程度来分,实时操作系统又分为硬件的实时操作系统和软件的实时操作系统。系统必须在极其严格的时间内完成的任务叫做硬件的实时操作系统,如果不是很严格的话就是软件的实时操作系统。
  FreeRTOS为一个完全免费、可商业化的实时操作系统,为不适合或不可在 eCOS、嵌入式 Linux(或实时 Linux)甚至 uCLinux 上开发的应用程序提供更小、更简单的实时处理系统。

官方中文网站:
RTOS - Free professionally developed and robust real time operating system for small embedded systems development
https://www.freertos.org/zh-cn-cmn-s/RTOS.html

文件结构

FreeRTO部分文件结构如下

|--FreeRTOS
|  |--Demo              //预先制作的示例工程
|  |--Common            //独立于demo的通用代码,大部分已废弃
|  |--source            //核心文件
|  |  |--task.c         //必需,任务操作
|  |  |--list.c         //必需,列表
|  |  |--queue.c        //基本必需,提供队列操作、信号量(semaphore)操作
|  |  |--timer.c        //可选,software timer
|  |  |--crountine.c    //可选,提供event group功能
|  |  |--stream_buffer.c 
|  |  |--event_groups.c
|  |  |--icnclude       //FreeRTOS本身的头文件
|  |  |--portable       //移植时涉及的文件
|  |  |  |--RVDS        //IDE环境,一般为keil或RVD
|  |  |  |  |--ARM_CM3  //cortexM3架构的移植文件
|  |  |  |  |  |--port.c
|  |  |  |  |  |--portmacro.h
|  |  |  |......
|  |  |  |  |......
|  |  |  |  |--MemMang  //内存管理文件,包含五种内存分配方式
|  |  |  |  |  |--heap_1.c
|  |  |  |  |  |--......

工程移植

  此处应用的工程模板为自制,以stm32f1的工程为例子,参考为安富莱开发板的FreeRTOS教程;
  首先在工程目录中建立FreeRTOS的文件目录,将FreeRTOSV8.2.3\FreeRTOS\Source里面如下所有文件移植到刚刚创建的目录中

  然后在Keil工程中建立Source和Portable目录,将以下文件包含在里面,完成后如图所示:

  其中heap4.c为系统内存分配方式,port.c和portmacro.h为RVDS中Cortex-M3对应的移植文件,
heap_4.c文件路径: FreeRTOS\Source\portable\MemMang
port.c和portmacro.h文件的路径:FreeRTOS\Source\portable\RVDS\ARM_CM3
  接着从FreeRTOSV8.2.3\FreeRTOS\Demo\CORTEX_STM32F103_Keil目录下将FreeRTOSConfig.h复制到工程中,此文件为官方整理好的配置文件,用户可通过此文件配置系统,可自定义位置。
  (此步可选)接着建立includes.h,可以用来集中管理头文件,完成后的目录如下:

includes.h可按照以下内容模板:

#ifndef __INCLUDES_
#define __INCLUDES_
/*
****************************************************************
*							标准库
****************************************************************
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
****************************************************************
*							OS
****************************************************************
*/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"

/*
****************************************************************
*							其他
****************************************************************
*/

#endif

  添加文件路径

  最后修改FreeRTOSConfig.h文件,在其中添加以下几行

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

  目的是更改底层映射函数(此步也可以通过其他方式完成,但此方法较为简单)
  其中vPortSVCHandler,xPortPendSVHandler和xPortSysTickHandler是在port.c文件里面定义的。
  SVC_Handler,PendSV_Handler和SysTick_Handler在startup_stm32f10x_hd.s文件里面进行了定义。
  并在stm32f10x_it.c中将对应的函数注销:

  接着编译时会出现以下错误

..\Object\Objects\project.axf: Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).

  查阅网上资料,修改FreeRTOS.h中206行定义即可

  至此,编译0错误0警告,基本移植完成,注意在编译时会报很多FreeRTOS文件的警告,无视重新编译即可,其他问题则需逐个解决

数据类型、命名规则和注释风格

  FreeRTOS核心源码文件的编写遵循MISRA代码规则,同时支持各种编译器。
FreeRTOS没有引入C99和C11的一些新特性和语法,除stdint.h文件(C99标准库)。

基础数据类型

  FFreeRTOS面对不同架构的设备,主要包含四种数据类型,每个移植的版本都含有自己的portmacro.h 头文件,包含了TickType_t和BaseType_t:

  1. TickType_t:
  • FreeRTOS配置了一个周期性的时钟中断:Tick Interrupt,每发生一次中断,中断次数累加,这被称为tick count,tick count这个变量的类型就是TickType_t;
  • 如果用户使能了宏定义 configUSE_16_BIT_TICKS,那么TickType_t定义的就是16位无符号数,否则就是32位无符号数;
  • 对于32位架构,一定要禁止configUSE_16_BIT_TICKS定义,将此宏设置为0,即配置成32位无符号数;
  1. BaseType_t
  • 使用设备架构最基础和最高效的数据类型
  • 由架构决定,32位架构就是32位有符号数、16位架构就是16位有效数据、8位架构同理;
  • 如果BaseType_t被定义成了char型,要特别注意将其设置为有符号数,因为部分函数的返回值是用负数来表示错误类型。
  • BaseType_t通常用作简单的返回值的类型,还有逻辑值,比如pdTRUE/pdFALSE

变量名

  FreeRTOS主要以前缀区分变量

基础前缀 含义
c char,根据MISRA代码规则,char定义的变量只能用于ASCII字符,前缀使用c。
s short,int16_t
i long, int32_t
u unsigned
p 指针
e 枚举
x 其他非标准的类型:结构体、task handle、queue handle等
复合前缀 含义
pc char指针,根据MISRA代码规则,char *定义的指针变量只能用于ASCII字符串,前缀使用pc。
uc unsigned char
pus uint16_t定义的指针变量

函数名

  函数名的前缀有2部分:返回值类型、在哪个文件定义

函数名前缀 含义
prv 加上了static声明的函数, private的缩写。
v 无返回值类型的函数
c 返回值类型为char的函数
Task 根据文件名,文件中相应的函数定义时也将文件名加到函数命名中,如tasks.c中的函数,前缀都带有Task

例子

函数名 含义
vTaskPrioritySet 返回值类型:void,在task.c中定义
xQueueReceive 返回值类型:BaseType_t, 在queue.c中定义
pvTimerGetTimerID 返回值类型:pointer to void,在tmer.c中定义

宏名

  宏名主体部分以大写为主,可添加小写前缀,用来表示这个宏在哪个文件中定义,例如

函数名 含义:在哪个文件中定义
port (比如portMAX_DELAY) portable.h或portmacro.h
task (比如taskENTER_CRITICAL()) task.h
pd (比如pdTRUE) projdefs.h
config (比如configUSE_PREEMPTION) FreeRTOSConfig.h
err (比如errQUEUE_FULL) projdefs.h

通用宏定义如下:

pdTRUE 1
pdFALSE 0
pdPASS 1
pdFAIL 0

点灯

  为了验证工程移植正确,通过实际点亮LED灯验证,main.c如下:

#include "main.h"
#include "includes.h"

static void vTaskLED1(void *pvParameters);
static void vTaskLED2(void *pvParameters);
	
int main()
{
	//SystemInit();       //设置系统时钟为72M;
	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//禁止JTAG和SWJ功能,关闭调试,释放引脚
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	LED_Init();
	/* 创建任务*/
	xTaskCreate( vTaskLED1, /* 任务函数*/
				"vTaskLED", /* 任务名*/
				512, /*任务栈 大小,单位 word ,也就是 4 字节*/
				NULL, /* 任务参数*/
				1, /* 任务优先级*/
				NULL /* 任务句柄*/
	);
	xTaskCreate( vTaskLED2, /* 任务函数*/
				"vTaskLED", /* 任务名*/
				512, /*任务栈 大小,单位 word ,也就是 4 字节*/
				NULL, /* 任务参数*/
				2, /* 任务优先级*/
				NULL /* 任务句柄*/
	);
	/* 启动调度,开始执行任务*/
	vTaskStartScheduler();	
	
	
	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	/*
	如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
	heap 空间不足造成创建失败,此时要加大 FreeRTOSConfig.h 文件中定义的 heap 大小:
	#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 )*/
	while(1);
	
}
/*
*********************************************************************************************************
*	函 数 名: vTaskLED1
*	功能说明: LED闪烁任务
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*	优 先 级:  1	(: 1 数值越小优先级越低,这个跟 uCOS 相反)
*	说    明:
*********************************************************************************************************
*/
static void vTaskLED1(void *pvParameters)
{
	while(1)
	{
		LED_Toggle(1);
		vTaskDelay(1000);
	}
}
/*
*********************************************************************************************************
*	函 数 名: vTaskLED1
*	功能说明: LED闪烁任务
*	形    参: pvParameters 是在创建该任务时传递的形参
*	返 回 值: 无
*	优 先 级:  2
*	说    明:
*********************************************************************************************************
*/
static void vTaskLED2(void *pvParameters)
{
	while(1)
	{
		LED_Toggle(2);
		vTaskDelay(2000);
	}
}

  成功点亮LED!

标签:文件,定义,FreeRTOS,--,基础,任务,应用,include
From: https://www.cnblogs.com/cloudraysun/p/17421932.html

相关文章

  • MySQL数据基础知识整理—3
    聚合函数我们先来看下定义:    在数据库中,聚合函数是指能够对一组数据进行计算并返回一个单一值的函数,这个单一值通常是对这组数据的总体统计结果。    简单来说,就是数据库提供给用户的一种常用函数,其中包括和,平均值,最大值,最小值等。下面我也会给出几个比较常用的聚合......
  • 【习题3】ArkTS基础知识 答案
    【习题3】ArkTS基础知识判断题1.循环渲染ForEach可以从数据源中迭代获取数据,并为每个数组项创建相应的组件。正确(True)错误(False)2.@Link变量不能在组件内部进行初始化。正确(True)错误(False)单选题1.用哪一种装饰器修饰的struct表示该结构体具有组件化能力?......
  • python基础08
    字典的内置方法1#dic={'username':"kevin",'age':18}2#定义空字典3#d={}4#info=dict(username='kevin',age=18)5#print(info)67##1.支持key取值8#new_dic=dic['username']9#print(new_dic)10#ite......
  • 算法基础上机实验——2023.5.21
    2.#include<cmath>#include<cstdio>#include<iostream>#include<algorithm>usingnamespacestd;intmain(){intn; cin>>n; n=n*100; intcock,hen,chicken; intcount=0; for(cock=0;cock<=n;c......
  • 一个基础的vue图片放大镜自定义指令
    <template> <div>  <divv-magnifyref="content"class="content">   <imgsrc="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"alt="">  </div> </d......
  • iOS UITabBarController 典型应用
    -(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{self.window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];//Overridepointforcustomizationafterapplicationlau......
  • 浅析视频技术与AI智能识别技术在智慧矿山场景中的应用
    一、背景分析能源与矿业是我国国民经济的重要物质生产部门和支柱产业之一,同时也是一个安全事故多发的高危行业,施工阶段的现场管理对工程成本、进度、质量及安全等至关重要。国家矿山安监局陆续发布(矿安〔2022)128号)文、(矿安综〔2023〕5号)文推动矿山重大灾害风险防控,山西、贵州......
  • Python的基础语法(五)“数据内置方法之字典、元组、集合”
    字典的内置方法1、字典常用的定义方法:info={'name':'tony','age':18,'sex':'male'}info=dict(name='tony',age='18')2、字典的内置方法2.1、按照key取值,可存可取:dic={......
  • Python多进程运行——Multiprocessing基础教程2
    转载:Python多进程运行——Multiprocessing基础教程2-知乎(zhihu.com)1数据共享在多进程处理中,所有新创建的进程都会有这两个特点:独立运行,有自己的内存空间。我们来举个例子展示一下:importmultiprocessing#emptylistwithglobalscoperesult=[]defsquare_l......
  • Nginx,安装及基础配置
    一:下载Nginx官网:http://nginx.org/中文网:https://nginx.p2hp.com/二:Nginx目录conf:存放核心配置文件contrib:存放语法支持脚本docs:存放文档资料html:存放静态html文件logs:存放日志文件temp:存放临时文件nginx.exe:懂的都懂三:配置文件【nginx.conf】文件位置:【conf】......