微信公眾號(hào) | strongerHuang
當(dāng)C++遇上輕量級(jí),你可能覺(jué)得“不可思議”。
今天就來(lái)分享一個(gè)GitHub上開(kāi)源的用C++編寫(xiě)的輕量級(jí)的RTOS:scmRTOS。
關(guān)于scmRTOS
scmRTOS是一個(gè)用C++編寫(xiě)的,適用于MCU的輕量級(jí)實(shí)時(shí)操作系統(tǒng)。
最低只需要512字節(jié)RAM(內(nèi)存)、1K的代碼量、具有上下文切換極低的延時(shí)。
開(kāi)源地址:https://github.com/scmrtos/scmrtos
支持的MCU平臺(tái)或類型:
MSP430
Blackfin
ARM7
Cortex-M0
Cortex-M4
STM8
上下文切換耗時(shí)情況:
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
內(nèi)核全用C++編寫(xiě):
內(nèi)核os_kernel.cpp的源代碼量也很小:
#include?"scmRTOS.h"
using?namespace?OS;
OS::TKernel OS::Kernel;
#if?scmRTOS_SUSPENDED_PROCESS_ENABLE != 0
OS::TProcessMap OS::TBaseProcess::SuspendedProcessMap = (1ul?<< (PROCESS_COUNT)) -?1;?
#endif
TBaseProcess * TKernel::ProcessTable[scmRTOS_PROCESS_COUNT +?1];
//------------------------------------------------------------------------------
//
// ? ?TKernel functions
//
#if?scmRTOS_CONTEXT_SWITCH_SCHEME == 0
void?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_t*?os_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::TBaseProcess(?stack_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::TBaseProcess(?stack_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 == 0
size_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_STACK
static?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 == 1
void?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
//------------------------------------------------------------------------------
內(nèi)核主要是處理調(diào)度相關(guān)的內(nèi)容,有認(rèn)真學(xué)習(xí)過(guò)RTOS內(nèi)核機(jī)制的同學(xué)應(yīng)該都能看得懂。
官方針對(duì)不同的MCU平臺(tái),都提供了對(duì)應(yīng)的端口(Port),只需要適當(dāng)修改,即可移植到你工程。
內(nèi)核還支持用戶擴(kuò)展,提供了調(diào)試分析、互斥、“消息隊(duì)列”等功能。
最后,你覺(jué)得這款用C++編寫(xiě)的RTOS怎么樣?