1 学习书籍
[野火®]《FreeRTOS 内核实现与应用开发实战—基于STM32》
2 学习计划
- 第一部分
- 以FreeRTOS V9.0.0 官方源码为蓝本,抽丝剥茧,不断迭代,教你怎么从0 开始把FreeRTOS 内核写出来。
- 书中涉及到的数据类型,变量名称、函数名称,文件名称,文件存放的位置都完全按照FreeRTOS 官方的方式来实现,当你学完这本书之后可以无缝地切换到原版的FreeRTOS 的使用。
- 要注意的是,在实现的过程中,某些函数会去掉一些形参和一些冗余的代码,只保留核心的功能,但这并不会影响我们学习。
第一部分为“从0 到1教你写FreeRTOS 内核”
- 即重点讲解FreeRTOS 的原理实现,从0 开始,不断迭代,教你怎么把FreeRTOS 的内核写出来,让你彻底学会任务是如何定义的,系统是如何调度的(包括底层的汇编代码讲解),多优先级是如何实现的等等操作系统最深层次的知识。
- 当你拿到本书开始学习的时候你一定会惊讶,原来RTOS 的学习并没有那么复杂,反而是那么的有趣,原来自己也可以写RTOS,成就感立马爆棚。
- 第二部分
- 主要讲FreeRTOS 的移植和内核组件的使用,不会再去深入讲解源码,着重讲应用,如果对第一部分不感兴趣的朋友,可以跳过第一部分,直接进入第二部分的学习,两者之间没有必然的联系。
“FreeRTOS 内核应用开发”
- 重点讲解FreeRTOS 的移植,内核每个组件的应用,比起第一部分,这部分内容掌握起来比较容易。
3 学习方法
- 全书内容循序渐进,不断迭代,
前一章都是后一章的基础
,必须从头开始阅读,不能进行跳跃式的阅读
。 - 在学习的时候务必做到两点:
- 一是不能一味地看书,要把代码和书本结合起来学习,
一边看书,一边调试代码
。看书倒是很简单,那如何调试代码?即单步执行每一条程序,看看程序的执行流程和执行的效果与自己大脑所想是不是一样; - 二是在每学完一章之后,
必须将配套的例程重写一遍
(切记不要复制,哪怕是一个分号,但可以抄),做到举一反三,确保真正理解。在自己写的时候肯定会错漏百出,这个时候要珍惜这些错误,好好调试,这是你提高编程能力的最好的机会。记住,程序不是一气呵成写出来的,而是一步一步调试出来的。
4 FreeRTOS编程风格
4.1 数据类型
- 在FreeRTOS 中,使用的数据类型虽然都是标准C 里面的数据类型,但是针对不同的处理器,对标准C 的数据类型又进行了
重定义
,给它们取了一个新的名字 - 在FreeRTOS 中,int 型从不使用,只使用short 和long 型。在Cortex-M内核的MCU中,short 为16 位,long 为32 位。
- FreeRTOS 中详细的数据类型重定义在portmacro.h 这个头文件中实现
1 #define portCHAR char
2 #define portFLOAT float
3 #define portDOUBLE double
4 #define portLONG long
5 #define portSHORT short
6 #define portSTACK_TYPE uint32_t
7 #define portBASE_TYPE long
8
9 typedef portSTACK_TYPE StackType_t;
10 typedef long BaseType_t;
11 typedef unsigned long UBaseType_t;
12
13 #if( configUSE_16_BIT_TICKS == 1 )
14 typedef uint16_t TickType_t;
15 #define portMAX_DELAY ( TickType_t ) 0xffff
16 #else
17 typedef uint32_t TickType_t;
18 #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
- 在FreeRTOS 中,我们都需要明确的指定变量char 是有符号的还是无符号的。
- 在keil 中,默认char 是无符号的,但是也可以配置为有符号的,具体配套过程见图 3-3
4.2 变量名
- 在FreeRTOS 中,定义变量的时候往往会把
变量的类型
当作前缀
加在变量上,这样的好处是让用户一看到这个变量就知道该变量的类型
- char 型变量的前缀是c
- short 型变量的前缀是s
- long 型变量的前缀是l
- portBASE_TYPE 类型变量的前缀是x
- 还有其他的数据类型,比如数据结构,任务句柄,队列句柄等定义的变量名的前缀也是x
- 变量是无符号型的那么会有一个前缀u
- 指针变量则会有一个前缀p
- 一个无符号的char 型变量的时候会加一个uc 前缀
- 一个char 型的指针变量的时候会有一个pc 前缀
4.3 函数名
函数名:
- 包含了函数
返回值的类型
、函数所在的文件名
和函数的功能
,如果是私有
的函数则会加一个prv
(private)的前缀。 - 特别的,在函数名中加入了函数所在的文件名,这大大的帮助了用户提高寻找函数定义的效率和了解函数作用的目的,具体的举例如下:
- vTaskPrioritySet()函数的返回值为void 型,在task.c 这个文件中定义。
- xQueueReceive()函数的返回值为portBASE_TYPE 型,在queue.c 这个文件中定义。
- vSemaphoreCreateBinary()函数的返回值为void 型,在semphr.h 这个文件中定义。
4.4 宏
宏均是由大写字母表示
,并配有小写字母的前缀
- 前缀用于表示该宏在哪个头文件定义
- 信号量的函数都是一个宏定义,但是它的函数的命名方法是遵循函数的命名方法而不是宏定义的方法
- 在贯穿FreeRTOS 的整个代码中,还有几个通用的宏定义我们也要注意下,都是表示0
和1 的宏
4.5 格式
- 一个tab 键盘等于四个空格键。我们在编程的时候最好使用空格键而不是使用tab 键,
当两个编译器的tab 键设置的大小不一样的时候,代码移植的时候代码的格式就会变乱
,而使用空格键
则不会出现这种问题。