2021-09-16 08:41 AM
Hello,
I am using an STM32WL55CC as SPI-Slave to read data from an SPI-master (1 master, 1 slave).
I have an SPI master that is talking occassionaly and I'm waiting for a message to start with a specific start-byte (0x3A) until I start reading a chunk of 60 Bytes.
If I'm polling the SPI line until I see the start-byte and then go ahead and read the rest of the message everything works fine. However, if I trigger the SPI line through an interrupt on the hardware NSS line the data transfer fails after reading the first 3 Bytes and I get an HAL_TIMEOUT returned.
This is the code I am using:
Initialization of SPI:
SPI_INIT()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);
//HAL_NVIC_EnableIRQ(EXTI4_IRQn); // ENABLE IN CASE OF INTERRUPT BASED TRIGGER
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
SPI RX-Routine:
uint8_t rx[100] = {0};
uint8_t spiRxFlag = 0;
void SPI_RX()
{
if(HAL_SPI_Receive(&hspi1, rx, 1, 1) == HAL_OK && rx[0] == 0x3A){
spiRxFlag = 1;
}
if(spiRxFlag){
HAL_SPI_Receive(&hspi1, rx+1, 60, 5);
spiRxFlag=0;
}
}
If I do it this way, reception works with no problem:
while(1)
{
SPI_RX();
}
Now, if I try to trigger SPI_RX() in the interrupt callback (after enabling the interrupt in SPI_INIT() line 16) the reception fails after 3 correct and 1 erroneous byte with an HAL_TIMEOUT.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
SPI_RX();
}
I don't know what is happening here, since I am using the same function to receive data and would be really grateful if someone's got an idea whats going wrong.
If you think you'll need more information I'll be happy to provide that.
Best,
Julius
2021-09-16 08:49 AM
Probably the master is sending data before the slave is ready. In the polling configuration, it's always listening, whereas the IT configuration has some setup time.
Be careful about calling blocking functions in interrupts.
2021-09-16 08:55 AM
I was thinking about that too. But why do I still receive the start-byte and the following 3 bytes correctly and only then it stops working?
About the blocking function in interrupt:
Isn't that ok since the function call is a callback in the isr and the interrupt flags are cleared and ready again?
2021-09-16 09:04 AM
> Isn't that ok since the function call is a callback in the isr and the interrupt flags are cleared and ready again?
You're calling it from within an interrupt which has the highest possible priority (0). That means SysTick isn't getting handled, which HAL functions rely upon for timeout calculation. I don't see how it could be returning HAL_TIMEOUT under that scenario. Could be missing something.
The interrupt flags aren't the concern.
2021-09-16 09:37 AM
You're correct, that's indeed something I should look at closer... It definitely raises a timeout but maybe it still has something to do with the blocking call.
Will only be able to work on it again on Tuesday but thank you already for the idea.