2021-09-04 10:06 AM
I have a STM32L412 on a nucleo board. In the debugger, the processor gets a hard fault after a random period of time. I have narrowed this down to when my app writes to the SPI DR register. Most of the time, this works ok (I can drive a TFT display), but sometimes for no apparent reason, it crashes. It seems to happen more often when I run the sysclk at 72Mhz. I need to run it this fast in order to get the baud rate divisor absolutely spot on for a UART device I need to run at 115200.
I have tried waiting for the SPI Tx fifo to be empty before I attempt to send, but still no joy. Is there a tried and trusted method of running SPI at this sysclk speed? I have tried using both the HAL_ and LL_ libraries.
2021-09-04 10:56 AM
You're going to want to look at the faulting instructions and registers in a disassembly view, and understand what side of the transaction this is occuring.
ie pulling the data from some pointer, or the write to the SPI->DR itself.
Perhaps the write causes and interrupt nearly instantaneously, and that's failing due to some buffering issue, the instance data, or stack full/corruption.
Make sure the flash wait states are appropriate for the speed you are clocking the MCU
2021-09-04 11:42 AM
Also try disconnecting whatever you have connected to that SPI.
JW
2021-09-04 12:04 PM
I have cut down the code to narrow down the problem: I know it is definitely not a problem accessing any of my data, as I try as a test just sending a constant value (the 0x02 in the code below). Interestingly, a value of 0x02 still crashes the stm. A value of 0x00 does not, which is wierd beyond belief. The same happens if I have the SPI slave hardware connected or not.
My spi1 is configured as a transmit only master, 8 bits size, no nssp, and with a prescaler of 256 so the spi baud rate is 292.968KBits/s.
Tesla - what exactly do you mean by "flash wait states" ?
void ST7735_WriteCommand(uint8_t cmd)
{
HAL_GPIO_WritePin(DC_PORT, DC_PIN, GPIO_PIN_RESET);
SET_BIT(SPI1->CR1, SPI_CR1_SPE);
while (!(SPI1->SR & SPI_SR_TXE));
// Send bytes over the SPI
SPI1->DR = 0x02;//cmd;
// Wait until the transmission is complete
while (SPI1->SR & SPI_SR_BSY);
while (!(SPI1->SR & SPI_SR_TXE));
}
2021-09-04 01:07 PM
> Interestingly, a value of 0x02 still crashes the stm.
What exactly do you mean by "crashes"? Where does the program counter go?
> Tesla - what exactly do you mean by "flash wait states" ?
JW
2021-09-04 06:43 PM
Have you checked your stack size?
2021-09-05 12:19 AM
Crashes: sometimes debugger shows stopped in hard fault handler, and calling stack correctly points back to my line of code. Sometimes shows hard fault handler, calling stack pointing back to some random point of code, not always valid code. Sometimes, debugger gets disconnected so there's no way of telling, although cpu looks halted as my timer-interrupt-driven led flasher has stopped.
The DR register is first written in my app three seconds after app startup. Before this point, the app behaves correctly. This is plenty of time for the stm32ide-generated code to have changed any clock frequencies.
Stack size is fine. How would writing a 0x00 (works) or a 0x02 (crashes) to DR be dependent on stack size?
2021-09-05 12:28 AM
Isn't MOSI pin connected to some onboard circuit on the Nucleo board?
JW