|
79 | 79 | #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( 0x02U )
|
80 | 80 | #define tmrSTATUS_IS_AUTORELOAD ( 0x04U )
|
81 | 81 |
|
| 82 | +/* |
| 83 | + * Macros to mark the start and end of a critical code region. |
| 84 | + */ |
| 85 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 86 | + #define tmrENTER_CRITICAL() vTimerEnterCritical() |
| 87 | + #define tmrEXIT_CRITICAL() vTimerExitCritical() |
| 88 | + #else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 89 | + #define tmrENTER_CRITICAL() taskENTER_CRITICAL() |
| 90 | + #define tmrEXIT_CRITICAL() taskEXIT_CRITICAL() |
| 91 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 92 | + |
82 | 93 | /* The definition of the timers themselves. */
|
83 | 94 | typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */
|
84 | 95 | {
|
|
149 | 160 | PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
|
150 | 161 | PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
|
151 | 162 |
|
| 163 | + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) |
| 164 | + PRIVILEGED_DATA static portSPINLOCK_TYPE xTaskSpinlock = portINIT_SPINLOCK_STATIC; |
| 165 | + PRIVILEGED_DATA static portSPINLOCK_TYPE xISRSpinlock = portINIT_SPINLOCK_STATIC; |
| 166 | + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ |
| 167 | + |
| 168 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 169 | + |
| 170 | +/* |
| 171 | + * Enters a critical section for timers. Disables interrupts and takes |
| 172 | + * both task and ISR spinlocks to ensure thread safety. |
| 173 | + */ |
| 174 | + static void vTimerEnterCritical( void ) PRIVILEGED_FUNCTION; |
| 175 | + |
| 176 | +/* |
| 177 | + * Exits a critical section for timers. Releases spinlocks in reverse order |
| 178 | + * and conditionally re-enables interrupts and yields if required. |
| 179 | + */ |
| 180 | + static void vTimerExitCritical( void ) PRIVILEGED_FUNCTION; |
| 181 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
152 | 182 | /*-----------------------------------------------------------*/
|
153 | 183 |
|
154 | 184 | /*
|
|
576 | 606 | traceENTER_vTimerSetReloadMode( xTimer, xAutoReload );
|
577 | 607 |
|
578 | 608 | configASSERT( xTimer );
|
579 |
| - taskENTER_CRITICAL(); |
| 609 | + tmrENTER_CRITICAL(); |
580 | 610 | {
|
581 | 611 | if( xAutoReload != pdFALSE )
|
582 | 612 | {
|
|
587 | 617 | pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
|
588 | 618 | }
|
589 | 619 | }
|
590 |
| - taskEXIT_CRITICAL(); |
| 620 | + tmrEXIT_CRITICAL(); |
591 | 621 |
|
592 | 622 | traceRETURN_vTimerSetReloadMode();
|
593 | 623 | }
|
|
601 | 631 | traceENTER_xTimerGetReloadMode( xTimer );
|
602 | 632 |
|
603 | 633 | configASSERT( xTimer );
|
604 |
| - portBASE_TYPE_ENTER_CRITICAL(); |
| 634 | + tmrENTER_CRITICAL(); |
605 | 635 | {
|
606 | 636 | if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
|
607 | 637 | {
|
|
614 | 644 | xReturn = pdTRUE;
|
615 | 645 | }
|
616 | 646 | }
|
617 |
| - portBASE_TYPE_EXIT_CRITICAL(); |
| 647 | + tmrEXIT_CRITICAL(); |
618 | 648 |
|
619 | 649 | traceRETURN_xTimerGetReloadMode( xReturn );
|
620 | 650 |
|
|
1113 | 1143 | /* Check that the list from which active timers are referenced, and the
|
1114 | 1144 | * queue used to communicate with the timer service, have been
|
1115 | 1145 | * initialised. */
|
1116 |
| - taskENTER_CRITICAL(); |
| 1146 | + tmrENTER_CRITICAL(); |
1117 | 1147 | {
|
1118 | 1148 | if( xTimerQueue == NULL )
|
1119 | 1149 | {
|
|
1155 | 1185 | mtCOVERAGE_TEST_MARKER();
|
1156 | 1186 | }
|
1157 | 1187 | }
|
1158 |
| - taskEXIT_CRITICAL(); |
| 1188 | + tmrEXIT_CRITICAL(); |
1159 | 1189 | }
|
1160 | 1190 | /*-----------------------------------------------------------*/
|
1161 | 1191 |
|
|
1169 | 1199 | configASSERT( xTimer );
|
1170 | 1200 |
|
1171 | 1201 | /* Is the timer in the list of active timers? */
|
1172 |
| - portBASE_TYPE_ENTER_CRITICAL(); |
| 1202 | + tmrENTER_CRITICAL(); |
1173 | 1203 | {
|
1174 | 1204 | if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
|
1175 | 1205 | {
|
|
1180 | 1210 | xReturn = pdTRUE;
|
1181 | 1211 | }
|
1182 | 1212 | }
|
1183 |
| - portBASE_TYPE_EXIT_CRITICAL(); |
| 1213 | + tmrEXIT_CRITICAL(); |
1184 | 1214 |
|
1185 | 1215 | traceRETURN_xTimerIsTimerActive( xReturn );
|
1186 | 1216 |
|
|
1197 | 1227 |
|
1198 | 1228 | configASSERT( xTimer );
|
1199 | 1229 |
|
1200 |
| - taskENTER_CRITICAL(); |
| 1230 | + tmrENTER_CRITICAL(); |
1201 | 1231 | {
|
1202 | 1232 | pvReturn = pxTimer->pvTimerID;
|
1203 | 1233 | }
|
1204 |
| - taskEXIT_CRITICAL(); |
| 1234 | + tmrEXIT_CRITICAL(); |
1205 | 1235 |
|
1206 | 1236 | traceRETURN_pvTimerGetTimerID( pvReturn );
|
1207 | 1237 |
|
|
1218 | 1248 |
|
1219 | 1249 | configASSERT( xTimer );
|
1220 | 1250 |
|
1221 |
| - taskENTER_CRITICAL(); |
| 1251 | + tmrENTER_CRITICAL(); |
1222 | 1252 | {
|
1223 | 1253 | pxTimer->pvTimerID = pvNewID;
|
1224 | 1254 | }
|
1225 |
| - taskEXIT_CRITICAL(); |
| 1255 | + tmrEXIT_CRITICAL(); |
1226 | 1256 |
|
1227 | 1257 | traceRETURN_vTimerSetTimerID();
|
1228 | 1258 | }
|
|
1334 | 1364 | }
|
1335 | 1365 | /*-----------------------------------------------------------*/
|
1336 | 1366 |
|
| 1367 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 1368 | + static void vTimerEnterCritical( void ) |
| 1369 | + { |
| 1370 | + portDISABLE_INTERRUPTS(); |
| 1371 | + { |
| 1372 | + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); |
| 1373 | + |
| 1374 | + /* Task spinlock is always taken first */ |
| 1375 | + portGET_SPINLOCK( xCoreID, &xTaskSpinlock ); |
| 1376 | + |
| 1377 | + /* Take the ISR spinlock next */ |
| 1378 | + portGET_SPINLOCK( xCoreID, &xISRSpinlock ); |
| 1379 | + |
| 1380 | + /* Increment the critical nesting count */ |
| 1381 | + portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); |
| 1382 | + } |
| 1383 | + } |
| 1384 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 1385 | + |
| 1386 | +/*-----------------------------------------------------------*/ |
| 1387 | + |
| 1388 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 1389 | + static void vTimerExitCritical( void ) |
| 1390 | + { |
| 1391 | + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); |
| 1392 | + |
| 1393 | + configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); |
| 1394 | + |
| 1395 | + /* Get the xYieldPending status inside the critical section. */ |
| 1396 | + BaseType_t xYieldCurrentTask = xTaskUnlockCanYield(); |
| 1397 | + |
| 1398 | + /* Decrement the critical nesting count */ |
| 1399 | + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); |
| 1400 | + |
| 1401 | + /* Release the ISR spinlock */ |
| 1402 | + portRELEASE_SPINLOCK( xCoreID, &xISRSpinlock ); |
| 1403 | + |
| 1404 | + /* Release the task spinlock */ |
| 1405 | + portRELEASE_SPINLOCK( xCoreID, &xTaskSpinlock ); |
| 1406 | + |
| 1407 | + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) |
| 1408 | + { |
| 1409 | + portENABLE_INTERRUPTS(); |
| 1410 | + |
| 1411 | + if( xYieldCurrentTask != pdFALSE ) |
| 1412 | + { |
| 1413 | + portYIELD(); |
| 1414 | + } |
| 1415 | + else |
| 1416 | + { |
| 1417 | + mtCOVERAGE_TEST_MARKER(); |
| 1418 | + } |
| 1419 | + } |
| 1420 | + else |
| 1421 | + { |
| 1422 | + mtCOVERAGE_TEST_MARKER(); |
| 1423 | + } |
| 1424 | + } |
| 1425 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 1426 | +/*-----------------------------------------------------------*/ |
| 1427 | + |
1337 | 1428 | /* This entire source file will be skipped if the application is not configured
|
1338 | 1429 | * to include software timer functionality. If you want to include software timer
|
1339 | 1430 | * functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
|
|
0 commit comments