11/* --------------------------------------------------------------------------
2- * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
2+ * Copyright (c) 2013-2022 Arm Limited. All rights reserved.
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 *
@@ -99,6 +99,15 @@ typedef struct {
9999/* Kernel initialization state */
100100static osKernelState_t KernelState = osKernelInactive ;
101101
102+ /* Get OS Tick count value */
103+ static uint32_t OS_Tick_GetCount (void );
104+ #if (configUSE_TICKLESS_IDLE == 0 )
105+ /* Get OS Tick overflow status */
106+ static uint32_t OS_Tick_GetOverflow (void );
107+ #endif
108+ /* Get OS Tick interval */
109+ static uint32_t OS_Tick_GetInterval (void );
110+
102111/*
103112 Heap region definition used by heap_5 variant
104113
@@ -118,7 +127,7 @@ static osKernelState_t KernelState = osKernelInactive;
118127 HeapRegion_t array.
119128 */
120129 #define HEAP_5_REGION_SETUP 1
121-
130+
122131 #ifndef configHEAP_5_REGIONS
123132 #define configHEAP_5_REGIONS xHeapRegions
124133
@@ -152,25 +161,29 @@ extern void xPortSysTickHandler (void);
152161/*
153162 SysTick handler implementation that also clears overflow flag.
154163*/
164+ #if (USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION == 0 )
155165void SysTick_Handler (void ) {
166+ #if (configUSE_TICKLESS_IDLE == 0 )
156167 /* Clear overflow flag */
157168 SysTick -> CTRL ;
169+ #endif
158170
159171 if (xTaskGetSchedulerState () != taskSCHEDULER_NOT_STARTED ) {
160172 /* Call tick handler */
161173 xPortSysTickHandler ();
162174 }
163175}
176+ #endif
164177#endif /* SysTick */
165178
166179/*
167180 Setup SVC to reset value.
168181*/
169182__STATIC_INLINE void SVC_Setup (void ) {
170183#if (__ARM_ARCH_7A__ == 0U )
171- /* Service Call interrupt might be configured before kernel start */
172- /* and when its priority is lower or equal to BASEPRI, svc intruction */
173- /* causes a Hard Fault. */
184+ /* Service Call interrupt might be configured before kernel start */
185+ /* and when its priority is lower or equal to BASEPRI, svc instruction */
186+ /* causes a Hard Fault. */
174187 NVIC_SetPriority (SVCall_IRQn , 0U );
175188#endif
176189}
@@ -213,11 +226,22 @@ __STATIC_INLINE uint32_t IRQ_Context (void) {
213226}
214227
215228/* Get OS Tick count value */
216- static uint32_t OS_Tick_GetCount (void );
229+ static uint32_t OS_Tick_GetCount (void ) {
230+ uint32_t load = SysTick -> LOAD ;
231+ return (load - SysTick -> VAL );
232+ }
233+
234+ #if (configUSE_TICKLESS_IDLE == 0 )
217235/* Get OS Tick overflow status */
218- static uint32_t OS_Tick_GetOverflow (void );
236+ static uint32_t OS_Tick_GetOverflow (void ) {
237+ return ((SysTick -> CTRL >> 16 ) & 1U );
238+ }
239+ #endif
240+
219241/* Get OS Tick interval */
220- static uint32_t OS_Tick_GetInterval (void );
242+ static uint32_t OS_Tick_GetInterval (void ) {
243+ return (SysTick -> LOAD + 1U );
244+ }
221245
222246/* ==== Kernel Management Functions ==== */
223247
@@ -464,26 +488,10 @@ uint32_t osKernelGetTickCount (void) {
464488 return (ticks );
465489}
466490
467- /* Get OS Tick count value */
468- static uint32_t OS_Tick_GetCount (void ) {
469- uint32_t load = SysTick -> LOAD ;
470- return (load - SysTick -> VAL );
471- }
472-
473- /* Get OS Tick overflow status */
474- static uint32_t OS_Tick_GetOverflow (void ) {
475- return ((SysTick -> CTRL >> 16 ) & 1U );
476- }
477-
478- /* Get OS Tick interval */
479- static uint32_t OS_Tick_GetInterval (void ) {
480- return (SysTick -> LOAD + 1U );
481- }
482-
483491/*
484492 Get the RTOS kernel tick frequency.
485493*/
486- uint32_t osKernelGetTickFreq (void ) {
494+ uint32_t osKernelGetTickFreq (void ) {
487495 /* Return frequency in hertz */
488496 return (configTICK_RATE_HZ );
489497}
@@ -495,17 +503,35 @@ uint32_t osKernelGetSysTimerCount (void) {
495503 uint32_t irqmask = IS_IRQ_MASKED ();
496504 TickType_t ticks ;
497505 uint32_t val ;
506+ #if (configUSE_TICKLESS_IDLE != 0 )
507+ uint32_t val0 ;
508+
509+ /* Low Power Tickless Idle controls timer overflow flag and therefore */
510+ /* OS_Tick_GetOverflow may be non-functional. As a workaround a reference */
511+ /* time is measured here before disabling interrupts. Timer value overflow */
512+ /* is then checked by comparing reference against latest time measurement. */
513+ /* Timer count value returned by this method is less accurate but if an */
514+ /* overflow is missed, an invalid timer count would be returned. */
515+ val0 = OS_Tick_GetCount ();
516+ #endif
498517
499518 __disable_irq ();
500519
501520 ticks = xTaskGetTickCount ();
502521 val = OS_Tick_GetCount ();
503522
504523 /* Update tick count and timer value when timer overflows */
524+ #if (configUSE_TICKLESS_IDLE != 0 )
525+ if (val < val0 ) {
526+ ticks ++ ;
527+ }
528+ #else
505529 if (OS_Tick_GetOverflow () != 0U ) {
506530 val = OS_Tick_GetCount ();
507531 ticks ++ ;
508532 }
533+ #endif
534+
509535 val += ticks * OS_Tick_GetInterval ();
510536
511537 if (irqmask == 0U ) {
@@ -652,7 +678,7 @@ osThreadState_t osThreadGetState (osThreadId_t thread_id) {
652678 case eReady : state = osThreadReady ; break ;
653679 case eBlocked :
654680 case eSuspended : state = osThreadBlocked ; break ;
655- case eDeleted : state = osThreadTerminated ; break ;
681+ case eDeleted :
656682 case eInvalid :
657683 default : state = osThreadError ; break ;
658684 }
@@ -1257,7 +1283,7 @@ osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
12571283 if (IRQ_Context () != 0U ) {
12581284 stat = osErrorISR ;
12591285 }
1260- else if (hTimer == NULL ) {
1286+ else if (( hTimer == NULL ) || ( ticks == 0U ) ) {
12611287 stat = osErrorParameter ;
12621288 }
12631289 else {
@@ -1442,7 +1468,9 @@ uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
14421468 if (xEventGroupSetBitsFromISR (hEventGroup , (EventBits_t )flags , & yield ) == pdFAIL ) {
14431469 rflags = (uint32_t )osErrorResource ;
14441470 } else {
1445- rflags = flags ;
1471+ /* Retrieve bits that are already set and add flags to be set in current call */
1472+ rflags = xEventGroupGetBitsFromISR (hEventGroup );
1473+ rflags |= flags ;
14461474 portYIELD_FROM_ISR (yield );
14471475 }
14481476 #endif
@@ -1535,7 +1563,13 @@ uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t opti
15351563 rflags = (uint32_t )osErrorParameter ;
15361564 }
15371565 else if (IRQ_Context () != 0U ) {
1538- rflags = (uint32_t )osErrorISR ;
1566+ if (timeout == 0U ) {
1567+ /* Try semantic is not supported */
1568+ rflags = (uint32_t )osErrorISR ;
1569+ } else {
1570+ /* Calling osEventFlagsWait from ISR with non-zero timeout is invalid */
1571+ rflags = (uint32_t )osFlagsErrorParameter ;
1572+ }
15391573 }
15401574 else {
15411575 if (options & osFlagsWaitAll ) {
@@ -1901,7 +1935,7 @@ osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, cons
19011935 #endif
19021936 }
19031937 }
1904-
1938+
19051939 #if (configQUEUE_REGISTRY_SIZE > 0 )
19061940 if (hSemaphore != NULL ) {
19071941 if ((attr != NULL ) && (attr -> name != NULL )) {
0 commit comments