分享一个用C++编写的轻量级RTOS

原创 strongerHuang 2025-03-15 08:20
关注+星标公众,不错过精彩内容
图片

作者 | strongerHuang

微信公众号 | strongerHuang

C++遇上轻量级,你可能觉得“不可思议”。

今天就来分享一个GitHub上开源的用C++编写的轻量级的RTOS:scmRTOS

关于scmRTOS

scmRTOS是一个用C++编写的,适用于MCU的轻量级实时操作系统。

最低只需要512字节RAM(内存)、1K的代码量、具有上下文切换极低的延时。

开源地址:

https://github.com/scmrtos/scmrtos


支持的MCU平台或类型:
  • MSP430

  • AVR

  • Blackfin

  • ARM7

  • Cortex-M0

  • Cortex-M3

  • Cortex-M4

  • STM8


上下文切换耗时情况:
  • 900 ns在Cortex-M4上@ 168 MHz

  • 1.8 us在Blackfin上@ 200 MHz

  • 2.7 us在Cortex-M3上@72 MHz

  • 5 us在ARM7上@ 50 MHz

  • 38-42 us在AVR上@ 8 MHz

  • 45-50 us在MSP430上@ 5 MHz

  • 18-20 us在STM8上@ 16 MHz


内核全用C++编写:
内核os_kernel.cpp的源代码量也很小:
#include "scmRTOS.h"
using namespace OS;
OS::TKernel OS::Kernel;
#if scmRTOS_SUSPENDED_PROCESS_ENABLE != 0OS::TProcessMap OS::TBaseProcess::SuspendedProcessMap = (1ul << (PROCESS_COUNT)) - 1#endif
TBaseProcess * TKernel::ProcessTable[scmRTOS_PROCESS_COUNT + 1];
//------------------------------------------------------------------------------////    TKernel functions//#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0void TKernel::sched(){    uint_fast8_t NextPrty = highest_priority(ReadyProcessMap);    if(NextPrty != CurProcPriority)    {    #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1        context_switch_user_hook();    #endif
        stack_item_t*  Next_SP      = ProcessTable[NextPrty]->StackPointer;        stack_item_t** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);        CurProcPriority = NextPrty;        os_context_switcher(Curr_SP_addr, Next_SP);    }}#else//------------------------------------------------------------------------------void TKernel::sched(){    uint_fast8_t NextPrty = highest_priority(ReadyProcessMap);    if(NextPrty != CurProcPriority)    {        SchedProcPriority = NextPrty;
        raise_context_switch();        do        {            enable_context_switch();            DUMMY_INSTR();            disable_context_switch();        }         while(CurProcPriority != SchedProcPriority); // until context switch done    }}//------------------------------------------------------------------------------stack_item_tos_context_switch_hook(stack_item_t* sp) return Kernel.context_switch_hook(sp); }//------------------------------------------------------------------------------#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
//------------------------------------------------------------------------------////       OS Process's constructor////       Performs:  //           * initializing process data;//           * registering process in the kernel;//           * initializing stack frame;//                  //#if SEPARATE_RETURN_STACK == 0
TBaseProcess::TBaseProcessstack_item_t * StackPoolEnd                          , TPriority pr                          , void (*exec)()                      #if scmRTOS_DEBUG_ENABLE == 1                          , stack_item_t * aStackPool                          , const char   * name_str                      #endif                          ) : Timeout(0)                            , Priority(pr)                      #if scmRTOS_DEBUG_ENABLE == 1                            , WaitingFor(0)                            , StackPool(aStackPool)                            , StackSize(StackPoolEnd - aStackPool)                            , Name(name_str)                      #endif                       #if scmRTOS_PROCESS_RESTART_ENABLE == 1                            , WaitingProcessMap(0)                      #endif
{    TKernel::register_process(this);    init_stack_frame( StackPoolEnd                    , exec                #if scmRTOS_DEBUG_ENABLE == 1                         , aStackPool                #endif                      );}
#else  // SEPARATE_RETURN_STACK
TBaseProcess::TBaseProcessstack_item_t * Stack                          , stack_item_t * RStack                          , TPriority pr                          , void (*exec)()                      #if scmRTOS_DEBUG_ENABLE == 1                          , stack_item_t * aStackPool                          , stack_item_t * aRStackPool                          , const char   * name_str                      #endif                          ) : StackPointer(Stack)                            , Timeout(0)                            , Priority(pr)                      #if scmRTOS_DEBUG_ENABLE == 1                            , WaitingFor(0)                            , StackPool(aStackPool)                            , StackSize(Stack - aStackPool)                            , Name(name_str)                            , RStackPool(aRStackPool)                            , RStackSize(RStack - aRStackPool)                      #endif                       #if scmRTOS_PROCESS_RESTART_ENABLE == 1                            , WaitingProcessMap(0)                      #endif
{    TKernel::register_process(this);    init_stack_frame( Stack                    , RStack                    , exec                #if scmRTOS_DEBUG_ENABLE == 1                         , aStackPool                    , aRStackPool                #endif                      );}#endif // SEPARATE_RETURN_STACK//------------------------------------------------------------------------------void TBaseProcess::sleep(timeout_t timeout){    TCritSect cs;
    Kernel.ProcessTable[Kernel.CurProcPriority]->Timeout = timeout;    Kernel.set_process_unready(Kernel.CurProcPriority);    Kernel.scheduler();}//------------------------------------------------------------------------------void OS::TBaseProcess::wake_up(){    TCritSect cs;
    if(this->Timeout)    {        this->Timeout = 0;        Kernel.set_process_ready(this->Priority);        Kernel.scheduler();    }}//------------------------------------------------------------------------------void OS::TBaseProcess::force_wake_up(){    TCritSect cs;
    this->Timeout = 0;    Kernel.set_process_ready(this->Priority);    Kernel.scheduler();}//------------------------------------------------------------------------------//////   Idle Process////namespace OS{#ifndef __GNUC__  // avoid GCC bug ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15867 )    template<> void TIdleProc::exec();#endif
#if scmRTOS_DEBUG_ENABLE == 1    TIdleProc IdleProc("Idle");#else    TIdleProc IdleProc;#endif

}
namespace OS{    template<> void TIdleProc::exec()    {        for(;;)        {        #if scmRTOS_IDLE_HOOK_ENABLE == 1            idle_process_user_hook();        #endif
        #if scmRTOS_TARGET_IDLE_HOOK_ENABLE == 1            idle_process_target_hook();        #endif        }    }}//------------------------------------------------------------------------------#if scmRTOS_DEBUG_ENABLE == 1#if SEPARATE_RETURN_STACK == 0size_t TBaseProcess::stack_slack() const{     size_t slack = 0;     const stack_item_t * Stack = StackPool;     while (*Stack++ == scmRTOS_STACK_PATTERN)         slack++;     return slack;}#else  // SEPARATE_RETURN_STACKstatic size_t calc_stack_slack(const stack_item_t * Stack){     size_t slack = 0;     while (*Stack++ == scmRTOS_STACK_PATTERN)         slack++;     return slack;}size_t TBaseProcess::stack_slack() const{     return calc_stack_slack(StackPool);}size_t TBaseProcess::rstack_slack() const{     return calc_stack_slack(RStackPool);}#endif // SEPARATE_RETURN_STACK#endif // scmRTOS_DEBUG_ENABLE//------------------------------------------------------------------------------#if scmRTOS_PROCESS_RESTART_ENABLE == 1void TBaseProcess::reset_controls(){    Kernel.set_process_unready(this->Priority);    if(WaitingProcessMap)    {        clr_prio_tag( *WaitingProcessMap, get_prio_tag(Priority) );  // remove current process from service's process map        WaitingProcessMap = 0;    }    Timeout    = 0;#if scmRTOS_DEBUG_ENABLE == 1    WaitingFor = 0;#endif}#endif  // scmRTOS_PROCESS_RESTART_ENABLE//------------------------------------------------------------------------------
内核主要是处理调度相关的内容,有认真学习过RTOS内核机制的同学应该都能看得懂。

官方针对不同的MCU平台,都提供了对应的端口(Port),只需要适当修改,即可移植到你工程。
内核还支持用户扩展,提供了调试分析、互斥、“消息队列”等功能。
最后,你觉得这款用C++编写的RTOS怎么样?
------------ END ------------

图片
●专栏《嵌入式工具
●专栏《嵌入式开发》
●专栏《Keil教程》
●嵌入式专栏精选教程

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。


点击“阅读原文”查看更多分享。

strongerHuang 作者黄工,高级嵌入式软件工程师,分享嵌入式软硬件、物联网、单片机、开发工具、电子等内容。
评论
  • 曾经靠“砍一刀”撕裂传统电商格局的拼多多,如今疲态尽显。数据显示,拼多多今年第一季度实现营收957亿元,同比增长10%,市场预估1016亿元,相比预期低了近60亿元;经营利润为161亿元,相比去年同期下降38%;归属于普通股股东的净利润为147亿元,同比下降47%。与此同时,拼多多市值也坐上了“过山车”。去年市值一度突破 2180 亿美元,力压国内电商巨头阿里,今年(7月1日收盘)市值仅余 1497.59 亿美元,已不足阿里(市值2718.63亿美元)一半
    用户1742991715177 2025-07-05 14:24 470浏览
  • 在全球广泛倡导绿色低碳与可持续发展的时代浪潮中,新能源汽车作为实现节能减排的重要载体之一,正受到各国政府与企业的加速培育。在此背景下,为提升新能源汽车的市场渗透率,我国已率先进入充电基础设施建设的加速期,从私人专用充电桩到社区公用充电桩,从高速路网补能节点到城市公用充电桩,汽车补能网络正在急速膨胀中。图源:摄图网(已授权)据中国充电联盟(EVCIPA)最新统计数据显示,截止2025年5月份,我国充电基础设施累计数量为1440万台,同比上升45.1%。其中,在2025年1月~5月期间,我国充电基础
    华普微HOPERF 2025-07-09 16:13 367浏览
  •   去年底,整理旧物,扔的扔了,留的留了,这不,十四个几十年前留下来的工业级小型排风扇,下图左上角处,又拿出来,下决心把它们再利用发挥余热。  呵呵,这回不是拆而是装了。怎么装呢?组装、固定、机架、接线,简单,也不简单,原则是一切都用手头现有废旧材料,争取做到一个不买!DIY,废物利用,如今时髦的话,以旧换新!摆上台面,找来木条,策划怎么做?  比一比,看一看,觉得合适,按尺寸锯开木条。  咋走线?想到了,在有限空间内弯转,从一个螺丝孔穿出来,整体拼凑整齐。   咋固定风扇呢?找来木片条,锯断,
    自做自受 2025-07-06 21:37 639浏览
  • 在数字化、自动化高速发展的今天,光电耦合器正以一种低调却不可或缺的方式,悄然改变着我们的生活。它不仅是电子电路中的“安全卫士”,更是连接信号世界的“桥梁”,凭借出色的电气隔离能力,为各类设备提供稳定可靠的信号传输保障。电气隔离——让系统更安全在工业控制系统中,安全始终是重中之重。光电耦合器通过光信号进行电气隔离,能够有效防止高压电流侵入低压控制电路。例如,在智能电网系统中,它广泛应用于电表与通信模块之间,确保数据传输的安全性,防止电网高压对低压设备造成冲击。在电动汽车的电池管理系统(BMS)中,
    腾恩科技-彭工 2025-07-05 13:56 480浏览
  • 什么是LoRaWAN? LoRaWAN技术及应用LoRaWAN(Long Range Wide Area Network)是一种低功耗、长距离、广域网络通信协议,特别设计用于连接物联网(IoT)设备。LoRaWAN采用无线通信技术,能够覆盖数十公里的范围,提供长时间的电池寿命,适用于智能城市、农业、工业自动化、环境监测,与健康医疗等领域应用。来源: LoRa Alliance一探究竟:LoRaWAN物联网应用优势营运商采用 LoRaWAN 具有多方面的优势,除了长距离覆盖范围及低功耗的特点外,还
    百佳泰测试实验室 2025-07-10 14:51 430浏览
  •   几个月前,一个老旧的大风扇的散风圈(俺不知其专业名称)的开关按钮不起作用,就是锁不住了,散风圈也就不转了。今天,有空,就拿到工作台,开始拆解分析故障原因,能修好更好。  看看,用的时间够长了吧!皮肤都变颜色了。看标签,合格品2005年的。  底部四个螺丝固定,很容易拆开了。  看到掉下一个标签圆纸片,拿起来看看,是那个横向摇头的电机的。  找到那个按钮开关位置  应该是开关内部的有缺陷了。把它拆下来,一看就是正规合格品。  拿出我日积月累的分类藏宝盒,呵呵,找到一款螺丝孔位正好合适的。   
    自做自受 2025-07-10 11:16 462浏览
  • 提要:采用LOXIM的微孔雾化专用芯片LX8201,能突破压电陶瓷驱动电压超标(24伏)的技术难题,满足全球市场对喷雾玩具的电压安规认证要求。玩具行业尤其是喷雾玩具行业内人士都知道,喷雾玩具的压电陶瓷驱动电压超标(常需60-100V)与强制安规标准(中国,日本,欧美,都一样)对玩具电压的限制(≤24V)存在根本性冲突,如果采用“多层压电堆叠(MPA)技术“(比如日本TDK公司),成本将增加至现有微孔雾化片的10倍以上,这个矛盾一直没有得到好的解决。喷雾玩具在国内热销(淘宝/抖音),能卖的原因,无
    Loximonline 2025-07-08 10:55 318浏览
  • 在物联网无线通信领域,随着行业应用场景的不断拓宽,同一频段下的设备通信需求正呈指数级增长,然而这一增长趋势却与频谱资源的有限性形成了鲜明对立,信道拥挤、信号串扰与非线性失真等不良现象所造成的“通信压力”正在持续放大。从智能家居的设备互联到工业物联网的实时控制,从智慧楼宇的广域组网到智慧城市的海量数据传输,有限的频谱资源不仅需要满足不断增长的设备通信需求,还需要适配不同场景对速率、时延与可靠性等差异化要求。在此背景下,如何在有限的频谱资源中实现更为稳定的无线通信质量,已成为物联网行业发展路径中的核
    华普微HOPERF 2025-07-07 16:13 681浏览
  • 据知名市场研究机构Counterpoint Research发布的数据概览,2025年第二季度,中国智能手机销量预计将迎来小幅回暖,增长率约为1%。在这场销量微增的背后,华为与苹果两大品牌成为了推动市场前行的核心力量。其中华为手机的表现最为亮眼,数据显示,华为在中国市场的智能手机销量份额实现了12%的同比增长,这一成绩不仅使其成为了当季增长最快的品牌,更助力华为重新夺回销量榜首的位置。相比之下,vivo的表现就有些尴尬了。虽然还是位列第二,但vivo在第二季度的智能手机销量份额同比下降了9%,下
    用户1742991715177 2025-07-09 08:19 303浏览
  • 本文主要针对分立方案高速输出电路,由于MOS管、稳压管、PCB布局布线都存在一些寄生电容,这些寄生电容都会影响高速输出电路的占空比,所以本文对这些寄生电容的影响进行简单说明。测试工况:电压:24V,负载类型:阻性负载2K,输出频率:200Khz,要求占空比45%~55%;电路拓扑如下图所示:图1寄生电容分布情况:如下图所示,MOS管寄生电容为Cgd、Cgs、Cds,稳压管寄生电容为Cd;图2而MOS管手册常见的参数如下图所示为Ciss、Coss、Crss(为啥是这些参数,而不改成Cgs、Cgd、
    用户1751282873645 2025-07-08 23:58 277浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦