Skip to content

lai-nick/TTask-MultiTask

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TTask 多任务调度器模板

轻量级裸机任务调度器,不用 RTOS。
每个任务只需填三个函数指针(init / periodic / on_event),调度器自动按时机调用。
支持消息队列通信、1ms 精确定时。


🤖 AI 一键生成

把整个项目文件夹丢给 AI(Claude、GPT 等),再附上一句你的需求,AI 就能自动为你的 MCU 工程生成多任务框架:

把这个 TTask 模板集成到我的 STM32G0 项目中。
我的项目有:
  • 按键扫描(4个按键,10ms 轮询)
  • LED 指示灯(2个,状态指示)
  • 串口协议解析(115200bps,不定长帧)
  • 继电器控制(3路,带过零检测)
帮我生成对应的 task_xxx.c 和 timer.c 移植代码。

原理: 仓库中的 SKILL.md 包含了调度器的完整知识(API、任务模式、消息通信、移植方法、注意事项),AI 阅读后就能精准理解并替你写出适配代码。你只需要把生成的 task_xxx.c 放到工程里注册即可。

💡 这就是本项目的主要使用方式——不用自己读源码,交给 AI 理解框架然后自动输出你需要的任务代码。


快速开始

1. 目录结构

TTask-MultiTask-Template/
├── README.md                          ← 本文件
├── SKILL.md                           ← 完整技能文档(含教程、示例、FAQ)
├── User/
│   ├── main.c                         ← 主入口(只需 3 行)
│   └── scheduler/
│       ├── ptask.h / .c               ← Protothreads + 消息队列(底层)
│       ├── ttask.h / .c               ← 通用任务模板(上层 API)
│       ├── timer.h                    ← 硬件定时器接口
│       ├── tasks.h                    ← 任务 ID 定义
│       └── tasks.c                    ← 任务集中注册
├── examples/                          ← 6 个示例任务
│   ├── task_led.c                     ← LED 闪烁
│   ├── task_key.c                     ← 按键扫描 + 消息发送
│   ├── task_echo.c                    ← 串口回显 + 定时报告 + 事件接收
│   ├── task_ota.c                     ← OTA 升级(纯事件驱动)
│   ├── task_sensor.c                  ← 传感器读取(慢周期)
│   └── task_relay.c                   ← 继电器定时控制
└── port/                              ← 移植指南
    └── PORTING.md                     ← 各平台移植说明

2. 移植到你的项目

三步移植:

① 实现 1ms 硬件定时器

在你的工程中创建一个 timer.c,实现:

#include "scheduler/ptask.h"

void Timer_Init_1ms(void)
{
    // 配置你的 MCU 硬件定时器,产生 1ms 中断
    // 在定时器中断中调用 PTASK_Tick();
}

// 定时器中断服务函数
void TIMx_IRQHandler(void)
{
    // 清除中断标志
    PTASK_Tick();  // ← 驱动调度器时基
}

各平台的参考实现见 port/PORTING.md

② 创建一个任务

复制 examples/task_led.c 到你的 User/ 目录,按需修改:

#include "scheduler/ttask.h"

static void my_init(void)     { /* 初始化外设 */ }
static void my_periodic(void) { /* 周期执行的逻辑 */ }
static void my_event(uint16_t event, uint16_t param, void *data) {
    /* 收到消息时处理 */
}

TTask task_my = {
    .init      = my_init,
    .periodic  = my_periodic,
    .interval  = 100,        // 每 100ms 执行一次
    .on_event  = my_event,
};

③ 注册任务

scheduler/tasks.h 加一行 ID:

#define TASK_ID_MY      6    /* 你的新任务 */

scheduler/tasks.c 加一行注册:

extern TTask task_my;
TTASK_Register(&task_my);   /* TASK_ID_MY = 6 */

3. 核心 API

API 说明
TTASK_Init() 初始化调度器
TTASK_Register(&task) 注册任务,返回 ID
TTASK_Run() 主循环调用,驱动调度
TTASK_SendEvent(id, param) 发送消息
TTASK_SendEventISR(id, param) 从中断发送消息
PTASK_GetTick() 获取 1ms 时基计数值

4. 三种任务模式

模式 实现方式 适用场景
周期执行 .periodic + .interval LED 闪烁、按键扫描、传感器轮询
事件驱动 .on_event,不填 periodic OTA 升级、串口命令响应
混合 两者都填 继电器控制(周期检查超时 + 事件触发开关)

5. 任务间通信

// 发消息
TTASK_SendEvent(TASK_ID_ECHO, TASK_PARAM(1, 1));  // 按键1单击

// 收消息(定义 on_event 回调即可)
static void my_event(uint16_t event, uint16_t param, void *data) {
    uint8_t key = TASK_KEY(param);    // 获取按键号
    uint8_t evt = TASK_EVT(param);    // 获取事件类型
}

6. 关键特性

特性 说明
零 RTOS 依赖 纯 C 实现,只需 1ms 硬件定时器
低 RAM 占用 每任务约 20 字节
补偿式调度 last_run += interval,消除时间漂移
消息队列 每任务 8 条深度,环形缓冲
中断安全 SendEventISR 关中断保护
uint32_t 溢出安全 差值计算,溢出后仍正确

7. 从轮询迁移到 TTask

// 改造前:超级循环
while(1) {
    KEY_Scan();
    USART_Echo();
    Sensor_Read();
    LED_Toggle();
    Delay_Ms(10);
}

// 改造后:拆成 4 个 TTask
TTask task_key    = { .periodic=KEY_Scan,      .interval=10 };
TTask task_echo   = { .periodic=USART_Echo,    .interval=1 };
TTask task_sensor = { .periodic=Sensor_Read,   .interval=1000 };
TTask task_led    = { .periodic=LED_Toggle,    .interval=500 };

// main 只剩一行
while(1) TTASK_Run();

许可证

基于 WCH 官方 CH32V303 EVT 例程的调度器实现,MIT 许可证。

About

轻量级裸机任务调度器,不用 RTOS。 每个任务只需填三个函数指针(init / periodic / on_event),调度器自动按时机调用。 支持消息队列通信、1ms 精确定时。

Resources

Stars

Watchers

Forks

Contributors

Languages