vesperW · 5 小时前

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

大家好,我是麦鸽。

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

image.png

核心文件

项目概述:

这是一个轻量级的协作式多任务处理(任务调度)实现。相比于抢占式编程和像 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() 实现)

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

Image

架构

如何使用?

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

Image

样例

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

// ==== 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

END

作者:小麦大叔
来源:小麦大叔

推荐阅读

欢迎大家点赞留言,更多 Arm 技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
2896
内容数
304
分享一些在嵌入式应用开发方面的浅见,广交朋友
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息