2020-09-11 05:32 AM
Hello all,
I have serious problem with SPI2 on STM32H745 using interrupts.
First I try system with polling:
uint8_t Send(data)
{
*((uint8_t*)&SPI2->TXDR) = data;
while((SPI2->SR & SPI_SR_RXP) == 0)
{
}
return *((uint8_t*)&SPI2->RXDR);
}
All works as expected, I send correctly, receive what I expect.
But polling is not the solution, so I set up system to fire interrupt when byte is available:
uint8_t Send(data)
{
*((uint8_t*)&SPI2->TXDR) = data;
SPI2->IER = SPI_IER_RXPIE;
waitSignal();
return *((uint8_t*)&SPI2->RXDR);
}
void SPI2_IRQHandler(void)
{
SPI2->IER = 0;//disable interrupt
sendSignal();
}
What happens is that system does not care that I disabled all SPI interrupts and it goes to isr vector constantly! And system stalls ofcourse.
There is notice in errata about spurious TXP. So maybe they are related?
So I tried a work around:
uint8_t Send(data)
{
*((uint8_t*)&SPI2->TXDR) = data;
NVIC_EnableIRQ(SPI2_IRQn);
SPI2->IER = SPI_IER_RXPIE;
waitSignal();
return *((uint8_t*)&SPI2->RXDR);
}
void SPI2_IRQHandler(void)
{
//
SPI2->IER = 0;//disable interrupt
NVIC_DisableIRQ(SPI2_IRQn);
sendSignal();
}
Now system fires one interrupt, disable works, BUT I get nonsence in RXDR.
I put osciloscope to work and see, that RXP flag is fired too early! And ofcourse this makes bad data in RXDR.
My question is: how should it work then? Is there another workaround? I need only 1 byte, should I use DMA for this???
2020-09-11 06:24 AM
What do waitSignal and sendSignal do?
2020-09-11 06:44 AM
Waits/Sends signal about finished interrupt.
2020-09-11 06:49 AM
This is errata info about TXP:
2.10.3 TXP interrupt occurring while disabled
Description
SPI/I2S peripheral is set to its default state when disabled (SPE = 0). This flushes the FIFO buffers and resets their occupancy flags. TXP and TXC flags become set (the latter if the TSIZE field contains zero value), triggering interrupt if enabled with TXPIE or EOTIE bit, respectively. The resulting interrupt service can be spurious if it tries to write data into TXFIFO to clear the TXP and TXC flags, while both FIFO buffers are inaccessible (as the peripheral is disabled).
Workaround
Keep TXP and TXC (the latter if the TSIZE field contains zero value) interrupt disabled whenever the SPI/I2S peripheral is disabled.
But I never enabled TXPIE, nor EOTIE.
2020-09-11 07:16 AM
Okay, that didn't explain very much. I don't know what "waits signal about finished interrupt" means.
If waitSignal is blocking, then this is no better than polling mode. If it's nonblocking, then this won't work since you read DR immediately afterwards. Maybe this is the source of your "nonsense" data.
Doesn't seem like the errata is relevant here.
2020-09-11 07:29 AM
Because the code itself does not matter. (it is blocking ofcourse, waits RTOS signal)
I disable interrupt enable control bit in ISR vector, but they still fire up? Is this correct way of MCU to operate (first time see such behaviour in my 15 year experience)? Nonsence!
And even with interrupt firing in the middle of transmission, when there is no byte yet. How can this be correct? Maybe I do something wrong, and comunity could help.
2020-09-11 08:23 AM
Here are those oscilograms
I make manual CSN, send 3 bytes
First is RXP polling. All correct
Next is Changing interrupt control bit in ISR (IER = 0), 1 was byte sent, system stall repeating SPI interrupt routine multiple times! Totally unexpected.
FInal is where I disable NVIC SPI2 interrupt in ISR. First byte is read after full transmission, next interrupts fire in the middle of transmission! How can it be?
2020-09-14 12:35 AM
nobody works with STM32H7 + SPI?