2018-06-12 02:11 AM
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