分享一个用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 作者黄工,高级嵌入式软件工程师,分享嵌入式软硬件、物联网、单片机、开发工具、电子等内容。
评论 (0)
  • ​ 一、公司及产品概述作为国内领先的语音芯片研发企业,深耕语音技术领域25年,其产品以高稳定性、低功耗和多场景适应性著称。公司推出的语音识别芯片系列(如WTK6900系列)融合了语音识别、自然语言处理、音频编解码等核心技术,广泛应用于智能家居、工业设备、医疗电子及消费类产品中。二、核心技术特点语音识别与处理技术 厂家语音识别芯片采用先进的信号处理算法(如MFCC特征提取)和机器学习模型(如DNN、HMM),支持多语言、方言及复杂环境下的高精度识别。芯片内置噪声抑制和回声消除功能,即使在
    广州唯创电子 2025-03-19 08:48 42浏览
  • 在PCB(印刷电路板)的制造过程中,材料选择对最终产品的性能、稳定性和可靠性有着直接的影响。作为行业领先的PCB制造商,捷多邦始终坚持在材料选择上精益求精,确保每一款PCB产品都能够满足客户对高质量的需求。今天,我们将重点分析FR4、Rogers和铝基板三种常见材料,它们如何影响PCB的质量与性能,以及捷多邦如何通过优化材料选择为客户提供更具竞争力的产品。1. FR4:高性价比的通用材料FR4是最常见的PCB基材,广泛应用于消费电子、通信、计算机等领域。它由玻璃纤维和环氧树脂复合而成,具有良好的
    捷多邦 2025-03-19 10:09 63浏览
  • ​ 在智能设备普及的今天,语音识别已成为人机交互的核心入口。然而,环境噪声、口音差异、硬件设计限制等因素常导致识别率下降,影响用户体验。广州唯创电子凭借25年技术积累,推出 WTK6900系列语音识别芯片,通过“芯片性能+算法优化+场景适配”三位一体的解决方案,将标准方案识别率提升至 97%,为行业树立技术标杆。一、WTK6900系列:破解语音识别难题的核心利器1. 高性能芯片架构,奠定识别基础WTK6900系列采用 32位高性能处理器 与 深度神经网络(DNN)算法,支持实时语音信号
    广州唯创电子 2025-03-19 09:11 30浏览
  • 在电子产品制造中,选择合适的PCB至关重要。虽然廉价PCB节省成本,但长期使用下来,它们可能会带来更多的风险和隐患。作为工程师,我们需要权衡PCB的质量与成本,尤其是在高要求的应用中。论文将以捷多邦为例,分析廉价PCB与高质量PCB的差异。 1.材料与性能廉价PCB通常采用低质量材料,这可能会影响其电气和机械性能。相比之下,捷多邦的高质量PCB采用符合行业标准的优质材料(如FR4、PTFE等),确保更高的热稳定性和抗湿性,提升产品的可靠性。 2.准确性与可靠性廉价的PCB工艺
    捷多邦 2025-03-19 09:36 80浏览
  • 在电子制造业中,PCB(印制电路板)作为电子设备的核心组件,其质量直接决定了产品的性能和可靠性。尤其是高端PCB,广泛应用于航空航天、医疗设备、通信设备等领域,对质量的要求近乎苛刻。捷多邦作为PCB行业的领先品牌,深知严格的质量管理体系是确保高端PCB制造成功的关键。1. ​原材料质量控制高端PCB的制造始于原材料的严格筛选。捷多邦采用符合IPC标准的基材,如FR-4、PTFE等,确保材料的电气性能、机械性能和耐热性满足高端应用需求。通过严格的入库检验,包括铜箔附着力、表面平整度等测试。2. ​
    捷多邦 2025-03-19 10:13 77浏览
  • 在电子领域,高品质线路板是众多电子产品稳定运行的基石。那么,究竟达到怎样的标准,才能被称为高品质线路板呢?​捷多邦小编整理了关于高品质线路板的标准解析​,一起看看吧。 从电气性能角度出发,高品质线路板首当其冲要确保线路导通性良好。这意味着电流能顺畅地在铜箔线路中流动,电阻、电容等关键参数必须严格符合设计要求。无论是在初始运行,还是经过长时间的使​用后,都能维持稳定的电气性能,不出现参数漂移等问题。同时,面对复杂的电磁环境,它要有极强的抗干扰能力,有效减少信号传输时的失真与干扰,保证信号
    捷多邦 2025-03-19 09:33 78浏览
  • 在现代电子行业,PCB(印刷电路板)的质量直接影响到产品的稳定性与性能。作为全球领先的PCB制造商,捷多邦始终将质量放在第一位,致力于为客户提供高可靠性、高精度的PCB产品。为了确保每一块成品PCB都符合最高的质量标准,捷多邦在从设计到生产的每个环节都严格把控,确保质量无可挑剔。1. 精准设计:从需求到规格PCB的质量首先体现在设计阶段。捷多邦的设计团队根据客户需求,使用最新的EDA软件进行电路板布局设计。通过设计规则检查(DRC),确保电路板设计满足行业标准和客户的特殊需求。无论是单面板、双面
    捷多邦 2025-03-19 10:09 61浏览
  • 概念在GNSS测量和地理信息系统(GIS)中,基线(Baseline)是指两个或多个接收机之间的直线距离,通常用于描述RTK(实时动态定位)或其他差分GPS技术中的相对位置关系。基线通常由三个分量表示:东向(East)、北向(North)和垂直向(Up),分别表示两个测点之间的东西方向、南北方向和垂直方向的距离差。RTK(Real-Time Kinematic,实时动态)基线是指在RTK GPS测量技术中,两个测站(通常是一个固定的基准站和一个移动的接收站)之间的向量差。这个向量差包括了两个测站
    德思特测试测量 2025-03-19 11:23 80浏览
  • PCB层数越多质量就越好吗?多层板制造中的质量控制要点随着电子产品对性能和功能要求的不断提高,多层PCB(多层印刷电路板)已经成为众多高端应用领域的标准配置。很多人存在一个误区:层数越多的PCB质量就一定越好。实际上,层数与质量并不是直接的正比关系,正确的设计和精确的质量控制才是决定PCB质量的关键。1. 层数并非质量的唯一标准多层PCB的质量并不仅仅取决于层数的多少,而是与其设计、制造精度和材料的选择密切相关。增加层数的目的通常是为了提高电路密度和实现复杂的布线结构。如果设计不合理或制造不精确
    捷多邦 2025-03-19 10:14 115浏览
  • 这是一个很有意思的话题,在职场人士之间争论不休。证书到底有没有用?有人支持,也有人反对。不过,在正式聊这个话题之前,我想先分享一个我亲身经历的真实故事。那时,我和同学们正在读管理学的研究生课程。有一次,我们的教授要求大家穿正装上课。这时,有个同学问了个很有趣的问题:“教授,某某的董事长可以穿得五颜六色,我们这些职场新人为什么非得穿正装?”教授听后,停顿了一下,然后淡定地回了句:“你当然也可以穿得五颜六色,但前提是——先成为某某的董事长那样的人。”这句话点出了一个事实:同一套规则,并不适用于所有人
    优思学院 2025-03-19 12:02 70浏览
  • 在PCB制造过程中,表面处理工艺的选择直接影响到电路板的性能、可靠性和成本。捷多邦作为行业领先的PCB制造商,致力于为客户提供高质量、高可靠性的PCB产品。本文将深入探讨沉金、镀金和HASL(热风整平)三种常见表面处理工艺的特点及其对PCB质量的影响,帮助您做出最佳选择。 1. 沉金(ENIG)沉金工艺通过化学沉积在PCB表面形成一层镍金合金,具有以下优势: ​平整度高:适合高密度、细间距的PCB设计,尤其适用于BGA和QFN封装。​抗氧化性强:金层能有效防止铜氧化,延长PC
    捷多邦 2025-03-19 10:11 84浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦