12#include "stk_config.h"
14#ifdef _STK_ARCH_ARM_CORTEX_M
18#ifdef STK_CORTEX_M_TRUSTZONE
30#error Expecting __CORTEX_M with value corresponding to Cortex-M model (0, 3, 4, ...)!
35 #error "SysTick peripheral definition is missing"
39#if (__CORTEX_M > 1U) && STK_TICKLESS_USE_ARM_DWT && !defined(DWT)
40 #error "DWT peripheral definition is missing"
44#define STK_CORTEX_M_FPU ((__FPU_PRESENT == 1U) && (__FPU_USED == 1U))
47#define STK_CORTEX_M_MANAGE_LR (__CORTEX_M >= 3U)
50#define STK_CORTEX_M_EXC_RETURN_HANDLR_MSP 0xFFFFFFF1U
51#define STK_CORTEX_M_EXC_RETURN_THREAD_MSP 0xFFFFFFF9U
52#define STK_CORTEX_M_EXC_RETURN_THREAD_PSP 0xFFFFFFFDU
57#define STK_CORTEX_M_EXC_RETURN_S_HANDLR_MSP 0xFFFFFFE1U
58#define STK_CORTEX_M_EXC_RETURN_S_THREAD_MSP 0xFFFFFFE9U
59#define STK_CORTEX_M_EXC_RETURN_S_THREAD_PSP 0xFFFFFFEDU
61#define STK_CORTEX_M_EXC_RETURN_NS_THREAD_PSP 0xFFFFFFBCU
64#define STK_CORTEX_M_EXC_RETURN_S_BIT 0x00000040U
66#define STK_CORTEX_M_ISR_PRIORITY_HIGHEST 0
67#define STK_CORTEX_M_ISR_PRIORITY_LOWEST 0xFF
70#if STK_CORTEX_M_MANAGE_LR
71 #define STK_CORTEX_M_REGISTER_COUNT 17
73 #define STK_CORTEX_M_REGISTER_COUNT 16
77#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
78 #define STK_CORTEX_M_TZ_REGISTER_COUNT 2
80 #define STK_CORTEX_M_TZ_REGISTER_COUNT 0
84#define STK_CORTEX_M_TOTAL_REGISTER_COUNT \
85 (STK_CORTEX_M_REGISTER_COUNT + STK_CORTEX_M_TZ_REGISTER_COUNT)
88#ifndef STK_SYSTICK_HANDLER
89 #define STK_SYSTICK_HANDLER SysTick_Handler
93#ifndef STK_PENDSV_HANDLER
94 #define STK_PENDSV_HANDLER PendSV_Handler
98#ifndef STK_SVC_HANDLER
99 #define STK_SVC_HANDLER SVC_Handler
103enum ESvcCommandId : uint8_t
105 SVC_START_SCHEDULING = 0,
126#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
166#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
169#if STK_CORTEX_M_MANAGE_LR
176#define STK_ASM_EXIT_FROM_HANDLER "BX LR"
177#define STK_ASM_EXIT_FROM_FUNCTION "BX LR"
178#define STK_ASM_DISABLE_INTERRUPTS "CPSID i"
179#define STK_ASM_ENABLE_INTERRUPTS "CPSIE i"
186 __asm
volatile(
"SVC %0"
188 :
"I"(SVC_START_SCHEDULING)
194#ifdef SVC_FORCE_SWITCH
197 __asm
volatile(
"SVC %0"
199 :
"I"(SVC_FORCE_SWITCH)
226 STK_ASM_EXIT_FROM_FUNCTION
" \n"
228 :
"I"(SVC_ENTER_CRITICAL)
253 STK_ASM_EXIT_FROM_FUNCTION
" \n"
255 :
"I"(SVC_EXIT_CRITICAL)
263#if (defined(__clang__) && defined(__ARMCOMPILER_VERSION)) || defined(__ICCARM__)
264 __asm
volatile(STK_ASM_DISABLE_INTERRUPTS :::
"memory");
274#if (defined(__clang__) && defined(__ARMCOMPILER_VERSION)) || defined(__ICCARM__)
275 __asm
volatile(STK_ASM_ENABLE_INTERRUPTS :::
"memory");
286#if (defined(__clang__) && defined(__ARMCOMPILER_VERSION)) || defined(__ICCARM__)
288 __asm
volatile(
"MRS %0, primask" :
"=r"(primask));
289 return (primask & 1U);
291 return (__get_PRIMASK() & 1U);
300 SES = __get_PRIMASK();
301 HW_DisableInterrupts();
322#ifdef CONTROL_nPRIV_Msk
337 return !__atomic_test_and_set(&lock, __ATOMIC_ACQUIRE);
361 __asm
volatile(
"dmb ishst" :::
"memory");
363 __atomic_clear(&lock, __ATOMIC_RELEASE);
365#elif defined(RP2040_H)
367#define STK_SIO_SPINLOCK SIO->SPINLOCK31
386 bool success = (STK_SIO_SPINLOCK == 0 ? false : ((lock) =
true,
true));
415 STK_SIO_SPINLOCK = 1;
418#undef STK_SIO_SPINLOCK
438 HW_CriticalSectionStart(ses);
442 HW_CriticalSectionEnd(ses);
449 HW_CriticalSectionEnd(ses);
491 uint32_t timeout = 0xFFFFFF;
492 while (!HW_SpinLockTryLock(lock))
539 Word R4, R5, R6, R7, R8, R9, R10, R11;
562int32_t SaveJmp(JmpFrame &)
566#if (__CORTEX_M >= 3U)
568 "STMIA r0, {r4-r11} \n"
569 "STR sp, [r0, #32] \n"
570 "STR lr, [r0, #36] \n"
573 "STR r4, [r0, #0] \n"
574 "STR r5, [r0, #4] \n"
575 "STR r6, [r0, #8] \n"
576 "STR r7, [r0, #12] \n"
578 "STR r1, [r0, #16] \n"
580 "STR r1, [r0, #20] \n"
582 "STR r1, [r0, #24] \n"
584 "STR r1, [r0, #28] \n"
586 "STR r1, [r0, #32] \n"
588 "STR r1, [r0, #36] \n"
593 "STR r1, [r0, #40] \n"
618void RestoreJmp(JmpFrame &, int32_t )
622#if (__CORTEX_M >= 3U)
624 "LDR sp, [r0, #32] \n"
626 "LDR r2, [r0, #40] \n"
629 "LDR r2, [r0, #36] \n"
630 "LDMIA r0, {r4-r11} \n"
635 "LDR r2, [r0, #36] \n"
637 "LDR r2, [r0, #32] \n"
639 "LDR r2, [r0, #28] \n"
641 "LDR r2, [r0, #24] \n"
643 "LDR r2, [r0, #20] \n"
645 "LDR r2, [r0, #16] \n"
647 "LDR r4, [r0, #0] \n"
648 "LDR r5, [r0, #4] \n"
649 "LDR r6, [r0, #8] \n"
650 "LDR r7, [r0, #12] \n"
663 return (__get_IPSR() != 0U);
671#ifdef CONTROL_nPRIV_Msk
672 return ((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0U);
685 __asm
volatile(
"MOV %0, sp" :
"=r" (sp));
693 SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
701 __set_CONTROL(__get_CONTROL() & ~CONTROL_FPCA_Msk);
711 SCB->CPACR |= (0b11 << 20) | (0b11 << 22);
745 SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;
752 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
764 uint32_t VAL = SysTick->VAL;
776 return SysTick->LOAD - VAL;
784 SysTick->LOAD = ticks - 1U;
786 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
793#if defined(CoreDebug)
795 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
801#if (__CORTEX_M == 7U)
802 DWT->LAR = 0xC5ACCE55;
808 DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
812 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
830static volatile bool s_StkCortexmCsuLock =
false;
835 Context() : PlatformContext(), m_exit_buf(), m_overrider(nullptr),
837 m_sleep_ticks(0), m_sleep_error(0U),
839 m_csu(0U), m_csu_nesting(0U), m_started(false), m_exiting(false)
848 void Initialize(IPlatform::IEventHandler *handler, IKernelService *service, Stack *exit_trap,
849 uint32_t resolution_us)
851 PlatformContext::Initialize(handler, service, exit_trap, resolution_us);
854 "expect Stack::mode member at offset of 0 (first member)");
856 "expect Stack::mode member at offset of 4 (second member)");
860 m_overrider =
nullptr;
864 #if (__CORTEX_M > 1) && STK_TICKLESS_USE_ARM_DWT
865 HW_DWTEnableCounter();
868 #if STK_SEGGER_SYSVIEW
870 HW_CoreClockFrequency(),
871 HW_CoreClockFrequency(),
879 HW_DisableInterrupts();
881 #if STK_TICKLESS_IDLE
885 if (m_handler->OnTick(m_stack_idle, m_stack_active
891 #if STK_SEGGER_SYSVIEW
892 SEGGER_SYSVIEW_OnTaskStopExec();
893 if (
GetContext().m_stack_active->tid != SYS_TASK_ID_SLEEP)
894 SEGGER_SYSVIEW_OnTaskStartExec(
GetContext().m_stack_active->tid);
897 HW_ScheduleContextSwitch();
901 #if STK_TICKLESS_IDLE
902 if (ticks != m_sleep_ticks)
904 ReloadTickPeriod(ticks);
905 m_sleep_ticks = ticks;
909 HW_EnableInterrupts();
915 uint32_t current_ses;
916 HW_CriticalSectionStart(current_ses);
918 if (m_csu_nesting == 0U)
921 HW_SpinLockLock(s_StkCortexmCsuLock);
940 if (m_csu_nesting == 0U)
943 uint32_t ses_to_restore = m_csu;
946 HW_SpinLockUnlock(s_StkCortexmCsuLock);
949 HW_CriticalSectionEnd(ses_to_restore);
957 Word current_ses = HW_SVCEnterCritical();
959 if (m_csu_nesting == 0U)
962 HW_SpinLockLock(s_StkCortexmCsuLock);
982 if (m_csu_nesting == 0U)
985 Word ses_to_restore = m_csu;
988 HW_SpinLockUnlock(s_StkCortexmCsuLock);
991 HW_SVCExitCritical(ses_to_restore);
999 void ReloadTickPeriod(Timeout ticks_requested);
1002 typedef IPlatform::IEventOverrider eovrd_t;
1004 JmpFrame m_exit_buf;
1005 eovrd_t *m_overrider;
1006#if STK_TICKLESS_IDLE
1008 uint32_t m_sleep_error;
1011 uint8_t m_csu_nesting;
1012 volatile bool m_started;
1032#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1034extern "C" stk::Word PlatformArmCortexM_GetTlsFromContext()
1039extern "C" void PlatformArmCortexM_SetTlsInContext(
stk::Word tp)
1054 HiResClockDWT() : m_acc(0), m_prev(0U)
1056 HW_DWTEnableCounter();
1058 m_prev = HW_DWTGetCounter();
1062 static HiResClockDWT *GetInstance()
1066 static HiResClockDWT clock;
1072 const uint32_t current = HW_DWTGetCounter();
1075 uint32_t delta = current - m_prev;
1087 uint32_t GetFrequency()
1089 return HW_CoreClockFrequency();
1097 static HiResClockM0 *GetInstance()
1101 static HiResClockM0 clock;
1110 uint32_t val = SysTick->VAL;
1111 uint32_t load = SysTick->LOAD;
1114 return cycles +
static_cast<Cycles>(load - val);
1117 uint32_t GetFrequency()
1119 return HW_CoreClockFrequency();
1123#if (__CORTEX_M >= 3U)
1124 typedef HiResClockDWT HiResClockImpl;
1126 typedef HiResClockM0 HiResClockImpl;
1139 HW_DisableInterrupts();
1154#if STK_TICKLESS_IDLE
1155void Context::ReloadTickPeriod(
Timeout ticks_requested)
1160 STK_ASSERT(
static_cast<uint64_t
>(ticks_requested) * reload <= UINT32_MAX);
1164#if (__CORTEX_M > 1) && STK_TICKLESS_USE_ARM_DWT
1165 const uint32_t error = HW_DWTGetCounter();
1166 __stk_compiler_barrier();
1170 HW_SysTickDisable();
1174 const uint32_t elapsed_till_stop = HW_SysTickGetElapsed(HW_SysTickValueAfterDisable());
1179 const uint32_t cpu_ticks_requested =
static_cast<uint32_t
>(ticks_requested) * reload;
1182 uint32_t new_load = cpu_ticks_requested - elapsed_till_stop - m_sleep_error;
1185 if (new_load > cpu_ticks_requested)
1186 new_load = cpu_ticks_requested;
1189 HW_SysTickRearm(new_load);
1191#if (__CORTEX_M > 1) && STK_TICKLESS_USE_ARM_DWT
1193 m_sleep_error = HW_DWTGetCounter() - error;
1198extern "C" void STK_SYSTICK_HANDLER()
1200#if STK_SEGGER_SYSVIEW
1201 SEGGER_SYSVIEW_RecordEnterISR();
1206#ifdef HAL_MODULE_ENABLED
1208#if STK_TICKLESS_IDLE
1209 uwTick += ctx.m_sleep_ticks * ctx.m_tick_resolution;
1227#if STK_SEGGER_SYSVIEW
1228 SEGGER_SYSVIEW_RecordExitISR();
1229 SEGGER_SYSVIEW_IsStarted();
1241#define STK_ASM_BLOCK_PRIVILEGE_MODE\
1242 "LDR r1, %[st_active]\n" \
1243 "LDR r1, [r1, #4] \n" \
1244 "CMP r1, %[priv_val] \n" \
1247 "MRS r0, CONTROL \n"\
1248 "ORR r0, r0, #1 \n"\
1249 "MSR CONTROL, r0 \n"\
1253 "MRS r0, CONTROL \n"\
1254 "BIC r0, r0, #1 \n"\
1255 "MSR CONTROL, r0 \n"\
1261 ".syntax unified \n"
1263 STK_ASM_DISABLE_INTERRUPTS
" \n"
1272 "VSTMDBEQ r0!, {s16-s31} \n"
1276#if STK_CORTEX_M_MANAGE_LR
1279 "STMDB r0!, {r4-r11, LR}\n"
1282 "SUBS r0, r0, #16 \n"
1283 "STMIA r0!, {r4-r7} \n"
1288 "SUBS r0, r0, #32 \n"
1289 "STMIA r0!, {r4-r7} \n"
1290 "SUBS r0, r0, #16 \n"
1294 "LDR r1, %[st_idle] \n"
1302#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1304 "MRS r3, PSPLIM_NS \n"
1305 "STMDB r0!, {r2, r3} \n"
1310#ifdef CONTROL_nPRIV_Msk
1311 STK_ASM_BLOCK_PRIVILEGE_MODE
1315 "LDR r1, %[st_active] \n"
1322#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1323 "LDMIA r0!, {r2, r3} \n"
1325 "MSR PSPLIM_NS, r3 \n"
1329#if STK_CORTEX_M_MANAGE_LR
1331 "LDMIA r0!, {r4-r11, LR}\n"
1334 "LDMIA r0!, {r4-r7} \n"
1339 "LDMIA r0!, {r4-r7} \n"
1346 "VLDMIAEQ r0!, {s16-s31} \n"
1351 STK_ASM_ENABLE_INTERRUPTS
" \n"
1353 STK_ASM_EXIT_FROM_HANDLER
" \n"
1357 [st_active]
"m" (
GetContext().m_stack_active),
1367 ".syntax unified \n"
1370#ifdef CONTROL_nPRIV_Msk
1371 STK_ASM_BLOCK_PRIVILEGE_MODE
1375 "LDR r1, %[st_active] \n"
1379#if STK_CORTEX_M_MANAGE_LR
1381 "LDMIA r0!, {r4-r11, LR}\n"
1384 "LDMIA r0!, {r4-r7} \n"
1389 "LDMIA r0!, {r4-r7} \n"
1396 "VLDMIAEQ r0!, {s16-s31} \n"
1402#if !STK_CORTEX_M_MANAGE_LR
1404 "LDR r0, =%[exc_ret] \n"
1408 STK_ASM_ENABLE_INTERRUPTS
" \n"
1410 STK_ASM_EXIT_FROM_HANDLER
" \n"
1413 : [st_active]
"m" (
GetContext().m_stack_active),
1415 [exc_ret]
"i" (STK_CORTEX_M_EXC_RETURN_THREAD_PSP)
1419void Context::Start()
1424 SaveJmp(m_exit_buf);
1428 m_handler->OnStop();
1432 HW_StartScheduler();
1435void Context::OnStart()
1441 HW_EnableFullFpuAccess();
1447 m_handler->OnStart(m_stack_active);
1449#if STK_TICKLESS_IDLE
1455 HW_SysTickStart(m_tick_resolution);
1460 NVIC_SetPriority(PendSV_IRQn, STK_CORTEX_M_ISR_PRIORITY_LOWEST);
1461 NVIC_SetPriority(SysTick_IRQn, STK_CORTEX_M_ISR_PRIORITY_LOWEST);
1463#ifdef CONTROL_nPRIV_Msk
1464 NVIC_SetPriority(SVCall_IRQn, STK_CORTEX_M_ISR_PRIORITY_HIGHEST);
1476 "Word must be uintptr_t width for safe pointer round-trip via frame->PC");
1481 "NVIC priority bit width exceeds safe shift range");
1484 volatile ExceptionFrame *
const frame =
reinterpret_cast<volatile ExceptionFrame *
>(svc_args);
1493 const ESvcCommandId command =
static_cast<ESvcCommandId
>(*insn_ptr);
1497 case SVC_START_SCHEDULING: {
1504 HW_DisableInterrupts();
1516#ifdef CONTROL_nPRIV_Msk
1517 case SVC_ENTER_CRITICAL: {
1518 const Word saved_basepri = __get_BASEPRI();
1519 __set_BASEPRI(
static_cast<uint32_t
>(1U) << __NVIC_PRIO_BITS);
1522 frame->R0 = saved_basepri;
1525 case SVC_EXIT_CRITICAL: {
1527 __set_BASEPRI(frame->R0);
1543 ".syntax unified \n"
1544 ".global SVC_Handler_Main \n"
1547#ifdef STK_CORTEX_M_TRUSTZONE
1554 #if (__CORTEX_M >= 33U)
1564 "MRSEQ r0, MSP_NS \n"
1571 "MRSEQ r0, PSP_NS \n"
1580 "LSLS r1, r1, #29 \n"
1581 "BMI .use_psp_v8m_b \n"
1584 "LSLS r1, r1, #25 \n"
1593 ".use_psp_v8m_b: \n"
1595 "LSLS r1, r1, #25 \n"
1605#elif (__CORTEX_M >= 3U)
1614 "LSLS r0, r0, #29 \n"
1615 "BMI .use_psp_m0 \n"
1617 "B .call_main_m0 \n"
1626 "LDR r1, =SVC_Handler_Main \n"
1633static void OnTaskRun(
ITask *task)
1638static void OnTaskExit()
1641 HW_CriticalSectionStart(cs);
1645 HW_CriticalSectionEnd(cs);
1654static void OnSchedulerSleep()
1658 #if STK_SEGGER_SYSVIEW
1659 SEGGER_SYSVIEW_OnIdle();
1662 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
1668static void OnSchedulerSleepOverride()
1674static void OnSchedulerExit()
1683#if STK_SEGGER_SYSVIEW
1684static void SendSysDesc()
1686 SEGGER_SYSVIEW_SendSysDesc(
"SuperTinyKernel (STK)");
1693 GetContext().Initialize(event_handler, service, exit_trap, resolution_us);
1710 "ExceptionFrame layout must match the ARMv7-M hardware exception frame exactly");
1712 "TaskFrame size must equal ExceptionFrame plus optional EXC_RETURN word plus optional TrustZone words");
1717 Word *stack_top = Context::InitStackMemory(stack_memory);
1720 stack->
SP =
hw::PtrToWord(stack_top - STK_CORTEX_M_TOTAL_REGISTER_COUNT);
1726 TaskFrame *
const task_frame =
reinterpret_cast<TaskFrame *
>(stack_top) - 1;
1738 task_frame->exc.PC =
hw::PtrToWord(
GetContext().m_overrider !=
nullptr ? &OnSchedulerSleepOverride : &OnSchedulerSleep);
1740 task_frame->exc.R0 = 0U;
1746 task_frame->exc.R0 = 0U;
1755 task_frame->exc.PC &= ~0x1UL;
1759 task_frame->exc.PSR =
static_cast<Word>(1U) << 24;
1761#if STK_CORTEX_M_MANAGE_LR
1775#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1777 task_frame->EXC_RETURN = STK_CORTEX_M_EXC_RETURN_S_THREAD_PSP;
1779 task_frame->EXC_RETURN = STK_CORTEX_M_EXC_RETURN_NS_THREAD_PSP;
1781 task_frame->EXC_RETURN = STK_CORTEX_M_EXC_RETURN_THREAD_PSP;
1785#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1789 task_frame->tz.PSPLIM = 0U;
1790 task_frame->tz.PSPLIM_NS = 0U;
1815#if defined(STK_CORTEX_M_TRUSTZONE) && (__CORTEX_M >= 33U)
1822__stk_nsc_entry
void NSC_SwitchToNext()
1826 if (HW_IsHandlerMode())
1829 GetContext().m_handler->OnTaskSwitch(HW_GetCallerSP());
1838__stk_nsc_entry
void NSC_Sleep(
Timeout ticks)
1840 if (HW_IsHandlerMode())
1843 GetContext().m_handler->OnTaskSleep(HW_GetCallerSP(), ticks);
1861 if (HW_IsHandlerMode())
1867 if (sync_obj !=
nullptr &&
1868 cmse_check_pointed_object(sync_obj, CMSE_NONSECURE) ==
nullptr)
1872 if (mutex !=
nullptr &&
1873 cmse_check_pointed_object(mutex, CMSE_NONSECURE) ==
nullptr)
1878 return GetContext().m_handler->OnTaskWait(HW_GetCallerSP(), sync_obj, mutex, timeout);
1889__stk_nsc_entry
TId NSC_GetTid()
1891 if (HW_IsHandlerMode())
1894 return GetContext().m_handler->OnGetTid(HW_GetCallerSP());
1904__stk_nsc_entry int32_t NSC_GetTickResolution()
1906 return static_cast<int32_t
>(
GetContext().m_tick_resolution);
1912void Context::OnStop()
1914#if STK_SEGGER_SYSVIEW
1915 SEGGER_SYSVIEW_Stop();
1922 SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk;
1937 HW_DisableInterrupts();
1948 GetContext().m_handler->OnTaskSwitch(HW_GetCallerSP());
1953 GetContext().m_handler->OnTaskSleep(HW_GetCallerSP(), ticks);
1958 return GetContext().m_handler->OnTaskWait(HW_GetCallerSP(), sync_obj, mutex, timeout);
1963 return GetContext().m_handler->OnGetTid(HW_GetCallerSP());
1982 return HW_GetCallerSP();
1993 if (HW_IsHandlerMode() || HW_IsPrivilegedThreadMode())
2002 if (HW_IsHandlerMode() || HW_IsPrivilegedThreadMode())
2010 HW_SpinLockLock(m_lock);
2015 HW_SpinLockUnlock(m_lock);
2020 return HW_SpinLockTryLock(m_lock);
2025 return HW_IsHandlerMode();
2030 return HiResClockImpl::GetInstance()->GetCycles();
2035 Cycles freq = HiResClockImpl::GetInstance()->GetFrequency();
volatile uint32_t SystemCoreClock
System clock frequency in Hz.
Contains common inventory for platform implementation.
#define GetContext()
Get platform's context.
Top-level STK include. Provides the Kernel class template and all built-in task-switching strategies.
Hardware Abstraction Layer (HAL) declarations for the stk::hw namespace.
void STK_PANIC_HANDLER_DEFAULT(stk::EKernelPanicId id)
Default panic handler: disable interrupts, record the id, and spin in a tight loop — a defined,...
#define STK_KERNEL_PANIC(id)
Called when the kernel detects an unrecoverable internal fault.
#define __stk_attr_used
Marks a symbol as used, preventing the linker from discarding it even if no references are visible (d...
#define __stk_forceinline
Forces compiler to always inline the decorated function, regardless of optimisation level.
#define STK_TICKLESS_IDLE
Enables tickless (dynamic-tick) low-power operation during idle periods.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
#define __stk_attr_noinline
Prevents compiler from inlining the decorated function (function prefix).
#define STK_CRITICAL_SECTION_NESTINGS_MAX
Maximum allowable recursion depth for critical section entry (default: 16).
#define STK_STATIC_ASSERT_DESC_N(NAME, X, DESC)
Compile-time assertion with a user-defined name suffix and a custom error description.
#define STK_ARCH_CPU_COUNT
Number of physical CPU cores available to the scheduler (default: 1).
#define __stk_attr_naked
Suppresses compiler-generated function prologue and epilogue (function prefix).
#define STK_STACK_MEMORY_FILLER
Sentinel value written to the entire stack region at initialization (stack watermark pattern).
#define __stk_attr_noreturn
Declares that function never returns to its caller (function prefix).
#define __stk_relax_cpu
Emits a CPU pipeline-relaxation hint for use inside hot busy-wait (spin) loops (in-code statement).
Namespace of STK package.
uintptr_t Word
Native processor word type.
const TId TID_ISR
Reserved task/thread id representing an ISR context.
static __stk_forceinline Cycles ConvertTimeUsToClockCycles(Cycles clock_freq, Ticks time_us)
Convert time (microseconds) to core clock cycles.
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
int32_t Timeout
Timeout time (ticks).
@ STACK_SLEEP_TRAP
Stack of the Sleep trap.
@ STACK_USER_TASK
Stack of the user task.
@ STACK_EXIT_TRAP
Stack of the Exit trap.
uint64_t Cycles
Cycles value.
@ ACCESS_PRIVILEGED
Privileged access mode (access to hardware is fully unrestricted).
EKernelPanicId
Identifies the source of a kernel panic.
@ KERNEL_PANIC_UNKNOWN_SVC
Unknown service command received by SVC handler.
@ KERNEL_PANIC_HRT_HARD_FAULT
Kernel running in KERNEL_HRT mode reported deadline failure of the task.
@ KERNEL_PANIC_NONE
Panic is absent (no fault).
@ KERNEL_PANIC_SPINLOCK_DEADLOCK
Spin-lock timeout expired: lock owner never released.
__stk_forceinline T * WordToPtr(Word value) noexcept
Cast a CPU register-width integer back to a pointer.
__stk_forceinline Word PtrToWord(T *ptr) noexcept
Cast a pointer to a CPU register-width integer.
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
uint32_t GetTickResolution() const
Get resolution of the system tick timer in microseconds. Resolution means a number of microseconds be...
void ProcessTick()
Process one tick.
void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap)
Initialize scheduler's context.
TId GetTid() const
Get thread Id.
void Sleep(Timeout ticks)
Put calling process into a sleep state.
Word GetCallerSP() const
Get caller's Stack Pointer (SP).
void Start()
Start scheduling.
void SwitchToNext()
Switch to a next task.
void Stop()
Stop scheduling.
bool InitStack(EStackType stack_type, Stack *stack, IStackMemory *stack_memory, ITask *user_task)
Initialize stack memory of the user task.
void SetEventOverrider(IEventOverrider *overrider)
Set platform event overrider.
IWaitObject * Wait(ISyncObject *sync_obj, IMutex *mutex, Timeout timeout)
void ProcessHardFault()
Cause a hard fault of the system.
Base platform context for all platform implementations.
static void Exit()
Exit a critical section.
static void Enter()
Enter a critical section.
bool TryLock()
Attempt to acquire SpinLock in a single non-blocking attempt.
void Lock()
Acquire SpinLock, blocking until it is available.
void Unlock()
Release SpinLock, allowing another thread or core to acquire it.
static uint32_t GetFrequency()
Get clock frequency.
static Cycles GetCycles()
Get number of clock cycles elapsed.
Word SP
Stack Pointer (SP) register (note: must be the first entry in this struct).
EAccessMode mode
access mode
Interface for a stack memory region.
virtual size_t GetStackSize() const =0
Get number of elements of the stack memory array.
Interface for mutex synchronization primitive.
Interface for a user task.
virtual void Run()=0
Entry point of the user task.
Interface for the kernel services exposed to the user processes during run-time when Kernel started s...
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.
RISC-V specific event handler.