NVIC Priority on USB OTG Causes UART to Stop

groger57 wrote on Monday, April 29, 2019:

Hello:

I am using HAL on a Cortex M4 processor, with FreeRTOS 9.0. In the HAL setup of the modules, I implemented the FreeRTOS. In both USB OTG and the USART, I added the setup for each:
In USB OTG:
HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0);
and in the USART, which uses DMA:
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);

Before I added the initialization for the USB OTG, the USART DMA/Callback worked fine. After adding it in, it stopped functioning. If I comment out the call to configure USB OTG, the USART DMA functions OK. The odd part is, there is no USB code running, just the initialization for the hardware that includes the call to HAL_NVIC_SetPriority as shown above.
I tried changing the priority on both USB and USART from 5 to 15, and that does not seem to help. I do not see any relationship between these two peripherals that would cause this to happen.

Any idea what might be going on?

rtel wrote on Monday, April 29, 2019:

First - have you determined this is a FreeRTOS issue? Or does the same
happen even if FreeRTOS is not in the project (or, at least, no FreeRTOS
API functions have been called at all - including functions that just
create FreeRTOS objects such as tasks and queues).

groger57 wrote on Monday, April 29, 2019:

I also should have mentioned that when I set up the software in Cube, I selected TIM17 as the sysTick generator. This might be relevant? Also, for now I commented out the USB initialization and found something more specific. In any case, I believe it is related to using FreeRTOS.

I have an SPI flash device I am reading/writing to in polling mode (as it is used infrequently). The call is simple and is preceded and followed by a chip select call. I know it works as I have tested it after HW init, and before FreeRTOS init

HAL_SPI_TransmitReceive(&hspi1, &txBfr, data, 4, 0xFF);

In a running task, and when a certain condition exists I want to update the flash. As soon as I make the call above, every task stops functioning.

So far as I can see, no interrupts are used on the SPI call, but clearly it must need to be handled differently in FreeRTOS. I guess my understanding is not clear - I believed that only hardware that used an interrupt or DMA method had to be set up with specific priority handling. In this case, it cannot be the issue.
What do I need to do to implement accessing a peripheral that is not using interrupts, from FreeRTOS task ?

Thanks again.

rtel wrote on Monday, April 29, 2019:

It is very hard to say just from your descriptions - so just more
questions I’m afraid. First and most important, when you pause the
debugger, what is the code executing? Which IDE are you using? If one
that has a FreRTOS aware plug-in available, when you pause the debugger,
what state does it say the tasks are in? Finally, if you use the
Tracealyzer tool, what does it show the system as doing?

groger57 wrote on Monday, April 29, 2019:

Hi Richard,

I added some code into the hard fault handler and had it break. Please see attached screen cap from the registers on EWARM. There are several registers in red, I see one with a “ISR Pending” bit set. Is it possible SPI is doing something with interrupts even though none are specifically set?
It’s a bit mysterious as all this code worked fine in FreeRTOS using an STM32F4 (CMSIS) . This is using HAL/LL, which has caused me a lot of grief in getting this ported over.

groger57 wrote on Monday, April 29, 2019:

I found some additional information, but it is not clear why it is occuring, but see this is the cause of the fault. In the HAL module “stm32l4xx_hal_spi.c”, at line 1290, I place a breakpoint:
/* Set the Rx Fifo threshold /
if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (initial_RxXferCount > 1U))
{
/
Set fiforxthreshold according the reception data length: 16bit /
CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
}
else
{
/
Set fiforxthreshold according the reception data length: 8bit */
SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
}

On the first call to HAL_SPI_TransmitReceive, I hover the cursor over the “hspi->Init” at line 1290. I can see the initialization values look Ok, as poulated by the spi.c MSP_Init function. After the second call to HAL_SPI_TransmitReceive from the FreeRTOS task, those values have changed to values that pretty clearly are large, overflowed, and seemingly corrupted.
In file main, I use the same access to the handle as the other peripherals, and as used by HAL:
“extern SPI_HandleTypeDef hspi1;”
The handle/struct is used only 2 places, in spi.c for initialization, and in main.c, as I described here. Other peripheral handles I use in FreeRTOS such as ADC and USART are functioning without this problem.

Why would this one blow up in the RTOS task?

groger57 wrote on Monday, April 29, 2019:

And yet another update. I did something that fixes it, but makes little sense. In main, at initialzation, I created a second handle:
SPI_HandleTypeDef myhspi1;

And then assigned the handle set by extern SPI_HandleTypeDef hspi1 to the new one:
myhspi1 = hspi1;

In the RTOS task, I use the handle myhspi1, and it runs without fault. What could be happening with this? So bizarre.

Thanks for taking the time to read and provide feedback this post.

rtel wrote on Monday, April 29, 2019:

Where was hspi1 declared? By which I mean, is it a global variable, on
the stack, or where? If on the stack, which stack?

groger57 wrote on Monday, April 29, 2019:

It is declared in spi.c, as a global, same as the other peripheral handles is declared in Cube. I use the other handles the same way and have had no issue with them.

rtel wrote on Tuesday, April 30, 2019:

Is it the handle itself that is getting corrupted? If so, are you able
to set a data watchpoint to break the debugger when it gets written to?

I would recommend updating your FreeRTOS source files to the very latest
(10.2.0) then ensuring configASSERT() is defined, as the newer the
version of FreeRTOS the more asserts there are in the code to detect
invalid interrupt priorities - which in turn is the main cause of data
corruption on Cortex-M devices.

groger57 wrote on Tuesday, April 30, 2019:

The structure / handle is getting configured in spi.c, and nothing else should be accessing it after. It is loaded with the configuration data in the init, including pointer to the data structure. (on stack) So somehow calling the transmitReceive using the original handle from the task it was getting corrupted. Why a second handle copied from the first doesn’t get corrupted is a mystery. I have a large heap and stack allocation in the linker setup (for the USB) I might try modifying it to see if that changes anything. But again - this is the only peripheral handle impacted. I do run config assert, in this case the hard fault handler grabbed it. Also, I will install 10.2, thanks for this.

BTW - I find it amazing you still find time to answer so many questions, and likely many are trvial or repetitious (like mine) Can’t imagine what it’s like to get by with 3 hours of sleep a night 8) Thanks for being there to support your creation, a terrific product.