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>
This commit is contained in:
kar-rahul-aws 2023-03-23 15:06:33 +05:30 committed by GitHub
parent 9488ba22d8
commit 99797e14e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 826 additions and 387 deletions

73
portable/GCC/ARM_CM4F/port.c Normal file → Executable file
View file

@ -251,11 +251,11 @@ static void prvTaskExitError( void )
void vPortSVCHandler( void )
{
__asm volatile (
" ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */
" ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n"/* Restore the task stack pointer. */
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
@ -274,17 +274,17 @@ static void prvPortStartFirstTask( void )
* would otherwise result in the unnecessary leaving of space in the SVC stack
* for lazy saving of FPU registers. */
__asm volatile (
" ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n"/* Set the msp back to the start of the stack. */
" mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */
" msr control, r0 \n"
" cpsie i \n"/* Globally enable interrupts. */
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc 0 \n"/* System call to start first task. */
" svc 0 \n" /* System call to start first task. */
" nop \n"
" .ltorg \n"
);
@ -305,6 +305,7 @@ BaseType_t xPortStartScheduler( void )
#if ( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue;
@ -336,20 +337,46 @@ BaseType_t xPortStartScheduler( void )
/* Calculate the maximum acceptable priority group value for the number
* of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ulImplementedPrioBits++;
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
}
if( ulImplementedPrioBits == 8 )
{
/* When the hardware implements 8 priority bits, there is no way for
* the software to configure PRIGROUP to not have sub-priorities. As
* a result, the least significant bit is always used for sub-priority
* and there are 128 preemption priorities and 2 sub-priorities.
*
* This may cause some confusion in some cases - for example, if
* configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
* priority interrupts will be masked in Critical Sections as those
* are at the same preemption priority. This may appear confusing as
* 4 is higher (numerically lower) priority than
* configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
* have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
* to 4, this confusion does not happen and the behaviour remains the same.
*
* The following assert ensures that the sub-priority bit in the
* configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
* confusion. */
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
ulMaxPRIGROUPValue = 0;
}
else
{
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
}
#ifdef __NVIC_PRIO_BITS
{
/* Check the CMSIS configuration that defines the number of
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS );
}
#endif
@ -358,7 +385,7 @@ BaseType_t xPortStartScheduler( void )
/* Check the FreeRTOS configuration that defines the number of
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
configASSERT( ulImplementedPrioBits == configPRIO_BITS );
}
#endif
@ -453,15 +480,15 @@ void xPortPendSVHandler( void )
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"
" \n"
" stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */
" str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n"
@ -473,12 +500,12 @@ void xPortPendSVHandler( void )
" msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n"
" \n"
" ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"
" \n"
@ -772,10 +799,10 @@ static void vPortEnableVFP( void )
{
__asm volatile
(
" ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */
" ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */
" ldr r1, [r0] \n"
" \n"
" orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */
" orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */
" str r1, [r0] \n"
" bx r14 \n"
" .ltorg \n"