Electronics > Microcontrollers

STM32 stuck (freeze) after using SPI transfer in interrupt mode

(1/3) > >>

nishantnidaria:
Greetings!

I am using an STM32G030C8T6 on a custom PCB everything seems to be working fine but "sometimes" randomly my MCU gets stuck after i send (using SPI) battery voltage to the Master device, it happens randomly there's no pattern i could follow. |O

Note: my STM32 is a slave device and the master device is a Raspberry Pi

STM32 receives data from raspberry pi in while loop using the following function/code:


--- Code: ---void SPI_Receive_Commands(void)
{

while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
  {
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);

if(spi_buf[0] == 'v') // Battery voltage function
{
memset(spi_buf,'*',10);
Battery_Voltage();
HAL_GPIO_WritePin(GPIOA, Voltage_Ready_Pin, GPIO_PIN_SET); // Indicating Raspberry pi that the transmission is starting
HAL_SPI_Transmit_IT(&hspi1, (uint8_t *)batteryVoltage, 6); // Sending voltage (e.g., 13.54)
HAL_SPI_Transmit(&hspi1, (uint8_t *)"v", 1, 100); // Sending the last character 'v' to finish transmission
HAL_GPIO_WritePin(GPIOA, Voltage_Ready_Pin, GPIO_PIN_RESET); // Indicating Raspberry pi that the transmission has finished
printmsg("Sending battery voltage\r\n");
}
  }
}
--- End code ---

Thank you in advance for your help and guidance!  :)

nishantnidaria:
Yes when i say interrupt mode i only meant for the transmission part,

I don't have a mechanism to make sure first call has finished transmitting before using hspi1 again. The sending part only stops after sending the character 'v' and then pulling the GPIO low again.

I used _IT function because i am sending withing the receive loop.

Yes SS pin going to the peripheral is actually toggling as expected.

nishantnidaria:
Adding a HAL_Delay(1000) between these two will help MCU not get stuck anymore ?

something like this:


--- Code: ---HAL_SPI_Transmit_IT(&hspi1, (uint8_t *)batteryVoltage, 6); // Sending voltage (e.g., 13.54)
HAL_Delay(1000);
      HAL_SPI_Transmit(&hspi1, (uint8_t *)"v", 1, 100); // Sending the last character 'v' to finish transmission
--- End code ---

Siwastaja:
It doesn't help that ST's documentation,
https://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32F439xx_User_Manual/group__spi__exported__functions__group2.html#gafbb309aa738bb3296934fb1a39ffbf40

- title says "user manual", does not actually document anything.

"Transmit an amount of data in non-blocking mode with Interrupt." is the full description of the function, no instructions let alone an example how to use it - go figure. So we can only guess.

Construct the full packet first, do not try to append using two transmit function calls; just use HAL_SPI_Transmit once since apparently you are fine with the blocking call. If you call transmit function twice, you probably "should" wait for the the first to finish before the second, but since this is undocumented, I don't know.

Assuming HAL_SPI_Transmit returns only after the transmission is fully completed (full description in the manual: "Transmit an amount of data in blocking mode. "), that one works as it should, but for the interrupt version, you should write an interrupt handler that waits for the completion. There probably is some HAL function you should call in the ISR, but since the official documentation does not document this, it's beyond anyone's guess.

I would hazard a guess there is a separate document, the actual HAL user manual, titled something different from user manual. You should try to find this documentation and read it to understand how to use the HAL functions.

My recommendation is to use SPI bare metal, bypassing these extra layers of complications, replacing them with other complications.

AndyC_772:
It's timing, again.

You're:

- indicating to the Rpi that data is available
- then, bearing in mind the Rpi is free to act upon that indication at any time, preparing a response and entering a loop that will send it to the SPI port

This can't work reliably, because:

- the Rpi CPU is much faster than the STM32, so it can quite reasonably be expected to initiate an SPI read before the first byte is actually in the Tx shift register, and
- your loop must guarantee to keep up with SPI reads, which means it needs to be tight, fast, and have interrupts disabled

You need DMA for this. Prepare the response, store it in memory, set up a DMA channel to transmit it via SPI. Then, and only then, raise the flag to the Rpi.

I agree that the HAL isn't really beneficial here - it's just a layer of obfuscation over and above the underlying hardware, which you need to know all about anyway.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod