Skip to content

1 编程规范

1.1 变量名前缀

变量名前缀含义
cchar
sint16_t, short
lint32_t, long
xBaseType_t其它非标准的类型:结构体\task handle queue handle 等
uunsigned
p指针
ucuint8_t, unsigned char
pcchar 指针

1.2 函数名前缀

函数名前缀含义
v返回 void
x返回 BaseTpye_t

2 内存管理

五种heap实现 一般使用 heap_4.c heap_3.c是标准库实现,比较慢 heap_2.c是直接分配的,相邻空间不合并回收 heap_5.c是支持 分隔的

3 任务

3.1 动态创建

3.2 静态分配

3.3 任务调度

  1. 相同优先级的轮流运行
  2. 最高优先级的先运行 a. 高优先级的任务未执行完, 更低优先级的任务 永远无法运行 b. 一旦高优先级的任务就绪, 会马上运行 c. 最高优先级的任务有多个, 会轮流运行

3.4 空闲任务

  1. 检查等待终止的任务(自杀任务)
  2. 调用hock 函数 用于调试 注意: 在 高优先级 任务 执行后 主动使用 vTtaskDelay 进入阻塞状态 使得空闲任务 得以运行

3.5 dealy 函数

  • vTaskDelay : 至少等待指定个数的 Tick Interruppt 才能运行
  • vTaskDelayUntil : 等待到指定的绝对时刻,才能变成就绪态

4 同步

4.1 有缺陷的例子

[!example] 例1

有一个全局变量end=0 任务A 执行 计算 大概要 1.5秒 执行完后会设置end=1 任务B 使用 while(end) 等待计算完成 这样会导致 rtos调度 把cpu资源给了无意义 的 任务B while循环 导致 计算缓慢

[!example] 例2 三个任务 使用同一个函数 这个函数 使用i2c在屏幕上打印信息 i2c 是比较耗时的 start,dev_addr,data,stop 如果不加以同步的保护, i2c的信号是混乱的 但是即便使用全局变量来保护,由于检查和设置这个全局变量不是原子性的, 出现冲突也是不可避免的, 即便这个概率非常小 可以使用 关中断的办法 避免调度 但是 这样还是不可避免 的 会使得为获得使用权的任务占用cpu无意义等待

4.2 解决办法

  • 环形缓冲区
  • 队列
  • 信号量
  • 互斥量
互斥措施阻塞-唤醒
全局变量1
环形缓冲区多个
队列多个

4.3 队列

队列的组成: 环形缓冲区 + 两个链表(发送者和接受者) 队列的本质: 环形缓冲区 + 互斥\阻塞-唤醒机制

  • 如果队列不传输数据,只调整"数据个数",他就是信号量
  • 如果信号量中,限定"数据个数"最大为1,它就是互斥量

如果队列空 读任务没有得到数据 可以进入阻塞 , 等待数据来到(写进程 主动唤醒 或 tick超时 唤醒)