Code only runs with the 'debug' build_type, what gives?

When I build my project with the following .ini configuration the code runs fine

[env:nucleo_f446re]
platform = ststm32
board = nucleo_f446re
framework = stm32cube
build_type = debug
build_flags = -O0
build_unflags = -Os

However if I change build_type to release the data seems to be getting corrupted. Essentially I see on my oscilloscope that the interrupts work fine however, the data that I’m trying to send over through SPI is all garbage. I considered it might have something to do with the compiler optimization but it doesn’t seem to change anything.

Suggestions?

What’s the observed vs. expected signal, and what code are you using to do the SPI transaction?

Expected is a series of individual messages
0x01FF
0x02FF
0x03FF
etc…

Observed is hard to explain, but an occasional glitch, some of the transactions go through fine, and others are not in an irregular pattern (if that makes sense) I would say it’s close to a 50/50.

For sending the data I’m using the ST default Hal layer on interrupt basis. The data itself is coming from an array that I’ve made volatile.

The code itself comes down to this line

void SendCommandNoReturn(uint8_t *TX, uint16_t size, uint16_t cs) {
  if ((&hspi1)->Lock == HAL_UNLOCKED) {
    ResetPin(GPIOA, cs);
    HAL_SPI_Transmit_IT(&hspi1, TX, size);
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
  SetPin(GPIOA, CS_0);
}

If there’d be a way to properly check whether TX is actually filled as supposed to that’d be neat but since it works while debugging I don’t see a way how :slight_smile:

Inspecting SDK-internal objects like this seems weird. The function HAL_SPI_Transmit_IT already does the locking.

What happens when omit this check?

Sorry for the late response, I wasn’t aware it did that internally, so it’s probably better to have gotten rid of it regardless, thanks for that!

The behaviour did change after removing it, the first part
0x01
0x02
etc
seems to be correct, however the 2nd byte is not being send over correctly all the time, only the first 2-3 of 8 transmits are good about 40% of the time.
The chipselect, clock etc are all working just fine but the data seems to be getting scrambled somehow.

Can you create a more minimal test-firmware that uses the regular polling mode of SPI (not IT and not DMA) as e.g. in STM32CubeF4/Projects/STM32F4-Discovery/Examples/SPI/SPI_FullDuplex_ComPolling at master · STMicroelectronics/STM32CubeF4 · GitHub? That could narrow it down whether it’s because it’s being used in interrupt mode or not.

I can swap interrupts out with polling quite easily, and it indeed works fine when using polling (with my firmware on top of it). I just swapped the interrupt out for the polling alternative function. Is it somehow timing related?

So I managed to find a ‘solution’ for it, essentially I had my SPI baudrate prescaler quite high, 256, I then lowered it to 8 and the issue dissapeared.

1 Like