2025-09-28 3:25 PM
L562 processor. SPI1. Blocking mode. Two sequential writes, second write variably returns error.
code:
// uses CS if USE_CS is set to CS_ACTIVE (default)
// CS is not used if USE_CS is set to CS_INACTIVE
uint32_t HAL_SPI::Send(
uint8_t* cmdptr,
uint32_t cmd_count,
uint8_t* dataptr,
uint32_t data_count,
bool USE_CS,
enum SPI_TRANSFER_MODE Override)
{
enum SPI_TRANSFER_MODE NEW_mode = OUT_mode;
int error_code;
// int old_divisor;
// ********************************** check input parameters***********************************
// need to check overrides
switch (Override)
{
case SPI_DMA: // TRANSMIT IS DMA FROM BUFFER, RECEIVE IS IRQ QUEUE (MAY CHANGE)
case SPI_IRQ: // TRANSMIT IS IRQ DRIVEN
case SPI_BLOCKING: // TRANSMIT AND RECEIVE ARE BYTE BLOCKING
{
NEW_mode = Override;
break;
}
default:
{
NEW_mode = OUT_mode;
// leave mode as is, cannot override
}
}
switch (NEW_mode)
{
case SPI_BLOCKING: // TRANSMIT AND RECEIVE ARE BYTE BLOCKING
{
time_start = _MICROSECOND_TIMER.Instance->CNT;
// always semaphore protected
if (!dedicated) xSemaphoreTake(busy, portMAX_DELAY);
// direct call to STMICRO driver, blocking mode
hspi->Instance->CR1 &= ~SPI_BAUDRATEPRESCALER_256;// reset to highest baudrate
hspi->Instance->CR1 |= transmit_divisor;
if (RESET.port != nullptr) RESET.set(); // make sure reset if high
if (USE_CS) RESET_CS(); // CS low if needed
/*
HAL_OK = 0x00,
HAL_ERROR = 0x01,
HAL_BUSY = 0x02,
HAL_TIMEOUT = 0x03
*/
if ((cmdptr != nullptr) && (cmd_count != 0))
{
// command pointer says to send data with A0 down
if (A0.port != nullptr) A0.reset();
result = HAL_SPI_Transmit(hspi, cmdptr, cmd_count, timeout);
// place to add delay if available
}
if ((dataptr != nullptr) && (data_count != 0))
{
// command pointer says to send data with A0 down
if (A0.port != nullptr) A0.set();
result = HAL_SPI_Transmit(hspi, dataptr, data_count, timeout);
// place to add delay if available
// while (hspi->State == HAL_SPI_STATE_BUSY_TX)
// {
// HAL_Delay(1);
// }
}
if (USE_CS) SET_CS(); // CS high if needed
// error reporting
ERROR_CODE = hspi->ErrorCode;
ERROR_REASON = (enum COMM_ERROR_TYPE) ERROR_CODE;
operations++;
// record errors if needed
switch (result)
{
case HAL_ERROR: //= 0x01U,
{
fail++;
break;
}
case HAL_BUSY: //= 0x02U,
{
fail++;
break;
}
case HAL_TIMEOUT: //= 0x03U
{
fail++;
break;
}
case HAL_OK:
{
// was OK
succeed++;
break;
}
}
// return semaphore for next operation
if (!dedicated) xSemaphoreGive(busy);
time_stop = _MICROSECOND_TIMER.Instance->CNT;
delta_time = time_stop - time_start;
break;
}
Using optimization for debug, this code works perfectly.
Using G0 (no optimization), the code fails either at line #70 after executing line #61 (write two bytes), or the second call to the routine at line #61 (writing one byte per call).
This is a display driver routine. Using version 1.19.0
The rest of the code in this routine simply returns HAL_OK.
2025-09-29 6:24 AM
Hello @Harvey White
The issue stems from your custom application code, not from CubeMX or the IDE.
It is most likely related to timing or the SPI peripheral not being ready between sequential writes and it becomes apparent when changing the code optimization level due to differences in execution speed.
To address this, add small delays after toggling the CS and A0 pins, and ensure the SPI state is ready before each transfer.
THX
Ghofrane
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.