| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- /*
- * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * -----------------------------------------------------------------------------
- *
- * Project: CMSIS-RTOS RTX
- * Title: Kernel functions
- *
- * -----------------------------------------------------------------------------
- */
- #include "rtx_lib.h"
- // OS Runtime Information
- osRtxInfo_t osRtxInfo __attribute__((section(".data.os"))) =
- //lint -e{785} "Initialize only OS ID, OS Version and Kernel State"
- { .os_id = osRtxKernelId, .version = osRtxVersionKernel, .kernel.state = osRtxKernelInactive };
- // ==== Helper functions ====
- /// Block Kernel (disable: thread switching, time tick, post ISR processing).
- static void KernelBlock (void) {
- OS_Tick_Disable();
- osRtxInfo.kernel.blocked = 1U;
- __DSB();
- if (GetPendSV() != 0U) {
- ClrPendSV();
- osRtxInfo.kernel.pendSV = 1U;
- }
- }
- /// Unblock Kernel
- static void KernelUnblock (void) {
- osRtxInfo.kernel.blocked = 0U;
- __DSB();
- if (osRtxInfo.kernel.pendSV != 0U) {
- osRtxInfo.kernel.pendSV = 0U;
- SetPendSV();
- }
- OS_Tick_Enable();
- }
- // Get Kernel sleep time
- static uint32_t GetKernelSleepTime (void) {
- const os_thread_t *thread;
- const os_timer_t *timer;
- uint32_t delay;
- delay = osWaitForever;
- // Check Thread Delay list
- thread = osRtxInfo.thread.delay_list;
- if (thread != NULL) {
- delay = thread->delay;
- }
- // Check Active Timer list
- timer = osRtxInfo.timer.list;
- if (timer != NULL) {
- if (timer->tick < delay) {
- delay = timer->tick;
- }
- }
- return delay;
- }
- // ==== Service Calls ====
- /// Initialize the RTOS Kernel.
- /// \note API identical to osKernelInitialize
- static osStatus_t svcRtxKernelInitialize (void) {
- if (osRtxInfo.kernel.state == osRtxKernelReady) {
- EvrRtxKernelInitialized();
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osOK;
- }
- if (osRtxInfo.kernel.state != osRtxKernelInactive) {
- EvrRtxKernelError((int32_t)osError);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osError;
- }
- #if (DOMAIN_NS == 1)
- // Initialize Secure Process Stack
- if (TZ_InitContextSystem_S() == 0U) {
- EvrRtxKernelError(osRtxErrorTZ_InitContext_S);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osError;
- }
- #endif
- // Initialize osRtxInfo
- osRtxInfo.isr_queue.data = osRtxConfig.isr_queue.data;
- osRtxInfo.isr_queue.max = osRtxConfig.isr_queue.max;
- osRtxInfo.thread.robin.timeout = osRtxConfig.robin_timeout;
- // Initialize Memory Pools (Variable Block Size)
- if (osRtxMemoryInit(osRtxConfig.mem.common_addr, osRtxConfig.mem.common_size) != 0U) {
- osRtxInfo.mem.common = osRtxConfig.mem.common_addr;
- }
- if (osRtxMemoryInit(osRtxConfig.mem.stack_addr, osRtxConfig.mem.stack_size) != 0U) {
- osRtxInfo.mem.stack = osRtxConfig.mem.stack_addr;
- } else {
- osRtxInfo.mem.stack = osRtxInfo.mem.common;
- }
- if (osRtxMemoryInit(osRtxConfig.mem.mp_data_addr, osRtxConfig.mem.mp_data_size) != 0U) {
- osRtxInfo.mem.mp_data = osRtxConfig.mem.mp_data_addr;
- } else {
- osRtxInfo.mem.mp_data = osRtxInfo.mem.common;
- }
- if (osRtxMemoryInit(osRtxConfig.mem.mq_data_addr, osRtxConfig.mem.mq_data_size) != 0U) {
- osRtxInfo.mem.mq_data = osRtxConfig.mem.mq_data_addr;
- } else {
- osRtxInfo.mem.mq_data = osRtxInfo.mem.common;
- }
- // Initialize Memory Pools (Fixed Block Size)
- if (osRtxConfig.mpi.stack != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.stack,
- osRtxConfig.mpi.stack->max_blocks,
- osRtxConfig.mpi.stack->block_size,
- osRtxConfig.mpi.stack->block_base);
- osRtxInfo.mpi.stack = osRtxConfig.mpi.stack;
- }
- if (osRtxConfig.mpi.thread != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.thread,
- osRtxConfig.mpi.thread->max_blocks,
- osRtxConfig.mpi.thread->block_size,
- osRtxConfig.mpi.thread->block_base);
- osRtxInfo.mpi.thread = osRtxConfig.mpi.thread;
- }
- if (osRtxConfig.mpi.timer != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.timer,
- osRtxConfig.mpi.timer->max_blocks,
- osRtxConfig.mpi.timer->block_size,
- osRtxConfig.mpi.timer->block_base);
- osRtxInfo.mpi.timer = osRtxConfig.mpi.timer;
- }
- if (osRtxConfig.mpi.event_flags != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.event_flags,
- osRtxConfig.mpi.event_flags->max_blocks,
- osRtxConfig.mpi.event_flags->block_size,
- osRtxConfig.mpi.event_flags->block_base);
- osRtxInfo.mpi.event_flags = osRtxConfig.mpi.event_flags;
- }
- if (osRtxConfig.mpi.mutex != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.mutex,
- osRtxConfig.mpi.mutex->max_blocks,
- osRtxConfig.mpi.mutex->block_size,
- osRtxConfig.mpi.mutex->block_base);
- osRtxInfo.mpi.mutex = osRtxConfig.mpi.mutex;
- }
- if (osRtxConfig.mpi.semaphore != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.semaphore,
- osRtxConfig.mpi.semaphore->max_blocks,
- osRtxConfig.mpi.semaphore->block_size,
- osRtxConfig.mpi.semaphore->block_base);
- osRtxInfo.mpi.semaphore = osRtxConfig.mpi.semaphore;
- }
- if (osRtxConfig.mpi.memory_pool != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.memory_pool,
- osRtxConfig.mpi.memory_pool->max_blocks,
- osRtxConfig.mpi.memory_pool->block_size,
- osRtxConfig.mpi.memory_pool->block_base);
- osRtxInfo.mpi.memory_pool = osRtxConfig.mpi.memory_pool;
- }
- if (osRtxConfig.mpi.message_queue != NULL) {
- (void)osRtxMemoryPoolInit(osRtxConfig.mpi.message_queue,
- osRtxConfig.mpi.message_queue->max_blocks,
- osRtxConfig.mpi.message_queue->block_size,
- osRtxConfig.mpi.message_queue->block_base);
- osRtxInfo.mpi.message_queue = osRtxConfig.mpi.message_queue;
- }
- osRtxInfo.kernel.state = osRtxKernelReady;
- EvrRtxKernelInitialized();
- return osOK;
- }
- /// Get RTOS Kernel Information.
- /// \note API identical to osKernelGetInfo
- static osStatus_t svcRtxKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
- uint32_t size;
- if (version != NULL) {
- version->api = osRtxVersionAPI;
- version->kernel = osRtxVersionKernel;
- }
- if ((id_buf != NULL) && (id_size != 0U)) {
- if (id_size > sizeof(osRtxKernelId)) {
- size = sizeof(osRtxKernelId);
- } else {
- size = id_size;
- }
- (void)memcpy(id_buf, osRtxKernelId, size);
- }
- EvrRtxKernelInfoRetrieved(version, id_buf, id_size);
- return osOK;
- }
- /// Get the current RTOS Kernel state.
- /// \note API identical to osKernelGetState
- static osKernelState_t svcRtxKernelGetState (void) {
- osKernelState_t state = osRtxKernelState();
- EvrRtxKernelGetState(state);
- return state;
- }
- /// Start the RTOS Kernel scheduler.
- /// \note API identical to osKernelStart
- static osStatus_t svcRtxKernelStart (void) {
- os_thread_t *thread;
- if (osRtxInfo.kernel.state != osRtxKernelReady) {
- EvrRtxKernelError(osRtxErrorKernelNotReady);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osError;
- }
- // Thread startup (Idle and Timer Thread)
- if (!osRtxThreadStartup()) {
- EvrRtxKernelError((int32_t)osError);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osError;
- }
- // Setup SVC and PendSV System Service Calls
- SVC_Setup();
- // Setup RTOS Tick
- if (OS_Tick_Setup(osRtxConfig.tick_freq, OS_TICK_HANDLER) != 0) {
- EvrRtxKernelError((int32_t)osError);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return osError;
- }
- osRtxInfo.tick_irqn = OS_Tick_GetIRQn();
- // Enable RTOS Tick
- OS_Tick_Enable();
- // Switch to Ready Thread with highest Priority
- thread = osRtxThreadListGet(&osRtxInfo.thread.ready);
- osRtxThreadSwitch(thread);
- if ((osRtxConfig.flags & osRtxConfigPrivilegedMode) != 0U) {
- // Privileged Thread mode & PSP
- __set_CONTROL(0x02U);
- } else {
- // Unprivileged Thread mode & PSP
- __set_CONTROL(0x03U);
- }
- osRtxInfo.kernel.state = osRtxKernelRunning;
- EvrRtxKernelStarted();
- return osOK;
- }
- /// Lock the RTOS Kernel scheduler.
- /// \note API identical to osKernelLock
- static int32_t svcRtxKernelLock (void) {
- int32_t lock;
- switch (osRtxInfo.kernel.state) {
- case osRtxKernelRunning:
- osRtxInfo.kernel.state = osRtxKernelLocked;
- EvrRtxKernelLocked(0);
- lock = 0;
- break;
- case osRtxKernelLocked:
- EvrRtxKernelLocked(1);
- lock = 1;
- break;
- default:
- EvrRtxKernelError((int32_t)osError);
- lock = (int32_t)osError;
- break;
- }
- return lock;
- }
- /// Unlock the RTOS Kernel scheduler.
- /// \note API identical to osKernelUnlock
- static int32_t svcRtxKernelUnlock (void) {
- int32_t lock;
- switch (osRtxInfo.kernel.state) {
- case osRtxKernelRunning:
- EvrRtxKernelUnlocked(0);
- lock = 0;
- break;
- case osRtxKernelLocked:
- osRtxInfo.kernel.state = osRtxKernelRunning;
- EvrRtxKernelUnlocked(1);
- lock = 1;
- break;
- default:
- EvrRtxKernelError((int32_t)osError);
- lock = (int32_t)osError;
- break;
- }
- return lock;
- }
- /// Restore the RTOS Kernel scheduler lock state.
- /// \note API identical to osKernelRestoreLock
- static int32_t svcRtxKernelRestoreLock (int32_t lock) {
- int32_t lock_new;
- switch (osRtxInfo.kernel.state) {
- case osRtxKernelRunning:
- case osRtxKernelLocked:
- switch (lock) {
- case 0:
- osRtxInfo.kernel.state = osRtxKernelRunning;
- EvrRtxKernelLockRestored(0);
- lock_new = 0;
- break;
- case 1:
- osRtxInfo.kernel.state = osRtxKernelLocked;
- EvrRtxKernelLockRestored(1);
- lock_new = 1;
- break;
- default:
- EvrRtxKernelError((int32_t)osError);
- lock_new = (int32_t)osError;
- break;
- }
- break;
- default:
- EvrRtxKernelError((int32_t)osError);
- lock_new = (int32_t)osError;
- break;
- }
- return lock_new;
- }
- /// Suspend the RTOS Kernel scheduler.
- /// \note API identical to osKernelSuspend
- static uint32_t svcRtxKernelSuspend (void) {
- uint32_t delay;
- if (osRtxInfo.kernel.state != osRtxKernelRunning) {
- EvrRtxKernelError(osRtxErrorKernelNotRunning);
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return 0U;
- }
- KernelBlock();
- osRtxInfo.kernel.state = osRtxKernelSuspended;
- delay = GetKernelSleepTime();
- EvrRtxKernelSuspended(delay);
- return delay;
- }
- /// Resume the RTOS Kernel scheduler.
- /// \note API identical to osKernelResume
- static void svcRtxKernelResume (uint32_t sleep_ticks) {
- os_thread_t *thread;
- os_timer_t *timer;
- uint32_t delay;
- uint32_t ticks, kernel_tick;
- if (osRtxInfo.kernel.state != osRtxKernelSuspended) {
- EvrRtxKernelResumed();
- //lint -e{904} "Return statement before end of function" [MISRA Note 1]
- return;
- }
- delay = GetKernelSleepTime();
- if (sleep_ticks >= delay) {
- ticks = delay - 1U;
- } else {
- ticks = sleep_ticks;
- }
- // Update Thread Delay sleep ticks
- thread = osRtxInfo.thread.delay_list;
- if (thread != NULL) {
- thread->delay -= ticks;
- }
- // Update Timer sleep ticks
- timer = osRtxInfo.timer.list;
- if (timer != NULL) {
- timer->tick -= ticks;
- }
- kernel_tick = osRtxInfo.kernel.tick + sleep_ticks;
- osRtxInfo.kernel.tick += ticks;
- while (osRtxInfo.kernel.tick != kernel_tick) {
- osRtxInfo.kernel.tick++;
- // Process Thread Delays
- osRtxThreadDelayTick();
- // Process Timers
- if (osRtxInfo.timer.tick != NULL) {
- osRtxInfo.timer.tick();
- }
- }
- osRtxInfo.kernel.state = osRtxKernelRunning;
- osRtxThreadDispatch(NULL);
- KernelUnblock();
- EvrRtxKernelResumed();
- }
- /// Get the RTOS kernel tick count.
- /// \note API identical to osKernelGetTickCount
- static uint32_t svcRtxKernelGetTickCount (void) {
- EvrRtxKernelGetTickCount(osRtxInfo.kernel.tick);
- return osRtxInfo.kernel.tick;
- }
- /// Get the RTOS kernel tick frequency.
- /// \note API identical to osKernelGetTickFreq
- static uint32_t svcRtxKernelGetTickFreq (void) {
- EvrRtxKernelGetTickFreq(osRtxConfig.tick_freq);
- return osRtxConfig.tick_freq;
- }
- /// Get the RTOS kernel system timer count.
- /// \note API identical to osKernelGetSysTimerCount
- static uint32_t svcRtxKernelGetSysTimerCount (void) {
- uint32_t tick;
- uint32_t count;
- tick = (uint32_t)osRtxInfo.kernel.tick;
- count = OS_Tick_GetCount();
- if (OS_Tick_GetOverflow() != 0U) {
- count = OS_Tick_GetCount();
- tick++;
- }
- count += tick * OS_Tick_GetInterval();
- EvrRtxKernelGetSysTimerCount(count);
- return count;
- }
- /// Get the RTOS kernel system timer frequency.
- /// \note API identical to osKernelGetSysTimerFreq
- static uint32_t svcRtxKernelGetSysTimerFreq (void) {
- uint32_t freq = OS_Tick_GetClock();
- EvrRtxKernelGetSysTimerFreq(freq);
- return freq;
- }
- // Service Calls definitions
- //lint ++flb "Library Begin" [MISRA Note 11]
- SVC0_0 (KernelInitialize, osStatus_t)
- SVC0_3 (KernelGetInfo, osStatus_t, osVersion_t *, char *, uint32_t)
- SVC0_0 (KernelStart, osStatus_t)
- SVC0_0 (KernelLock, int32_t)
- SVC0_0 (KernelUnlock, int32_t)
- SVC0_1 (KernelRestoreLock, int32_t, int32_t)
- SVC0_0 (KernelSuspend, uint32_t)
- SVC0_1N(KernelResume, void, uint32_t)
- SVC0_0 (KernelGetState, osKernelState_t)
- SVC0_0 (KernelGetTickCount, uint32_t)
- SVC0_0 (KernelGetTickFreq, uint32_t)
- SVC0_0 (KernelGetSysTimerCount, uint32_t)
- SVC0_0 (KernelGetSysTimerFreq, uint32_t)
- //lint --flb "Library End"
- // ==== Library functions ====
- /// RTOS Kernel Pre-Initialization Hook
- //lint -esym(759,osRtxKernelPreInit) "Prototype in header"
- //lint -esym(765,osRtxKernelPreInit) "Global scope (can be overridden)"
- //lint -esym(522,osRtxKernelPreInit) "Can be overridden (do not lack side-effects)"
- __WEAK void osRtxKernelPreInit (void) {
- }
- /// RTOS Kernel Error Notification Handler
- /// \note API identical to osRtxErrorNotify
- uint32_t osRtxKernelErrorNotify (uint32_t code, void *object_id) {
- EvrRtxKernelErrorNotify(code, object_id);
- return osRtxErrorNotify(code, object_id);
- }
- // ==== Public API ====
- /// Initialize the RTOS Kernel.
- osStatus_t osKernelInitialize (void) {
- osStatus_t status;
- osRtxKernelPreInit();
- EvrRtxKernelInitialize();
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- status = osErrorISR;
- } else {
- status = __svcKernelInitialize();
- }
- return status;
- }
- /// Get RTOS Kernel Information.
- osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
- osStatus_t status;
- EvrRtxKernelGetInfo(version, id_buf, id_size);
- if (IsException() || IsIrqMasked() || IsPrivileged()) {
- status = svcRtxKernelGetInfo(version, id_buf, id_size);
- } else {
- status = __svcKernelGetInfo(version, id_buf, id_size);
- }
- return status;
- }
- /// Get the current RTOS Kernel state.
- osKernelState_t osKernelGetState (void) {
- osKernelState_t state;
- if (IsException() || IsIrqMasked() || IsPrivileged()) {
- state = svcRtxKernelGetState();
- } else {
- state = __svcKernelGetState();
- }
- return state;
- }
- /// Start the RTOS Kernel scheduler.
- osStatus_t osKernelStart (void) {
- osStatus_t status;
- EvrRtxKernelStart();
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- status = osErrorISR;
- } else {
- status = __svcKernelStart();
- }
- return status;
- }
- /// Lock the RTOS Kernel scheduler.
- int32_t osKernelLock (void) {
- int32_t lock;
- EvrRtxKernelLock();
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- lock = (int32_t)osErrorISR;
- } else {
- lock = __svcKernelLock();
- }
- return lock;
- }
- /// Unlock the RTOS Kernel scheduler.
- int32_t osKernelUnlock (void) {
- int32_t lock;
- EvrRtxKernelUnlock();
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- lock = (int32_t)osErrorISR;
- } else {
- lock = __svcKernelUnlock();
- }
- return lock;
- }
- /// Restore the RTOS Kernel scheduler lock state.
- int32_t osKernelRestoreLock (int32_t lock) {
- int32_t lock_new;
- EvrRtxKernelRestoreLock(lock);
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- lock_new = (int32_t)osErrorISR;
- } else {
- lock_new = __svcKernelRestoreLock(lock);
- }
- return lock_new;
- }
- /// Suspend the RTOS Kernel scheduler.
- uint32_t osKernelSuspend (void) {
- uint32_t ticks;
- EvrRtxKernelSuspend();
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- ticks = 0U;
- } else {
- ticks = __svcKernelSuspend();
- }
- return ticks;
- }
- /// Resume the RTOS Kernel scheduler.
- void osKernelResume (uint32_t sleep_ticks) {
- EvrRtxKernelResume(sleep_ticks);
- if (IsException() || IsIrqMasked()) {
- EvrRtxKernelError((int32_t)osErrorISR);
- } else {
- __svcKernelResume(sleep_ticks);
- }
- }
- /// Get the RTOS kernel tick count.
- uint32_t osKernelGetTickCount (void) {
- uint32_t count;
- if (IsException() || IsIrqMasked()) {
- count = svcRtxKernelGetTickCount();
- } else {
- count = __svcKernelGetTickCount();
- }
- return count;
- }
- /// Get the RTOS kernel tick frequency.
- uint32_t osKernelGetTickFreq (void) {
- uint32_t freq;
- if (IsException() || IsIrqMasked()) {
- freq = svcRtxKernelGetTickFreq();
- } else {
- freq = __svcKernelGetTickFreq();
- }
- return freq;
- }
- /// Get the RTOS kernel system timer count.
- uint32_t osKernelGetSysTimerCount (void) {
- uint32_t count;
- if (IsException() || IsIrqMasked()) {
- count = svcRtxKernelGetSysTimerCount();
- } else {
- count = __svcKernelGetSysTimerCount();
- }
- return count;
- }
- /// Get the RTOS kernel system timer frequency.
- uint32_t osKernelGetSysTimerFreq (void) {
- uint32_t freq;
- if (IsException() || IsIrqMasked()) {
- freq = svcRtxKernelGetSysTimerFreq();
- } else {
- freq = __svcKernelGetSysTimerFreq();
- }
- return freq;
- }
|