TA的每日心情 | 衰 2024-10-6 20:55 |
---|
签到天数: 1 天 [LV.1]初来乍到
二级逆天
- 积分
- 1392
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
[paragraph]嵌入式系统不只是ARM+Linux,不是只有安卓,凡是电子产品都可称为嵌入式系统。物联网行业的兴起,也提升了FreeRTOS市场占有率。本文就是介绍FreeRTOS基础及其应用,只是个人整理,可能存在问题,其目的只是简要介绍系统的基础,只能作为入门资料。
目录
一、为什么要学习RTOS
二、操作系统基础
三、初识FreeRTOS
四、任务
五、队列
六、软件定时器
七、信号量
八、事件
九、任务通知
十、内存管理
十一、通用接口
一、为什么要学习RTOS
进入嵌入式这个领域,入门首先接触的是单片机编程,尤其是C51单片机来,基础的单片机编程通常都是指裸机编程,即不加入任何RTOS(RealTImeOperaTIngSystem实时操作系统)。常用的有国外的FreeRTOS、μC/OS、RTX和国内的RT-thread、HuaweiLiteOS和AliOS-Things等,其中开源且免费的FreeRTOS的市场占有率较高。
1.1前后台系统
在裸机系统中,所有的操作都是在一个无限的大循环里面实现,支持中断检测。外部中断紧急事件在中断里面标记或者响应,中断服务称为前台,main函数里面的while(1)无限循环称为后台,按顺序处理业务功能,以及中断标记的可执行的事件。小型的电子产品用的都是裸机系统,而且也能够满足需求。
1.2多任务系统
多任务系统的事件响应也是在中断中完成的,但是事件的处理是在任务中完成的。如果事件对应的任务的优先级足够高,中断对应的事件会立刻执行。相比前后台系统,多任务系统的实时性又被提高了。
在多任务系统中,根据程序的功能,把这个程序主体分割成一个个独立的,无限循环且不能返回的子程序,称之为任务。每个任务都是独立的,互不干扰的,且具备自身的优先级,它由操作系统调度管理。加入操作系统后,开发人员不需要关注每个功能模块之间的冲突,重心放在子程序的实现。缺点是整个系统随之带来的额外RAM开销,但对目前的单片机的来影响不大。
1.3学习RTOS的意义
学习RTOS,一是项目需要,随着产品要实现的功能越来越多,单纯的裸机系统已经不能完美地解决问题,反而会使编程变得更加复杂,如果想降低编程的难度,就必须引入RTOS实现多任务管理。二是技能需要,掌握操作系统,和基于RTOS的编程,实现更好的职业规划,对个人发展尤其是钱途是必不可少的。
以前一直觉得学操作系统就必须是linux,实际每个系统都有其应用场景,对于物联网行业,杀鸡焉用牛刀,小而美,且应用广泛的FreeRTOS是首选。有一个操作系统的基础,即使后续基于其他系统开发软件,也可触类旁通,对新技术快速入门。目前接触的几款芯片都是基于FreeRTOS。
如何学习RTOS?最简单的就是在别人移植好的系统之上,看看RTOS里面的API使用说明,然后调用这些API实现自己想要的功能即可。完全不用关心底层的移植,这是最简单快速的入门方法。这种学习方式,如果是做产品,可以快速的实现功能,弊端是当程序出现问题的时候,如果对RTOS不够了解,会导致调试困难,无从下手。
各种RTOS内核实现方式都差不多,我们只需要深入学习其中一款就行。万变不离其宗,正如掌握了C51基础,后续换其他型号或者更高级的ARM单片机,在原理和方法上,都是有借鉴意义,可以比较快的熟悉并掌握新单片机的使用。
二、操作系统基础2.1链表
链表作为C语言中一种基础的数据结构,在平时写程序的时候用的并不多,但在操作系统里面使用的非常多。FreeRTOS中存在着大量的基础数据结构链表和链表项的操作(list和lisTItem)。FreeRTOS中与链表相关的操作均在list.h和list.c这两个文件中实现。
链表比数组,最大优势是占用的内存空间可以随着需求扩大或缩小,动态调整。实际FreeRTOS中各种任务的记录都是依靠链表动态管理,具体的可以参考源码的任务控制块tskTCB。任务切换状态,就是将对应的链表进行操作,链表操作涉及创建和插入、删除和查找。
2.2队列
队列是一种只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队尾放入数据,对头挤出。先进先出,称为FIFO
2.3任务
在裸机系统中,系统的主体就是main函数里面顺序执行的无限循环,这个无限循环里面CPU按照顺序完成各种事情。在多任务系统中,根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为任务。系统中的每一任务都有多种运行状态。系统初始化完成后,创建的任务就可以在系统中竞争一定的资源,由内核进行调度。
就绪(Ready):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。
运行(Running):该状态表明任务正在执行,此时它占用处理器,调度器选择运行的永远是处于最高优先级的就绪态任务。
阻塞(Blocked):任务当前正在等待某个事件,比如信号量或外部中断。
挂起态(Suspended):处于挂起态的任务对调度器而言是不可见的。
挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到调用恢复任务的接口;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。
各任务运行时使用消息、信号量等方式进行通信,不能是全局变量。任务通常会运行在一个死循环中,不会退出,如果不再需要,可以调用删除任务。
2.4临界区
临界区就是一段在执行的时候不能被中断的代码段。在多任务操作系统里面,对全局变量的操作不能被打断,不能执行到一半就被其他任务再次操作。一般被打断,原因就是系统调度或外部中断。对临界区的保护控制,归根到底就是对系统中断的使能控制。在使用临界区时,关闭中断响应,对部分优先级的中断进行屏蔽,因此临界区不允许运行时间过长。为了对临界区进行控制,就需要使用信号量通信,实现同步或互斥操作。
三、初识FreeRTOS3.1FreeRTOS源码
FreeRTOS由美国的RichardBarry于2003年发布,2018年被亚马逊收购,改名为AWSFreeRTOS,版本号升级为V10,支持MIT开源协议,亚马逊收购FreeRTOS也是为了进入物联网和人工智能,新版本增加了物联网行业的网络协议等功能。
FreeRTOS是开源免费的,可从官网www.freertos.org下载源码和说明手册。例如展锐的UIS8910使用的是V10。以FreeRTOSv10.4.1为例,包含Demo例程,Source内核的源码,License许可文件。
3.1.1Source文件夹
FreeRTOS/Source文件夹下的文件:
包括FreeRTOS的通用的头文件include和C文件,包括任务、队列、定时器等,适用于各种编译器和处理器,是通用的。
需要特殊处理适配的在portblle文件夹,其下内容与编译器和处理器相关,FreeRTOS要想运行在一个单片机上面,它们就必须关联在一起,通常由汇编和C联合编写。通常难度比较高,不过一般芯片原厂提供移植好的接口文件。这里不介绍移植的方法,因为自己也不明白。
Portblle/MemMang文件夹下存放的是跟内存管理相关的,总共有五个heap文件,有5种内存动态分配方式,一般物联网产品选用heap4.c。
3.1.2Demo文件夹
里面包含了FreeRTOS官方为各个单片机移植好的工程代码,FreeRTOS为了推广自己,会给针对不同半导体厂商的评估板实现基础功能范例,Demo下就是参考范例。
3.1.3FreeRTOSConfig.h配置
FreeRTOSConfig.h头文件对FreeRTOS所需的功能的宏均做了定义,需要根据应用情况配置合适的参数,其作用类似MTK功能机平台的主mak文件,部分定义如下:
1.#defineconfigUSE_PREEMPTION1
2.#defineconfigUSE_IDLE_HOOK0
3.#defineconfigUSE_TICK_HOOK0
4.#defineconfigCPU_CLOCK_HZ(SystemCoreClock)
5.#defineconfigTICK_RATE_HZ((TickType_t)1000)
例如系统时钟tick等参数在就这个文件配置,具体作用可以看注释。一般情况下使用SDK不需要改动,特殊情况下咨询原厂再调整。
3.2FreeRTOS编码规范
接触一个新平台或者SDK,明白它的编码规范,文件作用,可以提高源码阅读效率,快速熟悉其内部实现。
3.2.1数据类型
FreeRTOS针对不同的处理器,对标准C的数据类型进行了重定义。
1.#defineportCHARchar
2.#defineportFLOATfloat
3.#defineportDOUBLEdouble
4.#defineportLONGlong
5.#defineportSHORTshort
6.#defineportSTACK_TYPEuint32_t
7.#defineportBASE_TYPElong
应用编码中,推荐使用的是下面这种风格。
1.typedefintint32_t;
2.typedefshortint16_t;
3.typedefcharint8_t;
4.typedefunsignedintuint32_t;
5.typedefunsignedshortuint16_t;
6.typedefunsignedcharuint8_t;
3.2.2变量名
FreeRTOS中,定义变量的时候往往会把变量的类型当作前缀,好处看到就知道其类型。
char型变量的前缀是c
short型变量的前缀是s
long型变量的前缀是l
复杂的结构体,句柄等定义的变量名的前缀是x
变量是无符号型的再加前缀u,是指针变量则加前缀p
3.2.3函数名
函数名包含了函数返回值的类型、函数所在的文件名和函数的功能,如果是私有的函数则会加一个prv(private)的前缀。
例如vTaskPrioritySet函数的返回值为void型,在task.c这个文件中定义 |
|