|
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 | /*
|
|
572 | 602 | traceENTER_vTimerSetReloadMode( xTimer, xAutoReload );
|
573 | 603 |
|
574 | 604 | configASSERT( xTimer );
|
575 |
| - taskENTER_CRITICAL(); |
| 605 | + tmrENTER_CRITICAL(); |
576 | 606 | {
|
577 | 607 | if( xAutoReload != pdFALSE )
|
578 | 608 | {
|
|
583 | 613 | pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
|
584 | 614 | }
|
585 | 615 | }
|
586 |
| - taskEXIT_CRITICAL(); |
| 616 | + tmrEXIT_CRITICAL(); |
587 | 617 |
|
588 | 618 | traceRETURN_vTimerSetReloadMode();
|
589 | 619 | }
|
|
597 | 627 | traceENTER_xTimerGetReloadMode( xTimer );
|
598 | 628 |
|
599 | 629 | configASSERT( xTimer );
|
600 |
| - portBASE_TYPE_ENTER_CRITICAL(); |
| 630 | + tmrENTER_CRITICAL(); |
601 | 631 | {
|
602 | 632 | if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
|
603 | 633 | {
|
|
610 | 640 | xReturn = pdTRUE;
|
611 | 641 | }
|
612 | 642 | }
|
613 |
| - portBASE_TYPE_EXIT_CRITICAL(); |
| 643 | + tmrEXIT_CRITICAL(); |
614 | 644 |
|
615 | 645 | traceRETURN_xTimerGetReloadMode( xReturn );
|
616 | 646 |
|
|
1116 | 1146 | /* Check that the list from which active timers are referenced, and the
|
1117 | 1147 | * queue used to communicate with the timer service, have been
|
1118 | 1148 | * initialised. */
|
1119 |
| - taskENTER_CRITICAL(); |
| 1149 | + tmrENTER_CRITICAL(); |
1120 | 1150 | {
|
1121 | 1151 | if( xTimerQueue == NULL )
|
1122 | 1152 | {
|
|
1158 | 1188 | mtCOVERAGE_TEST_MARKER();
|
1159 | 1189 | }
|
1160 | 1190 | }
|
1161 |
| - taskEXIT_CRITICAL(); |
| 1191 | + tmrEXIT_CRITICAL(); |
1162 | 1192 | }
|
1163 | 1193 | /*-----------------------------------------------------------*/
|
1164 | 1194 |
|
|
1172 | 1202 | configASSERT( xTimer );
|
1173 | 1203 |
|
1174 | 1204 | /* Is the timer in the list of active timers? */
|
1175 |
| - portBASE_TYPE_ENTER_CRITICAL(); |
| 1205 | + tmrENTER_CRITICAL(); |
1176 | 1206 | {
|
1177 | 1207 | if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
|
1178 | 1208 | {
|
|
1183 | 1213 | xReturn = pdTRUE;
|
1184 | 1214 | }
|
1185 | 1215 | }
|
1186 |
| - portBASE_TYPE_EXIT_CRITICAL(); |
| 1216 | + tmrEXIT_CRITICAL(); |
1187 | 1217 |
|
1188 | 1218 | traceRETURN_xTimerIsTimerActive( xReturn );
|
1189 | 1219 |
|
|
1200 | 1230 |
|
1201 | 1231 | configASSERT( xTimer );
|
1202 | 1232 |
|
1203 |
| - taskENTER_CRITICAL(); |
| 1233 | + tmrENTER_CRITICAL(); |
1204 | 1234 | {
|
1205 | 1235 | pvReturn = pxTimer->pvTimerID;
|
1206 | 1236 | }
|
1207 |
| - taskEXIT_CRITICAL(); |
| 1237 | + tmrEXIT_CRITICAL(); |
1208 | 1238 |
|
1209 | 1239 | traceRETURN_pvTimerGetTimerID( pvReturn );
|
1210 | 1240 |
|
|
1221 | 1251 |
|
1222 | 1252 | configASSERT( xTimer );
|
1223 | 1253 |
|
1224 |
| - taskENTER_CRITICAL(); |
| 1254 | + tmrENTER_CRITICAL(); |
1225 | 1255 | {
|
1226 | 1256 | pxTimer->pvTimerID = pvNewID;
|
1227 | 1257 | }
|
1228 |
| - taskEXIT_CRITICAL(); |
| 1258 | + tmrEXIT_CRITICAL(); |
1229 | 1259 |
|
1230 | 1260 | traceRETURN_vTimerSetTimerID();
|
1231 | 1261 | }
|
|
1337 | 1367 | }
|
1338 | 1368 | /*-----------------------------------------------------------*/
|
1339 | 1369 |
|
| 1370 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 1371 | + static void vTimerEnterCritical( void ) |
| 1372 | + { |
| 1373 | + portDISABLE_INTERRUPTS(); |
| 1374 | + { |
| 1375 | + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); |
| 1376 | + |
| 1377 | + /* Task spinlock is always taken first */ |
| 1378 | + portGET_SPINLOCK( xCoreID, &xTaskSpinlock ); |
| 1379 | + |
| 1380 | + /* Take the ISR spinlock next */ |
| 1381 | + portGET_SPINLOCK( xCoreID, &xISRSpinlock ); |
| 1382 | + |
| 1383 | + /* Increment the critical nesting count */ |
| 1384 | + portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); |
| 1385 | + } |
| 1386 | + } |
| 1387 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 1388 | + |
| 1389 | +/*-----------------------------------------------------------*/ |
| 1390 | + |
| 1391 | + #if ( portUSING_GRANULAR_LOCKS == 1 ) |
| 1392 | + static void vTimerExitCritical( void ) |
| 1393 | + { |
| 1394 | + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); |
| 1395 | + |
| 1396 | + configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); |
| 1397 | + |
| 1398 | + /* Get the xYieldPending status inside the critical section. */ |
| 1399 | + BaseType_t xYieldCurrentTask = xTaskUnlockCanYield(); |
| 1400 | + |
| 1401 | + /* Decrement the critical nesting count */ |
| 1402 | + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); |
| 1403 | + |
| 1404 | + /* Release the ISR spinlock */ |
| 1405 | + portRELEASE_SPINLOCK( xCoreID, &xISRSpinlock ); |
| 1406 | + |
| 1407 | + /* Release the task spinlock */ |
| 1408 | + portRELEASE_SPINLOCK( xCoreID, &xTaskSpinlock ); |
| 1409 | + |
| 1410 | + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) |
| 1411 | + { |
| 1412 | + portENABLE_INTERRUPTS(); |
| 1413 | + |
| 1414 | + if( xYieldCurrentTask != pdFALSE ) |
| 1415 | + { |
| 1416 | + portYIELD(); |
| 1417 | + } |
| 1418 | + else |
| 1419 | + { |
| 1420 | + mtCOVERAGE_TEST_MARKER(); |
| 1421 | + } |
| 1422 | + } |
| 1423 | + else |
| 1424 | + { |
| 1425 | + mtCOVERAGE_TEST_MARKER(); |
| 1426 | + } |
| 1427 | + } |
| 1428 | + #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ |
| 1429 | +/*-----------------------------------------------------------*/ |
| 1430 | + |
1340 | 1431 | /* This entire source file will be skipped if the application is not configured
|
1341 | 1432 | * to include software timer functionality. If you want to include software timer
|
1342 | 1433 | * functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
|
|
0 commit comments