优化 CMakeLists.txt,增加 lib-out 目录的包含;修改 app_config.c 中的 LED 灯带开关变量名;更新 app_config.h,增加新的灯效模式和方向控制;更新 SBDEMO.h 中的默认设备名称;在 msc_host.c 中添加 USB 设备连接类型的处理;在 usbport.c 中增加 USB 连接类型的状态管理;更新 Kconfig,增加 LED 灯带的最大图层数和竞速模式选项;新增 spbelib_interface.h 文件,定义无线调参功能接口;删除不再使用的 components/CMakeLists.txt 文件;更新 misc.h,添加读取 MCU 身份信息的 MD5 值的函数声明;修改 tim.h 中的 drv_pwm_init 函数参数;更新 kk.h,增加默认工作队列的创建宏;优化 sh.c 中的命令行插入字符串逻辑;更新 sdkconfig 默认配置文件,升级 ESP-IDF 版本和调整蓝牙默认发射功率。
微内核 k_kit
k_kit 以下简称 kit。kit 可以理解成是一个实时内核中的软定时器模块的强化版。 基于此设计的程序就是由所有软定时器组成的集合,这些集合既可作为一个完整的工程,也可以作为一个线程模块,使用非常灵活。
特点
- 是一个极小的,由事件驱动的,管理任务的微内核;
- 介于裸机与实时内核之间,适用于资源受限的微型系统的同时,尽可能提供类似实时内核接口和管理方式;
- 极低的跨平台需求,只需要实现几个简单的接口,即可在任何平台上运行;
- 所有功能模块都有独立的对象,所有对象动通过态申请和销毁;
- 极短的、固定的关中断时间,有效保障硬实时性;
- 基于 kit 设计的工程可无缝扩充到 RTK 实时内核中 点击查看 RTK;
文件结构
...
└── kit # 本目录
├── k_kit.c # kit 的所有实现代码。
├── k_kit.h # 完整的 kit 的功能接口
└── kk.h # 跨内核接口,与实时内核中 RTK 中的 `rtk_kk.h` 保持一致
模块简介
work
- work 是任务管理的对象,数据结构由 k_work_t 封装,在创建对象时设置实现函数;
- 任务拥有: 运行、延时、挂起、堵塞 的能力;
- 所有任务都由队列函数 k_work_q_handler() 执行调用管管理;
- 所有任务可设置由通讯模块唤醒;
- 所有任务默认附带一个接收邮箱;
- 所有任务函数必须返回;
- 所有任务都允许设置优先级,但不可抢断;
mbox
- mbox 是 work 附带的一个功能的扩展功能,用法与 fifo 类似;
- 邮箱在使用前需要被创建,每个任务最多只能有一个邮箱;
- 邮件内存从堆中申请,传递的是指针,与 fifo 不可混用;
- 一个新邮件被提交时,对应的任务一定被唤醒;
- 提取后的邮件在任务函数退出后被自动删除;
timer
- timer 是软定时器的管理对象,数据结构由 k_timer_t 封装,在创建对象时设置实现函数;
- 软定时器的本质是在 work 的基础上添加一些时间特性的任务;
- 软定时器拥有: 运行、延时、挂起 的能力;
- 所有软定时器都由队列函数 k_timer_q_handler() 执行调用管管理;
- 所有软定时器函数必须返回;
- 所有软定时器都允许设置优先级,但不可抢断;
work 与 timer 比较
| work | timer | |
|---|---|---|
| 入口 | k_work_q_handler() | k_timer_q_handler() |
| 运行 | 是 | 是 |
| 延时 | 是 | 是 |
| 挂起 | 是 | 是 |
| 堵塞 | 是 | 不支持 |
| 优先级 | 0 .. 7 | 0 .. 7 |
| mbox | 可用,默认唤醒 | 仅发送 |
| fifo | 可用,注册唤醒 | 可用,不支持唤醒 |
| queue | 可用,注册唤醒 | 可用,不支持唤醒 |
| pipe | 可用,注册唤醒 | 可用,不支持唤醒 |
| log | 可用 | 不可用 |
IPC
- kit 目前包含了三种常用的独立对象的通讯模块
fifo,queue,pipe和 work 专用的模块mbox;
| fifo | queue | pipe | mbox | |
|---|---|---|---|---|
| 对象 | k_fifo_t | k_queue_t | k_pipe_t | k_work_t |
| 数据缓存 | 堆 | 独立 | 独立 | 堆 |
| 数据吞吐 | 中 | 慢 | 快 | 中 |
| 数据交换 | 指针 | 副本 | 副本 | 指针 |
| 单位长度 | 不限 | 固定 | 字节 | 不限 |
| 总长度 | 不限 | 固定 | 固定 | 不限 |
| 在中断申请缓存 | 禁止 | 可用 | 不需要 | 禁止 |
| work | 完整可用 | 完整可用 | 完整可用 | 完整可用 |
| timer | 仅收发 | 仅收发 | 仅收发 | 仅发送 |
| isr | 仅收发 | 仅收发 | 仅收发 | 仅发送 |
调度机制
每个 work 对象都对应一个勾子函数为任务,由入口 k_work_q_handler() 管理(软定时器同理),通过三个关键链表的操作,调用对应的勾子函数。
主要由接口 k_work_submit(), k_work_resume(), k_work_suspend(), k_work_later() 等触发有关链表的操作。
-
dlist_t event_list;
dlist_t event_list 是一个双向链表,由上述的接口插入,在队列管理接口中取出;
-
slist_t ready_list[8];
dlist_t event_list 共8个成员的单向链表,每个成员表示一个优先级,由队列管理接口使用;
-
slist_t delayed_list;
slist_t delayed_list 是一个单向链表,由队列管理接口使用;
-
触发调试的过程:
- 在接口 k_work_submit() 中把任务对象添加超时信息并插入到 event_list 中;
- k_work_q_handler() 检测 delayed_list 如果有超时的任务,插入到 ready_list 中;
- k_work_q_handler() 总是在 event_list 取出任务对象,如果:
- 任务已超时:插入到 ready_list;
- 任务未超时:按时间顺序,插入到 delayed_list;
- 在 ready_list 中查找,如果:
- 存在任务:从链中删除并执行任务;
- 没有任务:无动作;
- 返回下个超时的任务的剩余时间;