Frequency Switching STM32F

marting2015 wrote on Monday, January 19, 2015:

Opps… I just read the comments, it tells me what might be the problem… the GDB window was small and I didn’t look…

	/* *** NOTE ***********************************************************
	If you find your application is crashing here then likely causes are:
		1) Stack overflow -
		   see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
		2) Incorrect interrupt priority assignment, especially on Cortex-M3
		   parts where numerically high priority values denote low actual
		   interrupt priorities, which can seem counter intuitive.  See
		   configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
		3) Calling an API function from within a critical section or when
		   the scheduler is suspended, or calling an API function that does
		   not end in "FromISR" from an interrupt.
		4) Using a queue or semaphore before it has been initialised or
		   before the scheduler has been started (are interrupts firing
		   before vTaskStartScheduler() has been called?).
	See http://www.freertos.org/FAQHelp.html for more tips, and ensure
	configASSERT() is defined!  http://www.freertos.org/a00110.html#configASSERT
	**********************************************************************/

Using STM32F4 with FreeRTOS 8.1, and trying to dynamically switch frequency.

Background: I can setup the target to run at any desired frequency and the target runs fine. In particular I am using 12 and 48 MHz. Selecting either of those two frequencies and doing a cold boot, the target runs fine. However if I switch frequency, the target runs for only a brief time and fails. Note that at either frequency I keep the peripheral bus clock constant at 12MHz, to avoid having to reconfigure peripherals.

I created a non-FreeRTOS build and used the same frequency switching code, and the target works fine. Note that this build is very simplified, no tasks, and no interrupts, but it does use the uart for debugging (similar to the FreeRTOS build).

The frequency switching implementation looks like this,

taskENTER_CRITICAL(); 
// run the switch frequency code here 
taskEXIT_CRITICAL();

The STM32 has a clock management library, and I use the HAL_RCC_ClockConfig() api to switch frequencies. This api also manages the systick, to keep it at 1ms.

Failure: After the frequency switch, the target “runs” for a brief time before it seems to halt. After the frequency switch, the target has all tasks blocked waiting for an event. If I press a button, or send a command thru uart, that event will partially process before the target halts. Sometimes the target will actually process more than one event before the halt.

Using GDB I can pause the target, and it shows that the target is in an infinite loop at this line, from list.c, vListInsert(), line 159.

for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. /
{
/
There is nothing to do here, we are just iterating to the
wanted insertion position. */
}

rtel wrote on Tuesday, January 20, 2015:

Provided the tick frequency remains the same I can’t think of any reason why the RTOS would care what frequency the core was running at.

Do you have configASSERT() defined? Maybe that would highlight where it goes wrong before you get stuck in the loop.

Where is the frequency switch code executed from? Is it trying to use any resources that the RTOS is using? Systick for example - I think some of the ST libraries require their own handler which then chains with the FreeRTOS handler.

Regards.

marting2015 wrote on Tuesday, January 20, 2015:

Thank you for the comment.

Yes, configASSERT() is defined, it will toggle an LED. I have seen configASSERT() called in other circumstances, so I believe it to be working. But in this case, its not being triggered.

The frequency switching code I am 99% sure is not using any FreeRTOS resources… I am calling into the STM HAL library, with HAL_RCC_ClockConfig() and HAL_RCC_OscConfig(). These functions poke registers.

Of the 4 reasons for the loop to get stuck, I have ruled out #1 and #4. #3 I am 95% sure is not happening. But #4, I am not sure how to prove. The failure is 100% reproducible. I might have some random interrupts from other components happening, but I would assume in some cases there would be no interrupt and the target would “work”.

I will keep plugging away…

marting2015 wrote on Tuesday, January 20, 2015:

Update, Within the HAL_RCC_ClockConfig() function there is a call to,
HAL_InitTick(TICK_INT_PRIORITY);

If I comment out that line, the target seems to behave, although now the systick interrupt is at the wrong frequency. There would seem to be some coupling between the HAL tick and the FreeRTOS kernel that is the root cause of the issue… this is what the commenter above suspected…

rtel wrote on Tuesday, January 20, 2015:

I think in STM32Cube ST install an interrupt handler for the Systick
that performs the processing necessary for their drivers, then call the
FreeRTOS handler, effectively chaining the two. In a FreeRTOS
application it would normally be the other way around - the FreeRTOS
tick hook would be used to call third party code.

Does HAL_InitTick() try to install a new handler? Or change the vector
base register? Those could cause you problems.

Otherwise you could leave the call commented out then re-configure the
tick interrupt yourself. You will find the code necessary in whichever
port.c file you are using. The function is normally called
prvSetupTimerInterrupt(), or something similar.

marting2015 wrote on Tuesday, January 20, 2015:

It seems to be a priority issue. STM HAL wants to set the sys tick int priority to 0 (highest priority), whereas FreeRTOS wants to set the priority to 15 (lowest priority). The function to re-init the systick interrupt frequency/priority is a __weak function, so I have overridden and I remove the code that set the priority. This seems to work. It also violates comments in HAL where they indicate they need priority 0 for systick for some of the HAL driver…