Skip to content

Commit 99797e1

Browse files
kar-rahul-awsaggargUbuntu
authored
Cortex-M Assert when NVIC implements 8 PRIO bits (#639)
* Cortex-M Assert when NVIC implements 8 PRIO bits * Fix CM3 ports * Fix ARM_CM3_MPU * Fix ARM CM3 * Fix ARM_CM4_MPU * Fix ARM_CM4 * Fix GCC ARM_CM7 * Fix IAR ARM ports * Uncrustify changes * Fix MikroC_ARM_CM4F port * Fix MikroC_ARM_CM4F port-(2) * Fix RVDS ARM ports * Revert changes for Tasking/ARM_CM4F port * Revert changes for Tasking/ARM_CM4F port-(2) * Update port.c Fix GCC/ARM_CM4F port * Update port.c * update GCC\ARM_CM4F port * update port.c * Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority * Fix merge error: remove duplicate code * Fix typos --------- Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Ubuntu <ubuntu@ip-172-31-17-174.ec2.internal>
1 parent 9488ba2 commit 99797e1

File tree

17 files changed

+805
-366
lines changed

17 files changed

+805
-366
lines changed

portable/CCS/ARM_CM3/port.c

100644100755
+45-18
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ BaseType_t xPortStartScheduler( void )
219219
#if ( configASSERT_DEFINED == 1 )
220220
{
221221
volatile uint32_t ulOriginalPriority;
222+
volatile uint32_t ulImplementedPrioBits = 0;
222223
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
223224
volatile uint8_t ucMaxPriorityValue;
224225

@@ -250,20 +251,46 @@ BaseType_t xPortStartScheduler( void )
250251

251252
/* Calculate the maximum acceptable priority group value for the number
252253
* of bits read back. */
253-
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
254254

255255
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
256256
{
257-
ulMaxPRIGROUPValue--;
257+
ulImplementedPrioBits++;
258258
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
259259
}
260260

261+
if( ulImplementedPrioBits == 8 )
262+
{
263+
/* When the hardware implements 8 priority bits, there is no way for
264+
* the software to configure PRIGROUP to not have sub-priorities. As
265+
* a result, the least significant bit is always used for sub-priority
266+
* and there are 128 preemption priorities and 2 sub-priorities.
267+
*
268+
* This may cause some confusion in some cases - for example, if
269+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
270+
* priority interrupts will be masked in Critical Sections as those
271+
* are at the same preemption priority. This may appear confusing as
272+
* 4 is higher (numerically lower) priority than
273+
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
274+
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
275+
* to 4, this confusion does not happen and the behaviour remains the same.
276+
*
277+
* The following assert ensures that the sub-priority bit in the
278+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
279+
* confusion. */
280+
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
281+
ulMaxPRIGROUPValue = 0;
282+
}
283+
else
284+
{
285+
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
286+
}
287+
261288
#ifdef __NVIC_PRIO_BITS
262289
{
263290
/* Check the CMSIS configuration that defines the number of
264291
* priority bits matches the number of priority bits actually queried
265292
* from the hardware. */
266-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
293+
configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS );
267294
}
268295
#endif
269296

@@ -272,7 +299,7 @@ BaseType_t xPortStartScheduler( void )
272299
/* Check the FreeRTOS configuration that defines the number of
273300
* priority bits matches the number of priority bits actually queried
274301
* from the hardware. */
275-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
302+
configASSERT( ulImplementedPrioBits == configPRIO_BITS );
276303
}
277304
#endif
278305

@@ -379,17 +406,17 @@ void xPortSysTickHandler( void )
379406

380407
/* Enter a critical section but don't use the taskENTER_CRITICAL()
381408
* method as that will mask interrupts that should exit sleep mode. */
382-
__asm( " cpsid i");
383-
__asm( " dsb");
384-
__asm( " isb");
409+
__asm( " cpsid i" );
410+
__asm( " dsb" );
411+
__asm( " isb" );
385412

386413
/* If a context switch is pending or a task is waiting for the scheduler
387414
* to be unsuspended then abandon the low power entry. */
388415
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
389416
{
390417
/* Re-enable interrupts - see comments above the cpsid instruction
391418
* above. */
392-
__asm( " cpsie i");
419+
__asm( " cpsie i" );
393420
}
394421
else
395422
{
@@ -450,27 +477,27 @@ void xPortSysTickHandler( void )
450477

451478
if( xModifiableIdleTime > 0 )
452479
{
453-
__asm( " dsb");
454-
__asm( " wfi");
455-
__asm( " isb");
480+
__asm( " dsb" );
481+
__asm( " wfi" );
482+
__asm( " isb" );
456483
}
457484

458485
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
459486

460487
/* Re-enable interrupts to allow the interrupt that brought the MCU
461488
* out of sleep mode to execute immediately. See comments above
462489
* the cpsid instruction above. */
463-
__asm( " cpsie i");
464-
__asm( " dsb");
465-
__asm( " isb");
490+
__asm( " cpsie i" );
491+
__asm( " dsb" );
492+
__asm( " isb" );
466493

467494
/* Disable interrupts again because the clock is about to be stopped
468495
* and interrupts that execute while the clock is stopped will increase
469496
* any slippage between the time maintained by the RTOS and calendar
470497
* time. */
471-
__asm( " cpsid i");
472-
__asm( " dsb");
473-
__asm( " isb");
498+
__asm( " cpsid i" );
499+
__asm( " dsb" );
500+
__asm( " isb" );
474501

475502
/* Disable the SysTick clock without reading the
476503
* portNVIC_SYSTICK_CTRL_REG register to ensure the
@@ -578,7 +605,7 @@ void xPortSysTickHandler( void )
578605
vTaskStepTick( ulCompleteTickPeriods );
579606

580607
/* Exit with interrupts enabled. */
581-
__asm( " cpsie i");
608+
__asm( " cpsie i" );
582609
}
583610
}
584611

portable/CCS/ARM_CM4F/port.c

100644100755
+45-18
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ BaseType_t xPortStartScheduler( void )
238238
#if ( configASSERT_DEFINED == 1 )
239239
{
240240
volatile uint32_t ulOriginalPriority;
241+
volatile uint32_t ulImplementedPrioBits = 0;
241242
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
242243
volatile uint8_t ucMaxPriorityValue;
243244

@@ -269,20 +270,46 @@ BaseType_t xPortStartScheduler( void )
269270

270271
/* Calculate the maximum acceptable priority group value for the number
271272
* of bits read back. */
272-
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
273273

274274
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
275275
{
276-
ulMaxPRIGROUPValue--;
276+
ulImplementedPrioBits++;
277277
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
278278
}
279279

280+
if( ulImplementedPrioBits == 8 )
281+
{
282+
/* When the hardware implements 8 priority bits, there is no way for
283+
* the software to configure PRIGROUP to not have sub-priorities. As
284+
* a result, the least significant bit is always used for sub-priority
285+
* and there are 128 preemption priorities and 2 sub-priorities.
286+
*
287+
* This may cause some confusion in some cases - for example, if
288+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
289+
* priority interrupts will be masked in Critical Sections as those
290+
* are at the same preemption priority. This may appear confusing as
291+
* 4 is higher (numerically lower) priority than
292+
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
293+
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
294+
* to 4, this confusion does not happen and the behaviour remains the same.
295+
*
296+
* The following assert ensures that the sub-priority bit in the
297+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
298+
* confusion. */
299+
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
300+
ulMaxPRIGROUPValue = 0;
301+
}
302+
else
303+
{
304+
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
305+
}
306+
280307
#ifdef __NVIC_PRIO_BITS
281308
{
282309
/* Check the CMSIS configuration that defines the number of
283310
* priority bits matches the number of priority bits actually queried
284311
* from the hardware. */
285-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
312+
configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS );
286313
}
287314
#endif
288315

@@ -291,7 +318,7 @@ BaseType_t xPortStartScheduler( void )
291318
/* Check the FreeRTOS configuration that defines the number of
292319
* priority bits matches the number of priority bits actually queried
293320
* from the hardware. */
294-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
321+
configASSERT( ulImplementedPrioBits == configPRIO_BITS );
295322
}
296323
#endif
297324

@@ -404,17 +431,17 @@ void xPortSysTickHandler( void )
404431

405432
/* Enter a critical section but don't use the taskENTER_CRITICAL()
406433
* method as that will mask interrupts that should exit sleep mode. */
407-
__asm( " cpsid i");
408-
__asm( " dsb");
409-
__asm( " isb");
434+
__asm( " cpsid i" );
435+
__asm( " dsb" );
436+
__asm( " isb" );
410437

411438
/* If a context switch is pending or a task is waiting for the scheduler
412439
* to be unsuspended then abandon the low power entry. */
413440
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
414441
{
415442
/* Re-enable interrupts - see comments above the cpsid instruction
416443
* above. */
417-
__asm( " cpsie i");
444+
__asm( " cpsie i" );
418445
}
419446
else
420447
{
@@ -475,27 +502,27 @@ void xPortSysTickHandler( void )
475502

476503
if( xModifiableIdleTime > 0 )
477504
{
478-
__asm( " dsb");
479-
__asm( " wfi");
480-
__asm( " isb");
505+
__asm( " dsb" );
506+
__asm( " wfi" );
507+
__asm( " isb" );
481508
}
482509

483510
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
484511

485512
/* Re-enable interrupts to allow the interrupt that brought the MCU
486513
* out of sleep mode to execute immediately. See comments above
487514
* the cpsid instruction above. */
488-
__asm( " cpsie i");
489-
__asm( " dsb");
490-
__asm( " isb");
515+
__asm( " cpsie i" );
516+
__asm( " dsb" );
517+
__asm( " isb" );
491518

492519
/* Disable interrupts again because the clock is about to be stopped
493520
* and interrupts that execute while the clock is stopped will increase
494521
* any slippage between the time maintained by the RTOS and calendar
495522
* time. */
496-
__asm( " cpsid i");
497-
__asm( " dsb");
498-
__asm( " isb");
523+
__asm( " cpsid i" );
524+
__asm( " dsb" );
525+
__asm( " isb" );
499526

500527
/* Disable the SysTick clock without reading the
501528
* portNVIC_SYSTICK_CTRL_REG register to ensure the
@@ -603,7 +630,7 @@ void xPortSysTickHandler( void )
603630
vTaskStepTick( ulCompleteTickPeriods );
604631

605632
/* Exit with interrupts enabled. */
606-
__asm( " cpsie i");
633+
__asm( " cpsie i" );
607634
}
608635
}
609636

portable/GCC/ARM_CM3/port.c

100644100755
+32-5
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ BaseType_t xPortStartScheduler( void )
262262
#if ( configASSERT_DEFINED == 1 )
263263
{
264264
volatile uint32_t ulOriginalPriority;
265+
volatile uint32_t ulImplementedPrioBits = 0;
265266
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
266267
volatile uint8_t ucMaxPriorityValue;
267268

@@ -293,20 +294,46 @@ BaseType_t xPortStartScheduler( void )
293294

294295
/* Calculate the maximum acceptable priority group value for the number
295296
* of bits read back. */
296-
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
297297

298298
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
299299
{
300-
ulMaxPRIGROUPValue--;
300+
ulImplementedPrioBits++;
301301
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
302302
}
303303

304+
if( ulImplementedPrioBits == 8 )
305+
{
306+
/* When the hardware implements 8 priority bits, there is no way for
307+
* the software to configure PRIGROUP to not have sub-priorities. As
308+
* a result, the least significant bit is always used for sub-priority
309+
* and there are 128 preemption priorities and 2 sub-priorities.
310+
*
311+
* This may cause some confusion in some cases - for example, if
312+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
313+
* priority interrupts will be masked in Critical Sections as those
314+
* are at the same preemption priority. This may appear confusing as
315+
* 4 is higher (numerically lower) priority than
316+
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
317+
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
318+
* to 4, this confusion does not happen and the behaviour remains the same.
319+
*
320+
* The following assert ensures that the sub-priority bit in the
321+
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
322+
* confusion. */
323+
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
324+
ulMaxPRIGROUPValue = 0;
325+
}
326+
else
327+
{
328+
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
329+
}
330+
304331
#ifdef __NVIC_PRIO_BITS
305332
{
306333
/* Check the CMSIS configuration that defines the number of
307334
* priority bits matches the number of priority bits actually queried
308335
* from the hardware. */
309-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
336+
configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS );
310337
}
311338
#endif
312339

@@ -315,7 +342,7 @@ BaseType_t xPortStartScheduler( void )
315342
/* Check the FreeRTOS configuration that defines the number of
316343
* priority bits matches the number of priority bits actually queried
317344
* from the hardware. */
318-
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
345+
configASSERT( ulImplementedPrioBits == configPRIO_BITS );
319346
}
320347
#endif
321348

@@ -756,4 +783,4 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
756783
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
757784
}
758785

759-
#endif /* configASSERT_DEFINED */
786+
#endif /* configASSERT_DEFINED */

0 commit comments

Comments
 (0)