/* * Copyright (c) 2013-2019 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(os_object_t *object) { #if (EXCLUSIVE_ACCESS == 0) uint32_t primask = __get_PRIMASK(); #else uint32_t n; #endif uint16_t max; uint32_t ret; max = osRtxInfo.isr_queue.max; #if (EXCLUSIVE_ACCESS == 0) __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 os_object_t *isr_queue_get(void) { #if (EXCLUSIVE_ACCESS != 0) uint32_t n; #endif uint16_t max; os_object_t *ret; max = osRtxInfo.isr_queue.max; #if (EXCLUSIVE_ACCESS == 0) __disable_irq(); if (osRtxInfo.isr_queue.cnt != 0U) { osRtxInfo.isr_queue.cnt--; ret = osRtxObject(osRtxInfo.isr_queue.data[osRtxInfo.isr_queue.out]); if (++osRtxInfo.isr_queue.out == max) { osRtxInfo.isr_queue.out = 0U; } } else { ret = NULL; } __enable_irq(); #else if (atomic_dec16_nz(&osRtxInfo.isr_queue.cnt) != 0U) { n = atomic_inc16_lim(&osRtxInfo.isr_queue.out, max); ret = osRtxObject(osRtxInfo.isr_queue.data[n]); } else { ret = NULL; } #endif return ret; } // ==== Library Functions ==== /// Tick Handler. // lint -esym(714,osRtxTick_Handler) "Referenced by Exception handlers" // lint -esym(759,osRtxTick_Handler) "Prototype in header" // lint -esym(765,osRtxTick_Handler) "Global scope" void osRtxTick_Handler(void) { os_thread_t *thread; OS_Tick_AcknowledgeIRQ(); osRtxInfo.kernel.tick++; #if __RTX_CPU_STATISTICS__ osRtxInfo.thread.run.curr->rtime += 1; #endif // Process Timers if (osRtxInfo.timer.tick != NULL) { osRtxInfo.timer.tick(); } // 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); EvrRtxThreadPreempted(osRtxInfo.thread.robin.thread); osRtxThreadSwitch(thread); osRtxInfo.thread.robin.thread = thread; osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout; } } } } } } /// Pending Service Call Handler. // lint -esym(714,osRtxPendSV_Handler) "Referenced by Exception handlers" // lint -esym(759,osRtxPendSV_Handler) "Prototype in header" // lint -esym(765,osRtxPendSV_Handler) "Global scope" 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(osRtxThreadObject(object)); break; case osRtxIdEventFlags: osRtxInfo.post_process.event_flags(osRtxEventFlagsObject(object)); break; case osRtxIdSemaphore: osRtxInfo.post_process.semaphore(osRtxSemaphoreObject(object)); break; case osRtxIdMemoryPool: osRtxInfo.post_process.memory_pool(osRtxMemoryPoolObject(object)); break; case osRtxIdMessage: osRtxInfo.post_process.message(osRtxMessageObject(object)); break; default: // Should never come here 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 { (void)osRtxErrorNotify(osRtxErrorISRQueueOverflow, object); } }