cancel
Showing results for 
Search instead for 
Did you mean: 

SPI Slave missing interrupts (NUCLEO-F401RE)

F. Pabst
Associate
Posted on June 12, 2018 at 11:11

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:

0690X0000060LDwQAM.png

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

0690X0000060LE1QAM.png

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

0690X0000060LEQQA2.png

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:

0690X0000060LEVQA2.png

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

0690X0000060LEaQAM.png

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

Any help appreciated.

Regards

0 REPLIES 0