#include #include #include #include #include #include #include #include #include #include #include #include #include #include __attribute__((noreturn)) void rt_task_entry(void); #if RT_ARM_PROFILE_AR #include "ar/ar.c" #elif RT_ARM_PROFILE_M #include "m/m.c" #endif void *rt_context_init(uintptr_t fn, uintptr_t arg, void *stack, size_t stack_size) { void *const sp = (char *)stack + stack_size; struct context *ctx = sp; --ctx; profile_context_init(ctx); #if RT_ARM_V8M /* V8M is the only variant with additional state based on the stack, so set * that here rather than pass the stack to profile_context_init. */ ctx->psplim = (uint32_t)stack; #endif // RT_ARM_V8M /* Exception return in all profiles will ignore the LSB of this field and * set the execution state based on the psr instead, but clear the LSB here * to match the behavior of exception entry, which does not set the LSB of * the exception return address. */ ctx->r0 = arg; ctx->r1 = fn; ctx->pc = (uint32_t)rt_task_entry & ~UINT32_C(1); return ctx; } __attribute__((noreturn, weak)) void rt_idle(void) { rt_task_drop_privilege(); for (;;) { __asm__("wfi" :::); } } __attribute__((noreturn, weak)) void rt_abort(void) { for (;;) { __asm__("udf" :::); } } __attribute__((noreturn, weak)) void rt_trap(void) { for (;;) { __asm__("bkpt" :::); } } #if RT_ARM_V6M #include "m/atomic-v6.c" #endif