I am bringing up STM32F446 in IAR8.50, FreeRTOS 10.2.0
I have numerous projects running in this environment using STM32F401, F412, F427. This is the first time for F446.
configASSERT in xPortStartScheduler fails verifying configPRIO_BITS.
I see a similar problem described here :
[Bringing up a SAM4S with Keil and FreeRTOS, Failure in XPortStartScheduler with configPRIO_BITS check]
I can clearly see where the problem comes from. The sequence that writes 0xFF to NVIC_IPR0 and then reads back the value, that is supposed to show only the active bits, does not work as intended, the read returns the same 0xFF:
/* Determine the number of priority bits available. First write to all
possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
As a result the ‘while’ loop below wraps around and the assert that follows it fails.
This seems to be a hardware problem. My question is - am I the only one who sees this, has anybody seen this before?
This may be an optimization issue; the compiler may believe that input and output must be the same and therefore “optimize” away the read. Can you post the generated assembly code?
That was my first guess, but no, this is IAR we are talking about, it does not optimize “volatile” data access.
// 245 volatile uint32_t ulOriginalPriority;
// 246 volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
??xPortStartScheduler_1:
LDR.N R4,??DataTable7_4 ;; 0xe000e400
// 247 volatile uint8_t ucMaxPriorityValue;
// 248
// 249 /* Determine the maximum priority from which ISR safe FreeRTOS API
// 250 functions can be called. ISR safe functions are those that end in
// 251 "FromISR". FreeRTOS maintains separate thread and ISR API functions to
// 252 ensure interrupt entry is as fast and simple as possible.
// 253
// 254 Save the interrupt priority value that is about to be clobbered. */
// 255 ulOriginalPriority = *pucFirstUserPriorityRegister;
LDRB R0,[R4, #+0]
STR R0,[SP, #+4]
// 256
// 257 /* Determine the number of priority bits available. First write to all
// 258 possible bits. */
// 259 *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
MOVS R0,#+255
STRB R0,[R4, #+0]
// 260
// 261 /* Read the value back to see how many bits stuck. */
// 262 ucMaxPriorityValue = *pucFirstUserPriorityRegister;
LDRB R0,[R4, #+0]
STRB R0,[SP, #+0]
It might be a bus timing issue, a read access to the IPR register follows the write immediately.
I think there is a problem elsewhere. STM32F446 is just another variant of a STM32F4 as your other STM32F4 MCUs . They should be equal with regards to NVIC.
Did you check the erratas and the basic (clock) MCU setup ?
Along the lines of what Hartmut wrote: Is this the first register access in your startup sequence? If should not be because normally there is a lot of MCU initialization going on before that. Do all other registers read back correctly?
Richard, that was a false alarm after all. That behavior was found on a remote setup. I can not reproduce it on my local setup and after some careful cleaning the remote setup now builds and runs correctly.
Thank you so much
-SN