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.