12#include "stk_config.h"
14#ifdef _STK_ARCH_RISC_V
64#ifndef STK_RISCV_CLINT_BASE_ADDR
65 #define STK_RISCV_CLINT_BASE_ADDR (0x2000000U)
67#ifndef STK_RISCV_CLINT_MTIMECMP_ADDR
68 #define STK_RISCV_CLINT_MTIMECMP_ADDR (STK_RISCV_CLINT_BASE_ADDR + 0x4000U)
70#ifndef STK_RISCV_CLINT_MTIME_ADDR
71 #define STK_RISCV_CLINT_MTIME_ADDR (STK_RISCV_CLINT_BASE_ADDR + 0xBFF8U)
78#define STK_RISCV_ISR_STACK_SIZE 256U
83#ifndef STK_TIMER_CLOCK_FREQUENCY
84 #define STK_TIMER_CLOCK_FREQUENCY 1000000U
91#ifndef STK_RISCV_ISR_SECTION
92 #define STK_RISCV_ISR_SECTION
99#define STK_RISCV_ISR extern "C" STK_RISCV_ISR_SECTION __attribute__ ((interrupt("machine")))
102#define STK_ASM_EXIT_FROM_HANDLER "mret"
109#ifndef STK_RISCV_CLINT_MTIMECMP_PER_HART
110 #define STK_RISCV_CLINT_MTIMECMP_PER_HART (1)
117#ifndef STK_ARCH_GET_CPU_ID
118 #define STK_ARCH_GET_CPU_ID() read_csr(mhartid)
122#if (__riscv_flen == 0)
123 #define STK_RISCV_FPU 0
125 #define STK_RISCV_FPU __riscv_flen
129#define XSTR(s) STR(s)
132#if (__riscv_xlen == 32)
133 #define REGBYTES XSTR(4)
134 #define LREG XSTR(lw)
135 #define SREG XSTR(sw)
136#elif (__riscv_xlen == 64)
137 #define REGBYTES XSTR(8)
138 #define LREG XSTR(ld)
139 #define SREG XSTR(sd)
141 #error Unsupported RISC-V platform!
144#if (STK_RISCV_FPU == 32)
145 #define FREGBYTES XSTR(4)
146 #define FLREG XSTR(flw)
147 #define FSREG XSTR(fsw)
148#elif (STK_RISCV_FPU == 64)
149 #define FREGBYTES XSTR(8)
150 #define FLREG XSTR(fld)
151 #define FSREG XSTR(fsd)
152#elif (STK_RISCV_FPU != 0)
153#error Unsupported FP register count!
157#if (__riscv_32e == 1)
158 #define STK_RISCV_REGISTER_COUNT (15 + (STK_RISCV_FPU != 0 ? 31 : 0))
160 #define STK_RISCV_REGISTER_COUNT (31 + (STK_RISCV_FPU != 0 ? 31 : 0))
163#define STK_SERVICE_SLOTS 2
165#if (__riscv_32e == 1)
166 #define FOFFSET XSTR(68)
167 #if (STK_RISCV_FPU == 0)
168 #define REGSIZE XSTR(((15 + STK_SERVICE_SLOTS) * 4))
170 #if (STK_RISCV_FPU == 32)
171 #define REGSIZE XSTR((((15 + STK_SERVICE_SLOTS) * 4) + (31 * 4)))
172 #elif (STK_RISCV_FPU == 64)
173 #define REGSIZE XSTR((((15 + STK_SERVICE_SLOTS) * 4) + (31 * 8)))
176#elif (__riscv_xlen == 32)
177 #define FOFFSET XSTR(132)
178 #if (STK_RISCV_FPU == 0)
179 #define REGSIZE XSTR(((31 + STK_SERVICE_SLOTS) * 4))
181 #if (STK_RISCV_FPU == 32)
182 #define REGSIZE XSTR((((31 + STK_SERVICE_SLOTS) * 4) + (31 * 4)))
183 #elif (STK_RISCV_FPU == 64)
184 #define REGSIZE XSTR((((31 + STK_SERVICE_SLOTS) * 4) + (31 * 8)))
187#elif (__riscv_xlen == 64)
188 #define FOFFSET XSTR(264)
189 #if (STK_RISCV_FPU == 0)
190 #define REGSIZE XSTR(((31 + STK_SERVICE_SLOTS) * 8))
192 #if (STK_RISCV_FPU == 32)
193 #define REGSIZE XSTR((((31 + STK_SERVICE_SLOTS) * 8) + (31 * 4)))
194 #elif (STK_RISCV_FPU == 64)
195 #define REGSIZE XSTR((((31 + STK_SERVICE_SLOTS) * 8) + (31 * 8)))
200#if (__riscv_xlen == 32)
201 #define REGBYTES_LOG2 "2"
202#elif (__riscv_xlen == 64)
203 #define REGBYTES_LOG2 "3"
212#ifndef STK_SYSTICK_HANDLER
213 #define STK_SYSTICK_HANDLER riscv_mtvec_mti
222#ifndef STK_SVC_HANDLER
223 #define STK_SVC_HANDLER riscv_mtvec_exception
233#ifndef STK_MSI_HANDLER
234 #define STK_MSI_HANDLER riscv_mtvec_msi
264#if (STK_RISCV_FPU != 0)
281#if (__riscv_32e != 1)
299#if (STK_RISCV_FPU != 0)
312 __asm
volatile(
"fence rw, rw" :::
"memory");
319#ifdef __riscv_zifencei
320 __asm
volatile(
"fence.i" :::
"memory");
322 __sync_synchronize();
330 __asm
volatile(
"wfi");
338 __asm
volatile(
"ecall");
352 __asm
volatile(
"csrrci zero, mstatus, %0"
362 __asm
volatile(
"csrrsi zero, mstatus, %0"
374 __asm
volatile(
"csrrci %0, mstatus, %1"
387 __asm
volatile(
"csrrs zero, mstatus, %0"
397 clear_csr(mie, MIP_MTIP);
414 return STK_TIMER_CLOCK_FREQUENCY;
424#if ( __riscv_xlen > 32)
425 return *((
volatile uint64_t *)STK_RISCV_CLINT_MTIME_ADDR);
427 volatile uint32_t *mtime_hi = ((uint32_t *)STK_RISCV_CLINT_MTIME_ADDR) + 1;
428 volatile uint32_t *mtime_lo = ((uint32_t *)STK_RISCV_CLINT_MTIME_ADDR);
436 while (hi != (*mtime_hi));
438 return ((uint64_t)hi << 32) | lo;
447#if STK_RISCV_CLINT_MTIMECMP_PER_HART
448 const uint8_t hart = HW_GetHartId();
450 const uint8_t hart = 0;
453#if (__riscv_xlen == 64)
454 ((
volatile uint64_t *)STK_RISCV_CLINT_MTIMECMP_ADDR)[hart] = next;
456 volatile uint32_t *mtime_lo = (uint32_t *)((uint64_t *)STK_RISCV_CLINT_MTIMECMP_ADDR + hart);
457 volatile uint32_t *mtime_hi = mtime_lo + 1;
460 STK_ASSERT(((uintptr_t)mtime_lo & (4 - 1)) == 0);
461 STK_ASSERT(((uintptr_t)mtime_hi & (4 - 1)) == 0);
467 (*mtime_lo) = (uint32_t)(time_next & 0xFFFFFFFF);
468 (*mtime_hi) = (uint32_t)(time_next >> 32);
479 return HW_GetMtime() - since;
486 __asm
volatile(
"csrci mcountinhibit, 0x1");
494 uint32_t high, low, check;
497 __asm
volatile(
"csrr %0, mcycleh" :
"=r"(high));
498 __asm
volatile(
"csrr %0, mcycle" :
"=r"(low));
499 __asm
volatile(
"csrr %0, mcycleh" :
"=r"(check));
501 while (high != check);
503 return (
static_cast<Cycles>(high) << 32) | low;
511 __asm
volatile(
"mv %0, sp"
523 ses = HW_EnterCriticalSection();
537 HW_ExitCriticalSection(ses);
559 return !__atomic_test_and_set(&lock, __ATOMIC_ACQUIRE);
580 uint32_t timeout = 0xFFFFFF;
581 while (!HW_SpinLockTryLock(lock))
617 __asm
volatile(
"fence rw, w" :::
"memory");
619 __atomic_clear(&lock, __ATOMIC_RELEASE);
626#ifdef _STK_RISCV_USE_PENDSV
628 volatile uint32_t *msip = (
volatile uint32_t *)(STK_RISCV_CLINT_BASE_ADDR);
637#ifndef _STK_SYSTEM_CORE_CLOCK_EXTERNAL
643static volatile bool s_StkRiscvCsuLock =
false;
656#ifdef _STK_RISCV_USE_PENDSV
724#if (STK_RISCV_FPU != 0)
743__attribute__((naked))
744int32_t SaveJmp(JmpFrame &)
748 SREG
" ra, 0*" REGBYTES
"(a0) \n"
749 SREG
" sp, 1*" REGBYTES
"(a0) \n"
750 SREG
" s0, 2*" REGBYTES
"(a0) \n"
751 SREG
" s1, 3*" REGBYTES
"(a0) \n"
752 SREG
" s2, 4*" REGBYTES
"(a0) \n"
753 SREG
" s3, 5*" REGBYTES
"(a0) \n"
754 SREG
" s4, 6*" REGBYTES
"(a0) \n"
755 SREG
" s5, 7*" REGBYTES
"(a0) \n"
756 SREG
" s6, 8*" REGBYTES
"(a0) \n"
757 SREG
" s7, 9*" REGBYTES
"(a0) \n"
758 SREG
" s8, 10*" REGBYTES
"(a0) \n"
759 SREG
" s9, 11*" REGBYTES
"(a0) \n"
760 SREG
" s10, 12*" REGBYTES
"(a0) \n"
761 SREG
" s11, 13*" REGBYTES
"(a0) \n"
762#if (STK_RISCV_FPU != 0)
764 SREG
" t0, 14*" REGBYTES
"(a0) \n"
788__attribute__((naked, noreturn))
789void RestoreJmp(JmpFrame &, int32_t )
793 LREG
" ra, 0*" REGBYTES
"(a0) \n"
794 LREG
" sp, 1*" REGBYTES
"(a0) \n"
795 LREG
" s0, 2*" REGBYTES
"(a0) \n"
796 LREG
" s1, 3*" REGBYTES
"(a0) \n"
797 LREG
" s2, 4*" REGBYTES
"(a0) \n"
798 LREG
" s3, 5*" REGBYTES
"(a0) \n"
799 LREG
" s4, 6*" REGBYTES
"(a0) \n"
800 LREG
" s5, 7*" REGBYTES
"(a0) \n"
801 LREG
" s6, 8*" REGBYTES
"(a0) \n"
802 LREG
" s7, 9*" REGBYTES
"(a0) \n"
803 LREG
" s8, 10*" REGBYTES
"(a0) \n"
804 LREG
" s9, 11*" REGBYTES
"(a0) \n"
805 LREG
" s10, 12*" REGBYTES
"(a0) \n"
806 LREG
" s11, 13*" REGBYTES
"(a0) \n"
807#if (STK_RISCV_FPU != 0)
808 LREG
" t0, 14*" REGBYTES
"(a0) \n"
819#if STK_SUBMICORSECOND_PRECISION_TIMER
823 static HiResClockCYCLE *GetInstance()
827 static HiResClockCYCLE clock;
833 return HW_GetCycleCounter();
836 uint32_t GetFrequency()
838 return HW_CoreClockFrequency();
841typedef HiResClockCYCLE HiResClockImpl;
846 static HiResClockMTIME *GetInstance()
850 static HiResClockMTIME clock;
856 return HW_GetMtime();
859 uint32_t GetFrequency()
861 return HW_MtimeClockFrequency();
864typedef HiResClockMTIME HiResClockImpl;
870 Context() : PlatformContext(), m_stack_main(), m_stack_isr(), m_stack_isr_mem(),
871 m_exit_buf(), m_overrider(nullptr), m_specific(nullptr), m_tick_period(0), m_last_mtime(0ULL),
875 m_csu(0), m_csu_nesting(0),
876 m_starting(false), m_started(false), m_exiting(false)
886 void Initialize(IPlatform::IEventHandler *handler, IKernelService *service, Stack *exit_trap, int32_t resolution_us)
888 PlatformContext::Initialize(handler, service, exit_trap, resolution_us);
892 StackMemoryWrapper<STK_RISCV_ISR_STACK_SIZE> stack_isr_mem(&m_stack_isr_mem);
893 m_stack_isr.SP = hw::PtrToWord(InitStackMemory(&stack_isr_mem));
907 m_tick_period = ConvertTimeUsToClockCycles(STK_TIMER_CLOCK_FREQUENCY, resolution_us);
914 #if STK_SUBMICORSECOND_PRECISION_TIMER
915 HW_EnableCycleCounter();
923 HW_CriticalSectionStart(cs);
925 #if STK_TICKLESS_IDLE
929 if (m_handler->OnTick(m_stack_idle, m_stack_active
941 const uint8_t hart = HW_GetHartId();
942 s_StkRiscvStackActive[hart] = m_stack_active;
943 #ifdef _STK_RISCV_USE_PENDSV
944 s_StkRiscvStackIdle[hart] = m_stack_idle;
947 HW_ScheduleContextSwitch(hart);
950 #if STK_TICKLESS_IDLE
951 m_sleep_ticks = ticks;
954 HW_CriticalSectionEnd(cs);
961 HW_CriticalSectionStart(current_ses);
963 if (m_csu_nesting == 0)
966 HW_SpinLockLock(s_StkRiscvCsuLock);
985 if (m_csu_nesting == 0)
988 Word ses_to_restore = m_csu;
991 HW_SpinLockUnlock(s_StkRiscvCsuLock);
994 HW_CriticalSectionEnd(ses_to_restore);
998 uint64_t GetSleepTicksPrev()
1000 #if STK_TICKLESS_IDLE
1001 uint64_t ticks = (
static_cast<uint64_t
>(m_sleep_ticks) *
static_cast<uint64_t
>(m_tick_period));
1003 uint64_t ticks = (1U *
static_cast<uint64_t
>(m_tick_period));
1013 const uint64_t mtime_now = HW_GetMtime();
1014 const uint64_t error = (mtime_now - m_last_mtime) - GetSleepTicksPrev();
1015 __stk_compiler_barrier();
1026 #if STK_TICKLESS_IDLE
1028 STK_ASSERT((
static_cast<uint64_t
>(m_sleep_ticks) *
static_cast<uint64_t
>(m_tick_period)) <= (UINT64_MAX - mtime_now));
1029 const uint64_t next_time = (
static_cast<uint64_t
>(m_sleep_ticks) *
static_cast<uint64_t
>(m_tick_period));
1031 const uint64_t next_time = (1U *
static_cast<uint64_t
>(m_tick_period));
1033 HW_SetMtimecmp(mtime_now + next_time - error);
1034 m_last_mtime = mtime_now;
1041 typedef IPlatform::IEventOverrider eovrd_t;
1042 typedef PlatformRiscV::ISpecificEventHandler sehndl_t;
1043 typedef StackMemoryWrapper<STK_RISCV_ISR_STACK_SIZE>::MemoryType isrmem_t;
1047 isrmem_t m_stack_isr_mem;
1048 JmpFrame m_exit_buf;
1049 eovrd_t *m_overrider;
1050 sehndl_t *m_specific;
1051 uint32_t m_tick_period;
1052 uint64_t m_last_mtime;
1053#if STK_TICKLESS_IDLE
1057 uint8_t m_csu_nesting;
1060 volatile bool m_exiting;
1066#ifdef _STK_RISCV_USE_PENDSV
1068 HW_CriticalSectionStart(cs);
1072 HW_CriticalSectionEnd(cs);
1089 HW_DisableInterrupts();
1099#define STK_ASM_SAVE_CONTEXT_BASE\
1100 SREG " x1, 2*" REGBYTES "(sp) \n"\
1103 SREG " x4, 5*" REGBYTES "(sp) \n"\
1104 SREG " x5, 6*" REGBYTES "(sp) \n"\
1105 SREG " x6, 7*" REGBYTES "(sp) \n"\
1106 SREG " x7, 8*" REGBYTES "(sp) \n"\
1107 SREG " x8, 9*" REGBYTES "(sp) \n"\
1108 SREG " x9, 10*" REGBYTES "(sp) \n"\
1109 SREG " x10, 11*" REGBYTES "(sp) \n"\
1110 SREG " x11, 12*" REGBYTES "(sp) \n"\
1111 SREG " x12, 13*" REGBYTES "(sp) \n"\
1112 SREG " x13, 14*" REGBYTES "(sp) \n"\
1113 SREG " x14, 15*" REGBYTES "(sp) \n"\
1114 SREG " x15, 16*" REGBYTES "(sp) \n"
1116#if (__riscv_32e != 1)
1117#define STK_ASM_SAVE_CONTEXT_RV32I_EXT\
1118 SREG " x16, 17*" REGBYTES "(sp) \n"\
1119 SREG " x17, 18*" REGBYTES "(sp) \n"\
1120 SREG " x18, 19*" REGBYTES "(sp) \n"\
1121 SREG " x19, 20*" REGBYTES "(sp) \n"\
1122 SREG " x20, 21*" REGBYTES "(sp) \n"\
1123 SREG " x21, 22*" REGBYTES "(sp) \n"\
1124 SREG " x22, 23*" REGBYTES "(sp) \n"\
1125 SREG " x23, 24*" REGBYTES "(sp) \n"\
1126 SREG " x24, 25*" REGBYTES "(sp) \n"\
1127 SREG " x25, 26*" REGBYTES "(sp) \n"\
1128 SREG " x26, 27*" REGBYTES "(sp) \n"\
1129 SREG " x27, 28*" REGBYTES "(sp) \n"\
1130 SREG " x28, 29*" REGBYTES "(sp) \n"\
1131 SREG " x29, 30*" REGBYTES "(sp) \n"\
1132 SREG " x30, 31*" REGBYTES "(sp) \n"\
1133 SREG " x31, 32*" REGBYTES "(sp) \n"
1135#define STK_ASM_SAVE_CONTEXT_RV32I_EXT
1138#if (STK_RISCV_FPU != 0)
1139#define STK_ASM_SAVE_CONTEXT_FP\
1140 FSREG " f0, " FOFFSET "+0*" FREGBYTES "(sp) \n"\
1141 FSREG " f1, " FOFFSET "+1*" FREGBYTES "(sp) \n"\
1142 FSREG " f2, " FOFFSET "+2*" FREGBYTES "(sp) \n"\
1143 FSREG " f3, " FOFFSET "+3*" FREGBYTES "(sp) \n"\
1144 FSREG " f4, " FOFFSET "+4*" FREGBYTES "(sp) \n"\
1145 FSREG " f5, " FOFFSET "+5*" FREGBYTES "(sp) \n"\
1146 FSREG " f6, " FOFFSET "+6*" FREGBYTES "(sp) \n"\
1147 FSREG " f7, " FOFFSET "+7*" FREGBYTES "(sp) \n"\
1148 FSREG " f8, " FOFFSET "+8*" FREGBYTES "(sp) \n"\
1149 FSREG " f9, " FOFFSET "+9*" FREGBYTES "(sp) \n"\
1150 FSREG " f10, " FOFFSET "+10*" FREGBYTES "(sp) \n"\
1151 FSREG " f11, " FOFFSET "+11*" FREGBYTES "(sp) \n"\
1152 FSREG " f12, " FOFFSET "+12*" FREGBYTES "(sp) \n"\
1153 FSREG " f13, " FOFFSET "+13*" FREGBYTES "(sp) \n"\
1154 FSREG " f14, " FOFFSET "+14*" FREGBYTES "(sp) \n"\
1155 FSREG " f15, " FOFFSET "+15*" FREGBYTES "(sp) \n"\
1156 FSREG " f16, " FOFFSET "+16*" FREGBYTES "(sp) \n"\
1157 FSREG " f17, " FOFFSET "+17*" FREGBYTES "(sp) \n"\
1158 FSREG " f18, " FOFFSET "+18*" FREGBYTES "(sp) \n"\
1159 FSREG " f19, " FOFFSET "+19*" FREGBYTES "(sp) \n"\
1160 FSREG " f20, " FOFFSET "+20*" FREGBYTES "(sp) \n"\
1161 FSREG " f21, " FOFFSET "+21*" FREGBYTES "(sp) \n"\
1162 FSREG " f22, " FOFFSET "+22*" FREGBYTES "(sp) \n"\
1163 FSREG " f23, " FOFFSET "+23*" FREGBYTES "(sp) \n"\
1164 FSREG " f24, " FOFFSET "+24*" FREGBYTES "(sp) \n"\
1165 FSREG " f25, " FOFFSET "+25*" FREGBYTES "(sp) \n"\
1166 FSREG " f26, " FOFFSET "+26*" FREGBYTES "(sp) \n"\
1167 FSREG " f27, " FOFFSET "+27*" FREGBYTES "(sp) \n"\
1168 FSREG " f28, " FOFFSET "+28*" FREGBYTES "(sp) \n"\
1169 FSREG " f29, " FOFFSET "+29*" FREGBYTES "(sp) \n"\
1170 FSREG " f30, " FOFFSET "+30*" FREGBYTES "(sp) \n"\
1171 FSREG " f31, " FOFFSET "+31*" FREGBYTES "(sp) \n"
1173#define STK_ASM_SAVE_CONTEXT_FP
1176#define STK_ASM_SAVE_CONTEXT_PC_STATUS\
1178 "csrr t1, mstatus \n"\
1179 SREG " t0, 0*" REGBYTES "(sp) \n"\
1180 SREG " t1, 1*" REGBYTES "(sp) \n"
1182#if (STK_RISCV_FPU != 0)
1183#define STK_ASM_SAVE_CONTEXT_FRCSR\
1185 SREG " t0, 4*" REGBYTES "(sp) \n"
1187#define STK_ASM_SAVE_CONTEXT_FRCSR
1190#define STK_ASM_SAVE_CONTEXT\
1191 "addi sp, sp, -" REGSIZE " \n" \
1192 STK_ASM_SAVE_CONTEXT_BASE\
1193 STK_ASM_SAVE_CONTEXT_RV32I_EXT\
1194 STK_ASM_SAVE_CONTEXT_FP\
1195 STK_ASM_SAVE_CONTEXT_PC_STATUS\
1196 STK_ASM_SAVE_CONTEXT_FRCSR
1198#define STK_ASM_LOAD_CONTEXT_BASE\
1199 LREG " x1, 2*" REGBYTES "(sp) \n"\
1202 LREG " x4, 5*" REGBYTES "(sp) \n"\
1203 LREG " x5, 6*" REGBYTES "(sp) \n"\
1204 LREG " x6, 7*" REGBYTES "(sp) \n"\
1205 LREG " x7, 8*" REGBYTES "(sp) \n"\
1206 LREG " x8, 9*" REGBYTES "(sp) \n"\
1207 LREG " x9, 10*" REGBYTES "(sp) \n"\
1208 LREG " x10, 11*" REGBYTES "(sp) \n"\
1209 LREG " x11, 12*" REGBYTES "(sp) \n"\
1210 LREG " x12, 13*" REGBYTES "(sp) \n"\
1211 LREG " x13, 14*" REGBYTES "(sp) \n"\
1212 LREG " x14, 15*" REGBYTES "(sp) \n"\
1213 LREG " x15, 16*" REGBYTES "(sp) \n"
1215#if (__riscv_32e != 1)
1216#define STK_ASM_LOAD_CONTEXT_RV32I_EXT\
1217 LREG " x16, 17*" REGBYTES "(sp) \n"\
1218 LREG " x17, 18*" REGBYTES "(sp) \n"\
1219 LREG " x18, 19*" REGBYTES "(sp) \n"\
1220 LREG " x19, 20*" REGBYTES "(sp) \n"\
1221 LREG " x20, 21*" REGBYTES "(sp) \n"\
1222 LREG " x21, 22*" REGBYTES "(sp) \n"\
1223 LREG " x22, 23*" REGBYTES "(sp) \n"\
1224 LREG " x23, 24*" REGBYTES "(sp) \n"\
1225 LREG " x24, 25*" REGBYTES "(sp) \n"\
1226 LREG " x25, 26*" REGBYTES "(sp) \n"\
1227 LREG " x26, 27*" REGBYTES "(sp) \n"\
1228 LREG " x27, 28*" REGBYTES "(sp) \n"\
1229 LREG " x28, 29*" REGBYTES "(sp) \n"\
1230 LREG " x29, 30*" REGBYTES "(sp) \n"\
1231 LREG " x30, 31*" REGBYTES "(sp) \n"\
1232 LREG " x31, 32*" REGBYTES "(sp) \n"
1234#define STK_ASM_LOAD_CONTEXT_RV32I_EXT
1237#if (STK_RISCV_FPU != 0)
1238#define STK_ASM_LOAD_CONTEXT_FP\
1239 FLREG " f0, " FOFFSET "+0*" FREGBYTES "(sp) \n"\
1240 FLREG " f1, " FOFFSET "+1*" FREGBYTES "(sp) \n"\
1241 FLREG " f2, " FOFFSET "+2*" FREGBYTES "(sp) \n"\
1242 FLREG " f3, " FOFFSET "+3*" FREGBYTES "(sp) \n"\
1243 FLREG " f4, " FOFFSET "+4*" FREGBYTES "(sp) \n"\
1244 FLREG " f5, " FOFFSET "+5*" FREGBYTES "(sp) \n"\
1245 FLREG " f6, " FOFFSET "+6*" FREGBYTES "(sp) \n"\
1246 FLREG " f7, " FOFFSET "+7*" FREGBYTES "(sp) \n"\
1247 FLREG " f8, " FOFFSET "+8*" FREGBYTES "(sp) \n"\
1248 FLREG " f9, " FOFFSET "+9*" FREGBYTES "(sp) \n"\
1249 FLREG " f10, " FOFFSET "+10*" FREGBYTES "(sp) \n"\
1250 FLREG " f11, " FOFFSET "+11*" FREGBYTES "(sp) \n"\
1251 FLREG " f12, " FOFFSET "+12*" FREGBYTES "(sp) \n"\
1252 FLREG " f13, " FOFFSET "+13*" FREGBYTES "(sp) \n"\
1253 FLREG " f14, " FOFFSET "+14*" FREGBYTES "(sp) \n"\
1254 FLREG " f15, " FOFFSET "+15*" FREGBYTES "(sp) \n"\
1255 FLREG " f16, " FOFFSET "+16*" FREGBYTES "(sp) \n"\
1256 FLREG " f17, " FOFFSET "+17*" FREGBYTES "(sp) \n"\
1257 FLREG " f18, " FOFFSET "+18*" FREGBYTES "(sp) \n"\
1258 FLREG " f19, " FOFFSET "+19*" FREGBYTES "(sp) \n"\
1259 FLREG " f20, " FOFFSET "+20*" FREGBYTES "(sp) \n"\
1260 FLREG " f21, " FOFFSET "+21*" FREGBYTES "(sp) \n"\
1261 FLREG " f22, " FOFFSET "+22*" FREGBYTES "(sp) \n"\
1262 FLREG " f23, " FOFFSET "+23*" FREGBYTES "(sp) \n"\
1263 FLREG " f24, " FOFFSET "+24*" FREGBYTES "(sp) \n"\
1264 FLREG " f25, " FOFFSET "+25*" FREGBYTES "(sp) \n"\
1265 FLREG " f26, " FOFFSET "+26*" FREGBYTES "(sp) \n"\
1266 FLREG " f27, " FOFFSET "+27*" FREGBYTES "(sp) \n"\
1267 FLREG " f28, " FOFFSET "+28*" FREGBYTES "(sp) \n"\
1268 FLREG " f29, " FOFFSET "+29*" FREGBYTES "(sp) \n"\
1269 FLREG " f30, " FOFFSET "+30*" FREGBYTES "(sp) \n"\
1270 FLREG " f31, " FOFFSET "+31*" FREGBYTES "(sp) \n"
1272#define STK_ASM_LOAD_CONTEXT_FP
1275#define STK_ASM_LOAD_CONTEXT_PC_STATUS\
1276 LREG " t0, 0*" REGBYTES "(sp) \n"\
1277 LREG " t1, 1*" REGBYTES "(sp) \n"\
1279 "csrw mstatus, t1 \n"
1281#if (STK_RISCV_FPU != 0)
1282#define STK_ASM_LOAD_CONTEXT_FRCSR\
1283 LREG " t0, 4*" REGBYTES "(sp) \n" \
1286#define STK_ASM_LOAD_CONTEXT_FRCSR
1289#define STK_ASM_LOAD_CONTEXT\
1290 STK_ASM_LOAD_CONTEXT_PC_STATUS\
1291 STK_ASM_LOAD_CONTEXT_FRCSR\
1292 STK_ASM_LOAD_CONTEXT_BASE\
1293 STK_ASM_LOAD_CONTEXT_RV32I_EXT\
1294 STK_ASM_LOAD_CONTEXT_FP\
1295 "addi sp, sp, " REGSIZE " \n"
1301 LREG
" sp, 0(t0) \n"
1303 STK_ASM_LOAD_CONTEXT
1304 STK_ASM_EXIT_FROM_HANDLER
" \n"
1308 :
"t0",
"t1",
"a2",
"a3",
"a4",
"a5",
"gp",
"memory");
1313#if (STK_RISCV_FPU != 0)
1317 :
"r"(MSTATUS_FS | MSTATUS_XS)
1324#if (STK_RISCV_FPU != 0)
1353 Word current_sp = HW_GetCallerSP();
1358 const Word isr_stack_top = isr_stack_base + STK_RISCV_ISR_STACK_SIZE;
1360 return ((current_sp >= isr_stack_base) && (current_sp < isr_stack_top));
1365 HW_LoadContextAndExit();
1369extern "C" STK_RISCV_ISR_SECTION
__stk_attr_used void TrySwitchContext()
1374#ifdef _STK_RISCV_USE_PENDSV
1375extern "C" STK_RISCV_ISR_SECTION
__stk_attr_naked void STK_SYSTICK_HANDLER()
1379 STK_ASM_SAVE_CONTEXT
1382#if (STK_ARCH_CPU_COUNT > 1)
1383 "csrr t0, mhartid \n"
1384 "la t1, s_StkRiscvSpIsrInt \n"
1385 "slli t0, t0, " REGBYTES_LOG2
" \n"
1387 SREG
" sp, 0(t1) \n"
1389 "la t1, s_StkRiscvSpIsrInt \n"
1390 SREG
" sp, 0(t1) \n"
1394#if (STK_ARCH_CPU_COUNT > 1)
1395 "csrr t0, mhartid \n"
1396 "la t1, s_StkRiscvStackIsr \n"
1397 "slli t0, t0, " REGBYTES_LOG2
" \n"
1399 LREG
" t1, 0(t1) \n"
1401 "la t1, s_StkRiscvStackIsr \n"
1402 LREG
" t1, 0(t1) \n"
1404 LREG
" sp, 0(t1) \n"
1407 "jal ra, TrySwitchContext \n"
1410#if (STK_ARCH_CPU_COUNT > 1)
1411 "csrr t0, mhartid \n"
1412 "la t1, s_StkRiscvSpIsrInt \n"
1413 "slli t0, t0, " REGBYTES_LOG2
" \n"
1415 LREG
" sp, 0(t1) \n"
1417 "la t1, s_StkRiscvSpIsrInt \n"
1418 LREG
" sp, 0(t1) \n"
1422 STK_ASM_LOAD_CONTEXT
1425 STK_ASM_EXIT_FROM_HANDLER
" \n"
1435 STK_ASM_SAVE_CONTEXT
1441#if (STK_ARCH_CPU_COUNT > 1)
1442 "csrr t0, mhartid \n"
1443 "la t1, s_StkRiscvStackIdle \n"
1444 "slli t0, t0, " REGBYTES_LOG2
" \n"
1446 LREG
" t1, 0(t1) \n"
1448 "la t1, s_StkRiscvStackIdle \n"
1449 LREG
" t1, 0(t1) \n"
1451 SREG
" sp, 0(t1) \n"
1454#if (STK_ARCH_CPU_COUNT > 1)
1455 "csrr t0, mhartid \n"
1457 "li t1, %[clint_msip_base] \n"
1460 "li t0, %[clint_msip_base] \n"
1466#if (STK_ARCH_CPU_COUNT > 1)
1467 "csrr t0, mhartid \n"
1468 "la t1, s_StkRiscvStackActive \n"
1469 "slli t0, t0, " REGBYTES_LOG2
" \n"
1471 LREG
" t1, 0(t1) \n"
1473 "la t1, s_StkRiscvStackActive \n"
1474 LREG
" t1, 0(t1) \n"
1476 LREG
" sp, 0(t1) \n"
1479 STK_ASM_LOAD_CONTEXT
1482 STK_ASM_EXIT_FROM_HANDLER
" \n"
1485 : [clint_msip_base]
"i" (STK_RISCV_CLINT_BASE_ADDR)
1529extern "C" STK_RISCV_ISR_SECTION
__stk_attr_naked void STK_SYSTICK_HANDLER()
1533 STK_ASM_SAVE_CONTEXT
1539#if (STK_ARCH_CPU_COUNT > 1)
1540 "csrr t0, mhartid \n"
1541 "la t1, s_StkRiscvStackActive \n"
1542 "slli t0, t0, " REGBYTES_LOG2
" \n"
1544 LREG
" t1, 0(t1) \n"
1546 "la t1, s_StkRiscvStackActive \n"
1547 LREG
" t1, 0(t1) \n"
1549 SREG
" sp, 0(t1) \n"
1552#if (STK_ARCH_CPU_COUNT > 1)
1553 "csrr t0, mhartid \n"
1554 "la t1, s_StkRiscvStackIsr \n"
1555 "slli t0, t0, " REGBYTES_LOG2
" \n"
1557 LREG
" t1, 0(t1) \n"
1559 "la t1, s_StkRiscvStackIsr \n"
1560 LREG
" t1, 0(t1) \n"
1562 LREG
" sp, 0(t1) \n"
1569 "jal ra, TrySwitchContext \n"
1574#if (STK_ARCH_CPU_COUNT > 1)
1575 "csrr t0, mhartid \n"
1576 "la t1, s_StkRiscvStackActive \n"
1577 "slli t0, t0, " REGBYTES_LOG2
" \n"
1579 LREG
" t1, 0(t1) \n"
1581 "la t1, s_StkRiscvStackActive \n"
1582 LREG
" t1, 0(t1) \n"
1584 LREG
" sp, 0(t1) \n"
1587 STK_ASM_LOAD_CONTEXT
1590 STK_ASM_EXIT_FROM_HANDLER
" \n"
1599void Context::OnStart()
1601 const uint8_t hart = HW_GetHartId();
1607 HW_EnableFullFpuAccess();
1613 m_handler->OnStart(m_stack_active);
1615#if STK_TICKLESS_IDLE
1621 m_last_mtime = HW_GetMtime();
1622 HW_SetMtimecmp(m_last_mtime + m_tick_period);
1629 s_StkRiscvStackIsr[hart] = &m_stack_isr;
1630 s_StkRiscvStackActive[hart] = m_stack_active;
1631#ifdef _STK_RISCV_USE_PENDSV
1632 s_StkRiscvStackIdle[hart] = m_stack_idle;
1636 set_csr(mie, MIP_MTIP
1637 #ifdef _STK_RISCV_USE_PENDSV
1643STK_RISCV_ISR
void STK_SVC_HANDLER()
1646 __asm
volatile(
"csrr %0, mcause"
1661 if (cause == IRQ_M_EXT)
1671 write_csr(mepc, read_csr(mepc) +
sizeof(
Word));
1676 HW_DisableInterrupts();
1702static void OnTaskRun(
ITask *task)
1707static void OnTaskExit()
1710 HW_CriticalSectionStart(cs);
1714 HW_CriticalSectionEnd(cs);
1723static STK_RISCV_ISR_SECTION
void OnSchedulerSleep()
1725#if STK_SEGGER_SYSVIEW
1726 SEGGER_SYSVIEW_OnIdle();
1736static STK_RISCV_ISR_SECTION
void OnSchedulerSleepOverride()
1742static void OnSchedulerExit()
1753 GetContext().Initialize(event_handler, service, exit_trap, resolution_us);
1756void Context::Start()
1761 SaveJmp(m_exit_buf);
1765 m_handler->OnStop();
1770 HW_EnableFullFpuAccess();
1774 HW_StartScheduler();
1786 "TaskFrame size must match REGSIZE: (REGISTER_COUNT + SERVICE_SLOTS) * REGBYTES");
1794 stack->
SP =
hw::PtrToWord(stack_top - (STK_RISCV_REGISTER_COUNT + STK_SERVICE_SLOTS));
1797 TaskFrame *
const task_frame =
reinterpret_cast<TaskFrame *
>(stack->
SP);
1809 task_frame->MEPC =
hw::PtrToWord(
GetContext().m_overrider != NULL ? &OnSchedulerSleepOverride : &OnSchedulerSleep);
1824 task_frame->MSTATUS = MSTATUS_MPP | MSTATUS_MPIE | (STK_RISCV_FPU != 0 ? (MSTATUS_FS | MSTATUS_XS) : 0);
1826#if (STK_RISCV_FPU != 0)
1827 task_frame->X3_FSR = 0;
1833void Context::OnStop()
1839#ifdef _STK_RISCV_USE_PENDSV
1840 clear_csr(mie, MIP_MSIP);
1856 HW_DisableInterrupts();
1867 GetContext().m_handler->OnTaskSwitch(HW_GetCallerSP());
1872 GetContext().m_handler->OnTaskSleep(HW_GetCallerSP(), ticks);
1877 GetContext().m_handler->OnTaskSleepUntil(HW_GetCallerSP(), timestamp);
1882 return GetContext().m_handler->OnTaskWait(HW_GetCallerSP(), sync_obj, mutex, timeout);
1887 return GetContext().m_handler->OnGetTid(HW_GetCallerSP());
1906 return HW_GetCallerSP();
1932 HW_SpinLockLock(m_lock);
1937 HW_SpinLockUnlock(m_lock);
1942 return HW_SpinLockTryLock(m_lock);
1947 return HW_IsHandlerMode();
1952 return HiResClockImpl::GetInstance()->GetCycles();
1957 uint32_t freq = HiResClockImpl::GetInstance()->GetFrequency();
#define STK_SYSTEM_CORE_CLOCK_FREQUENCY
System clock frequency in Hz. Default: 150 MHz.
#define STK_SYSTEM_CORE_CLOCK_VAR
Definition of the system core clock variable holding frequency of the CPU in Hz.
volatile uint32_t SystemCoreClock
System clock frequency in Hz.
Contains common inventory for platform implementation.
#define STK_ARCH_GET_CPU_ID()
Get CPU core id of the caller, e.g. if called while running on core 0 then returned value must be 0.
#define GetContext()
Get platform's context.
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_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_STATIC_ASSERT_DESC(X, DESC)
Compile-time assertion with a custom error description. Produces a compilation error if X is false.
#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).
Contains helper implementations which simplify user-side code.
#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.
int64_t Ticks
Ticks value.
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_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_CPU_EXCEPTION
CPU reported an exception and halted execution.
@ KERNEL_PANIC_SPINLOCK_DEADLOCK
Spin-lock timeout expired: lock owner never released.
__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).
void SetEventOverrider(IEventOverrider *overrider)
Set platform event overrider.
void Initialize(IEventHandler *event_handler, IKernelService *service, uint32_t resolution_us, Stack *exit_trap)
Initialize scheduler's context.
void SleepUntil(Ticks timestamp)
Put calling process into a sleep state until the specified timestamp.
void SetSpecificEventHandler(ISpecificEventHandler *handler)
void Stop()
Stop scheduling.
void Sleep(Timeout ticks)
Put calling process into a sleep state.
void SwitchToNext()
Switch to a next task.
void ProcessTick()
Process one tick.
uint32_t GetTickResolution() const
Get resolution of the system tick timer in microseconds. Resolution means a number of microseconds be...
bool InitStack(EStackType stack_type, Stack *stack, IStackMemory *stack_memory, ITask *user_task)
Initialize stack memory of the user task.
void ProcessHardFault()
Cause a hard fault of the system.
IWaitObject * Wait(ISyncObject *sync_obj, IMutex *mutex, Timeout timeout)
Word GetCallerSP() const
Get caller's Stack Pointer (SP).
TId GetTid() const
Get thread Id.
void Start()
Start scheduling.
Base platform context for all platform implementations.
static Word * InitStackMemory(IStackMemory *memory)
Initialize stack memory by filling it with STK_STACK_MEMORY_FILLER.
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).
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.