214 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			214 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * 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++; | ||
|  | 
 | ||
|  |   // 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); | ||
|  |   } | ||
|  | } |