操作系统(Operating System,简称OS)是管理计算机硬件与软件资源的计算机程序。简单说就是一种管理计算机资源的软件。目的是为了高效、合理、简单、安全的利用有限的计算机硬件与软件资源。
最初的电脑没有操作系统,人们通过各种按钮来控制计算机,后来出现了汇编语言,操作人员通过有孔的纸带将程序输入电脑进行编译。这些将语言内置的电脑只能由制作人员自己编写程序来运行,不利于程序、设备的共用。为了解决这种问题,就出现了操作系统,这样就很好实现了程序的共用,以及对计算机硬件资源的管理。
操作系统如同一个国家的管理,比如图书馆,医院,学校,矿产,耕地等等都是国家公共资源,如同计算机的硬件和软件公共资源。公共资源是有限的,国家就需要对资源进行管理,合理的利用,把资源优先分配给最需要的人,使得尽可能公平。操作系统也是对计算机的硬件和软件公共资源进行管理,合理的利用。
万字长文详细介绍操作系统基本概念
根据实际用途不同,又发展出了不用类型的操作系统。分别有 分时系统、实时系统、批处理系统、网络操作系统等。其中 分时系统、实时系统 是最常见的。
分时系统(Time Share Operating System):可以实现用户的人机交互需要,多个用户共同使用一个主机,很大程度上节约了资源成本。 分时系统具有多路性、独立性、交互性、及时性的优点,能够将用户-系统-终端任务实现。常见有:Windows、Linux、IOS、Android等。
实时系统(Real Time Operating System,简称 RTOS):是指系统可以快速的对外部命令进行响应,在对应的时间里处理问题,协调系统作。在嵌入式领域中,嵌入式实时操作系统正得到越来越广泛的应用。采用嵌入式实时操作系统(RTOS)可以更合理、更有效地利用CPU的资源,简化应用软件的设计,缩短系统开发时间,更好地保证系统的实时性和可靠性。不过实时性是相对分时系统大型系统而言的。玩过单片机人都知道直接立刻操作硬件资源实时性是最高的。常见有:μC/OS-II、μC/OS-III、FreeRTOS、RT-Thread、RTT、VxWorks.等。
常见的操作系统及应用领域
FreeRTOS是一个开源免费迷你的实时操作系统内核(Free自由,RTOS实时操作系统,通过字意就能知道是免费的)。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。
其他参考:
rtthrea-ucosii-freertos三系统学习总结
[RTOS]uCOS、FreeRTOS、RTThread、RTX等RTOS的对比之特点
官方网址:https://www.freertos.org
下载下来的源码是包含了一些库和工程实例等,用户需要提炼出有用的源码。
主要涉及2个目录:
Demo
Demo目录下是工程文件,以"芯片和编译器"组合成一个名字, 比如:CORTEX_STM32F103_Keil
Source
根目录下是核心文件,这些文件是通用的
include目录下头文件
portable目录下是移植时需要实现的文件
内存管理文件 目录名为:[compiler]/[architecture]
[IDE名]/[芯片内核]目录下文件,比如:RVDS/ARM_CM3,这表示cortexM3架构在RVDS工具上的移植文件
FreeRTOS/Source/下的文件 | 作用 |
---|---|
tasks.c | 必需,所有任务相关函数 |
list.c | 必须,列表,在内核整体控制上都使用了列表格式数据处理 |
queue.c | 基本必需,提供队列操作、信号量(semaphore)操作,任务和任务之间的通讯 |
timer.c | 可选,软件定时器,以任务形式存在 |
event_groups.c | 可选,提供 事件标志组 功能。 |
croutine.c | 可选,过时了,协线程(协程)文件,和任务类似,在系统资源比较缺乏下使用, |
FreeRTOS的最核心文件只有2个:
FreeRTOS/Source/tasks.c
FreeRTOS/Source/list.c
文件在...../portable/MemMang
下内存管理文件,它也是放在portable
目录下,表示你可以提供自己的函数。
源码中默认提供了5个文件,对应内存管理的5种方法。
参考文章:FreeRTOS说明书吐血整理【适合新手+入门】
文件 | 优点 | 缺点 | 应用场合 |
---|---|---|---|
heap_1.c | 分配简单,没有碎片,时间确定 | 只分配、不回收 | 适用要求非常严格的系统里,不允许使用动态内存的场景 |
heap_2.c | 动态分配、最佳匹配算法 | 碎片、时间不定 | 过时了,不推荐Heap_2。用Heap_4替代Heap_2,更高效。 |
heap_3.c | 调用标准库函数 | 速度慢、时间不定 | 适用使用标准C库中的malloc、free函数的场景 |
heap_4.c | 动态分配、相邻空闲内存可合并 | 较少碎片问题、时间不定 | 适用频繁分配、释放不同大小内存的场景 |
heap_5.c | 在heap_4基础上支持分隔的内存块 | 较少碎片问题、时间不定 | 适用内存块地址不连续的场景 |
注:通过对比可以看出一般最常用的是heap_4.c内存管理方式。
FreeRTOS需要3个头文件目录:
移植时用到的头文件:FreeRTOS/Source/portable/[IDE名]/[芯片内核名]
含有配置文件FreeRTOSConfig.h的目录
FreeRTOS本身的头文件:FreeRTOS/Source/include
头文件 | 作用 |
---|---|
portmacro.h | 实现与单片机接口的相关宏定义,系统移植文件。用于不通的编译器和芯片架构的移植、(不需要修改) |
FreeRTOSConfig.h | FreeRTOS的配置文件,比如选择调度算法:configUSE_PREEMPTION 每个demo都必定含有FreeRTOSConfig.h 建议去修改demo中的FreeRTOSConfig.h,而不是从头写一个 |
FreeRTOS.h | 使用FreeRTOS API函数时,必须包含此文件。 预编译指令。定义缺省值,或者编译的时候给出#error信息。(不需要修改) |
task.h | 任务管理:创建任务,删除任务,任务调度,等等 (不需要修改) |
list.h | 数据链表文件,FreeRTOS是用数据链表来进行任务管理的,该文件包含了对数据链表的操作函数。(不需要修改) |
queue.h | 队列文件 管理消息队列等等。(不需要修改) |
timers.h | 软件定时器头文件。(不需要修改) |
event_groups.h | 提供 事件标志组头文件。(不需要修改) |
crouting.h | 进程管理(不需要修改) |
stream_buffer.h | 流缓冲区头文件。流缓冲区传递一个连续的字节流。 |
message_buffer.h | 消息缓冲区头文件。消息缓冲区传递大小可变但离散的消息。消息缓冲区使用流缓冲区进行数据传输。 |
semphr.h | 信号量的一些宏函数。(不需要修改) |
projdefs.h | 用于定义系统常用到的常量宏。(不需要修改) |
stack_macros.h | 堆栈管理的一宏函数。(不需要修改)。V10.0.0开始为了一致性,已经重命名了StackMacros.h头文件stack_macros.h。为了兼容这两文件目前都在源码中。使用时直接删除StackMacros.h,选择stack_macros.h即可(新的源码不再使用StackMacros.h)。 |
StackMacros.h | 堆栈管理的一宏函数,旧文件。(不需要修改) |
mpu_prototypes.h | 当使用MPU时,标准(非MPU)API函数被映射到启动“MPU”的等效函数,其原型在此头文件中定义。 MPU是,即CPU升级芯片。 |
mpu_wrappers.h | 该文件重新定义要通过包装器宏调用的API函数,但仅适用于使用MPU的端口。 |
atomic.h | 原子操作支持头文件。该文件通过全局禁用中断来实现原子函数。每个编译器目录下都可以提供具有特定于体系结构的原子指令的实现。 原子操作是指不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换(context switch)。原子操作是在多线程环境下避免数据不一致必须的手段。 处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作。 例如:在单核CPU中, 能够在一个指令中完成的操作都可以看作为原子操作,因为中断只发生在指令间。 |
deprecated_definitions.h | 将过时的定义分离成单独一个新头文件,这些过时的定义在一些上年头的演示例程中仍会使用,必须包含在编译文件中。 |
官方Demo工程移植是有别于FreeRTOS移植,官方Demo工程是官方在一些常见芯片上的移植示例工程,还有很多芯片并没有示例工程,没有的就需要用户自己去移植,这需要对FreeRTOS操作系统和芯片硬件熟悉才行!对于初学者先移植官方Demo工程学习,有能力和需要再去移植FreeRTOS。
官方Demo工程是预先配置好的、没有编译错误的工程。目的是让你可以基于它进行修改,以适配你的单板。这些Demo还可以继续精简:
main函数中只需要保留2个函数:
prvSetupHardware()
vTaskStartScheduler()
每个移植的版本都含有自己的portmacro.h
头文件,里面定义了2个数据类型:
TickType_t:
FreeRTOS配置了一个周期性的时钟中断:Tick Interrupt
每发生一次中断,中断次数累加,这被称为tick count
tick count这个变量的类型就是TickType_t
TickType_t可以是16位的,也可以是32位的
FreeRTOSConfig.h中定义configUSE_16_BIT_TICKS时,TickType_t就是uint16_t
否则TickType_t就是uint32_t
对于32位架构,建议把TickType_t配置为uint32_t
BaseType_t:
这是该架构最高效的数据类型
32位架构中,它就是uint32_t
16位架构中,它就是uint16_t
8位架构中,它就是uint8_t
BaseType_t通常用作简单的返回值的类型,还有逻辑值,比如pdTRUE/pdFALSE
变量名有前缀:
变量名前缀 | 含义 |
---|---|
c | char |
s | int16_t,short |
l | int32_t,long |
x | BaseType_t, 其他非标准的类型:结构体、task handle、queue handle等 |
u | unsigned |
p | 指针 |
uc | uint8_t,unsigned char |
pc | char指针 |
函数名的前缀有2部分:返回值类型、在哪个文件定义。
函数名前缀 | 含义 |
---|---|
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 |