xmclib/CMSIS/RTOS2/RTX/Source/rtx_system.c
2024-10-17 17:09:59 +02:00

255 lines
6.3 KiB
C

/*
* Copyright (c) 2013-2017 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: System functions
*
* -----------------------------------------------------------------------------
*/
#include "rtx_lib.h"
// ==== Helper functions ====
/// Put Object into ISR Queue.
/// \param[in] object object.
/// \return 1 - success, 0 - failure.
static uint32_t isr_queue_put (void *object) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#else
uint32_t n;
#endif
uint16_t max;
uint32_t ret;
max = osRtxInfo.isr_queue.max;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (osRtxInfo.isr_queue.cnt < max) {
osRtxInfo.isr_queue.cnt++;
osRtxInfo.isr_queue.data[osRtxInfo.isr_queue.in] = object;
if (++osRtxInfo.isr_queue.in == max) {
osRtxInfo.isr_queue.in = 0U;
}
ret = 1U;
} else {
ret = 0U;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_inc16_lt(&osRtxInfo.isr_queue.cnt, max) < max) {
n = atomic_inc16_lim(&osRtxInfo.isr_queue.in, max);
osRtxInfo.isr_queue.data[n] = object;
ret = 1U;
} else {
ret = 0U;
}
#endif
return ret;
}
/// Get Object from ISR Queue.
/// \return object or NULL.
static void *isr_queue_get (void) {
#if (__EXCLUSIVE_ACCESS == 0U)
uint32_t primask = __get_PRIMASK();
#else
uint32_t n;
#endif
uint16_t max;
void *ret;
max = osRtxInfo.isr_queue.max;
#if (__EXCLUSIVE_ACCESS == 0U)
__disable_irq();
if (osRtxInfo.isr_queue.cnt != 0U) {
osRtxInfo.isr_queue.cnt--;
ret = osRtxInfo.isr_queue.data[osRtxInfo.isr_queue.out];
if (++osRtxInfo.isr_queue.out == max) {
osRtxInfo.isr_queue.out = 0U;
}
} else {
ret = NULL;
}
if (primask == 0U) {
__enable_irq();
}
#else
if (atomic_dec16_nz(&osRtxInfo.isr_queue.cnt) != 0U) {
n = atomic_inc16_lim(&osRtxInfo.isr_queue.out, max);
ret = osRtxInfo.isr_queue.data[n];
} else {
ret = NULL;
}
#endif
return ret;
}
// ==== Library Functions ====
/// Tick Handler.
void osRtxTick_Handler (void) {
os_thread_t *thread;
osRtxSysTimerAckIRQ();
osRtxInfo.kernel.tick++;
// Process Timers
osRtxTimerTick();
// Process Thread Delays
osRtxThreadDelayTick();
osRtxThreadDispatch(NULL);
// Check Round Robin timeout
if (osRtxInfo.thread.robin.timeout != 0U) {
if (osRtxInfo.thread.robin.thread != osRtxInfo.thread.run.next) {
// Reset Round Robin
osRtxInfo.thread.robin.thread = osRtxInfo.thread.run.next;
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
} else {
if (osRtxInfo.thread.robin.tick != 0U) {
osRtxInfo.thread.robin.tick--;
}
if (osRtxInfo.thread.robin.tick == 0U) {
// Round Robin Timeout
if (osRtxKernelGetState() == osRtxKernelRunning) {
thread = osRtxInfo.thread.ready.thread_list;
if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) {
osRtxThreadListRemove(thread);
osRtxThreadReadyPut(osRtxInfo.thread.robin.thread);
osRtxThreadSwitch(thread);
osRtxInfo.thread.robin.thread = thread;
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
}
}
}
}
}
}
/// Pending Service Call Handler.
void osRtxPendSV_Handler (void) {
os_object_t *object;
for (;;) {
object = isr_queue_get();
if (object == NULL) {
break;
}
switch (object->id) {
case osRtxIdThread:
osRtxInfo.post_process.thread((os_thread_t *)object);
break;
case osRtxIdEventFlags:
osRtxInfo.post_process.event_flags((os_event_flags_t *)object);
break;
case osRtxIdSemaphore:
osRtxInfo.post_process.semaphore((os_semaphore_t *)object);
break;
case osRtxIdMemoryPool:
osRtxInfo.post_process.memory_pool((os_memory_pool_t *)object);
break;
case osRtxIdMessage:
osRtxInfo.post_process.message_queue((os_message_t *)object);
break;
default:
break;
}
}
osRtxThreadDispatch(NULL);
}
/// Register post ISR processing.
/// \param[in] object generic object.
void osRtxPostProcess (os_object_t *object) {
if (isr_queue_put(object) != 0U) {
if (osRtxInfo.kernel.blocked == 0U) {
SetPendSV();
} else {
osRtxInfo.kernel.pendSV = 1U;
}
} else {
osRtxErrorNotify(osRtxErrorISRQueueOverflow, object);
}
}
// ==== Public API ====
/// Setup System Timer.
__WEAK int32_t osRtxSysTimerSetup (void) {
// Setup SysTick Timer
SysTick_Setup(osRtxInfo.kernel.sys_freq / osRtxConfig.tick_freq);
return SysTick_IRQn; // Return IRQ number of SysTick
}
/// Enable System Timer.
__WEAK void osRtxSysTimerEnable (void) {
SysTick_Enable();
}
/// Disable System Timer.
__WEAK void osRtxSysTimerDisable (void) {
SysTick_Disable();
}
/// Acknowledge System Timer IRQ.
__WEAK void osRtxSysTimerAckIRQ (void) {
SysTick_GetOvf();
}
/// Get System Timer count.
__WEAK uint32_t osRtxSysTimerGetCount (void) {
uint32_t tick;
uint32_t val;
tick = (uint32_t)osRtxInfo.kernel.tick;
val = SysTick_GetVal();
if (SysTick_GetOvf()) {
val = SysTick_GetVal();
tick++;
}
val += tick * SysTick_GetPeriod();
return val;
}
/// Get System Timer frequency.
__WEAK uint32_t osRtxSysTimerGetFreq (void) {
return osRtxInfo.kernel.sys_freq;
}