[简要](../../../../README.md)

# 微内核 k_kit

  > k_kit 以下简称 kit。kit 可以理解成是一个实时内核中的软定时器模块的强化版。
  基于此设计的程序就是由所有软定时器组成的集合，这些集合既可作为一个完整的工程，也可以作为一个线程模块，使用非常灵活。

## 特点
  - 是一个极小的，由事件驱动的，管理任务的微内核；
  - 介于裸机与实时内核之间，适用于资源受限的微型系统的同时，尽可能提供类似实时内核接口和管理方式；
  - 极低的跨平台需求，只需要实现几个简单的接口，即可在任何平台上运行；
  - 所有功能模块都有独立的对象，所有对象动通过态申请和销毁；
  - 极短的、固定的关中断时间，有效保障硬实时性；
  - 基于 kit 设计的工程可无缝扩充到 RTK 实时内核中 [点击查看 RTK](../../README.md)；

## 文件结构
```bash
...
└── 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 是一个单向链表，由队列管理接口使用；

  - 触发调试的过程：
    1. 在接口 k_work_submit() 中把任务对象添加超时信息并插入到 event_list 中；
    2. k_work_q_handler() 检测 delayed_list 如果有超时的任务，插入到 ready_list 中；
    3. k_work_q_handler() 总是在 event_list 取出任务对象，如果：
         - 任务已超时：插入到 ready_list;
         - 任务未超时：按时间顺序，插入到 delayed_list;
    4. 在 ready_list 中查找，如果：
         - 存在任务：从链中删除并执行任务；
         - 没有任务：无动作；
    5. 返回下个超时的任务的剩余时间；

## END

