推荐一个开源的轻量级任务调度器!TaskScheduler!

大家好,我是麦鸽。

这次推荐一款轻量级的嵌入式任务调度器,目前已经有1.4Kstar,这个项目比较轻量化,只有5个源文件,可以作为学习的一个开源项目。
核心文件

项目概述:

这是一个轻量级的协作式多任务处理(任务调度)实现。相比于抢占式编程和像 FreeRTOS 这样的框架,它提供了一种更简单的替代方案。

为什么是协作式的?

使用协作式处理时,我们无需过多担心并发处理中的陷阱(如竞态条件、死锁、活锁、资源共享等)。

协作式处理的设计天然地解决了这些问题。

正如 Herb Sutter(ISO C++ 标准委员会主席,微软公司)所说:

"每个学习并发编程的人,都认为自己理解了它,但最终都会发现自己遇到了原本认为不可能发生的竞态条件,发现自己其实并没有真正理解它。"

主要特点:

  • 周期性任务执行,支持动态的执行周期(默认是毫秒,也可以启用微秒精度)------执行频率

  • 任务迭代次数(有限或无限次迭代)

  • 预定义顺序执行任务

  • 动态调整任务执行参数(频率、迭代次数、回调方法)

  • 省电模式,当没有任务调度时进入空闲睡眠模式

  • 支持通过状态请求对象(Status Request)进行事件驱动的任务调用

  • 支持任务ID和控制点,用于错误处理和看门狗定时器

  • 支持本地任务存储指针(允许多个任务共享相同的回调代码)

  • 支持分层任务优先级

  • 支持 std::function(仅在 ESPx 和 STM32 测试过)

  • 任务超时功能

  • 支持静态和动态回调方法绑定

  • 提供 CPU负载/空闲统计,适用于时间敏感型应用

  • 支持带有优先级的调度选项(原始调度的优先级及间隔,包括是否处理调度遗漏)

  • 能够暂停/恢复启用/禁用调度

  • 在抢占式调度器(如 FreeRTOS)下提供线程安全的调度

  • 支持动态创建的任务在禁用时自动销毁

  • 支持在 FreeRTOS 下的"无滴答"执行(持续睡眠直到下一次调度任务调用)

  • 调度开销:每次调度约 15 至 18 微秒(以 Arduino UNO rev 3,16MHz 时钟为例,单一调度器,不带优先级)

兼容平台:

TaskScheduler 已在以下平台上进行过测试:

  • Arduino Uno R3

  • Arduino Nano

  • Arduino Micro

  • ATtiny85

  • ESP8266

  • ESP32

  • Teensy(测试过 Teensy 3.5)

  • nRF52(测试过 nRF52832)

  • nRF52 Adafruit Core(测试过 nRF52840,v3.6.2 修复版)

  • STM32(测试过 Mini USB STM32F103RCBT6 ARM Cortex-M3,Leaflabs Leaf maple mini 模块 F)

  • MSP430 和 MSP432 开发板

  • Raspberry Pi(需要外部的 Arduino.h 和 millis() 实现)

该项目为实现协作式多任务处理提供了一个简洁而高效的方案,尤其适用于需要周期性任务和节能模式的嵌入式系统。
架构

如何使用?

项目里已经提供了大量的样例程序,不过都是基于Arduino平台,也都是比较好理解的;
样例

下面是一段调度器使用的模板程序,具体如何使用,可以参考一下;

go 复制代码
// ==== Debug and Test options ==================
#define _DEBUG_
//#define _TEST_

//===== Debugging macros ========================
#ifdef _DEBUG_
#define SerialD Serial
#define _PM(a) SerialD.print(millis()); SerialD.print(": "); SerialD.println(a)
#define _PP(a) SerialD.print(a)
#define _PL(a) SerialD.println(a)
#define _PX(a) SerialD.println(a, HEX)
#else
#define _PM(a)
#define _PP(a)
#define _PL(a)
#define _PX(a)
#endif

#include <TaskScheduler.h>
Scheduler ts;

void task1Callback();
void task2Callback();

// ==== Task definitions ========================
Task t1 (100 * TASK_MILLISECOND, TASK_FOREVER, &task1Callback, &ts, true);
Task t2 (TASK_IMMEDIATE, 100 /* times */, &task2Callback, &ts, true);

void setup() {
  // put your setup code here, to run once:
#if defined(_DEBUG_) || defined(_TEST_)
  Serial.begin(115200);
  delay(2000);
  _PL("Scheduler Template: setup()");
#endif
}

// main loop
void loop() {
  ts.execute();
}

void task1Callback() {
_PM("task1Callback()");
//  task code
}

void task2Callback() {
_PM("task2Callback()");
//  task code
}

项目地址:https://github.com/arkhipenko/TaskScheduler

往期推荐

<>

新手必看!C语言精华知识:表驱动法
<>

<>

9条必学的嵌入式C语言调试技巧!宏定义的妙用
<>

<>

踩坑了!嵌入式C语言常见的几个陷阱!你遇到过吗?
<>

<>

嵌入式开发又遇到BUG?怎么办?教你几招直接起飞
<>

现成轮子OSAL操作系统抽象层的移植