AnsweredAssumed Answered

SPI Slave missing interrupts (NUCLEO-F401RE)

Question asked by F. Pabst on Jun 12, 2018

Hi,

im trying to implement a basic SPI full-duplex slave using HAL (the reason to use HAL here is that i have to switch to another STM MCU later).

 

The biggest problem is that the slave sometimes doesn't seem to react to interrupts in time / at all.

 

As Master i use a NUCLEO-F429ZI and as Slave a NUCLEO-F401RE.

 

The slave setup is being done by CubeMX (file attached).

 

I had a SPI full-duplex implemtation with several commands up and running already - but sadly it just works in ~95%  of time. I broke down the entire implementation I had before to:

 

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
    HAL_GPIO_TogglePin(ERROR_GPIO_Port, ERROR_Pin);
    uint8_t txData = 0x01;
    uint8_t rxData = 0x00;
    HAL_SPI_TransmitReceive_IT(&hspi2, &txData, &rxData, 1);
    HAL_GPIO_TogglePin(ERROR_GPIO_Port, ERROR_Pin);
}

 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

  // only CS pin is connected - all other EXTIs are tied low

  // so this function should mirror the CS pin - CS is just a DUMMY implentation as we use HW CS atm
  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM3)
  {
    sensor_read_request = 1; // is unused atm
  }
}

 

with HAL_SPI_TransmitReceive_IT(&hspi2, &txData, &rxData, 1) being called once in the beinning before main loop.

 

Master is continuously sending 1 byte, reading 1 bytes on the SPI bus using some µs delay inbetween for the slave being able to respond / TX.

 

uint8_t cmd = 0x02;

uint8_t data = 0x00;

uint8_t length = 1;

 

void SpiBusRead(uint8_t cmd, uint8_t* data, uint16_t length) {
    CS_Set();
    delayUS_DWT(cmdDelay);
    HAL_SPI_Transmit(&hspi4, &cmd, 1, HAL_MAX_DELAY);
    for (int ii = 0; ii < length; ii++) {
        delayUS_DWT(cmdDelay);
        HAL_SPI_Receive(&hspi4, &data[ii], 1, HAL_MAX_DELAY);
    }
    delayUS_DWT(cmdDelay);
    CS_Reset();
    delayUS_DWT(cmdDelay);
}

 

So in my Logic capture the slave should toggle LD2_Pin ech time the CS line is pulled. The ERROR_Pin should be toggled each time an SPI byte is received.

 

On the Master side I also have an ERROR_pin wich toggles when I detect something didn't work (further explanation coming later)

 

I tried both the HW CS and the SW CS for the slave - same problems on both [SW CS was implemented by using EXTI on CS PIN and use SET/CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_SSI) ]

 

1. Worst case: EXTI  + SPI interrupt is missing:

2. Here we can see how often this error occurs - when doing the 2 byte thing continusouly

.3 In a more complex scenario sometimes just the SPI interrupt is missing:

Since this was a 2 byte read request - the answer in being send 1 byte too late and leads to corrupted data (0x0001 indead of 0x0101)

 

4. This also might happen in between:

 

5. Or just the EXTIs are skipped andd SPI is totaly fine:

 

All in all it seems to me something is blocking interrupts - or the HAL might have some hickups.

 

Any help appreciated.

 

Regards

Attachments

Outcomes