[solved] SPIF gets cleared if ANY interrupt happens?
Posted: Fri May 31, 2019 6:25 am
I got PORTB pin 4 (SS) set to output high (need to do that anyway for the video output chip) as to not switch to slave mode automatically already.
I got SPIE cleared to disable SPI interrupts.
The MSTR bit is still set so it's seemingly not an SS pin issue. (Unless CE pin on the AD725 does funky stuff when hblank is triggered)
I don't have an SD card plugged in, I'm SPI-ing into the void.
I can do SPI transfers fine if I completely disable interrupts during the SPI transfers. For obvious reasons I don't want to do that.
But if an unrelated timer interrupt happens between starting the transfer and reading the SPIF flag, the SPIF flag gets cleared even with SPI interrupts disabled.
That doesn't seem to be documented in the ATmega644 manual
I started messing with the code to diagnose why the transfers randomly stopped after a while so I added an extra long loop to force the issue to happen:
Used to be just a
and that randomly got stuck. With the for-loop it guarantees an interrupt happens between the two and SPIF is never seen as set.
I can't find info on this behaviour.
Is that a CPU bug? Am I missing something else?
I guess I'll have to use a timer register instead and just assume the SPI transfer is done when the time runs out. Which is fine since I'm the master. It's not very pretty tho.
I got SPIE cleared to disable SPI interrupts.
The MSTR bit is still set so it's seemingly not an SS pin issue. (Unless CE pin on the AD725 does funky stuff when hblank is triggered)
I don't have an SD card plugged in, I'm SPI-ing into the void.
I can do SPI transfers fine if I completely disable interrupts during the SPI transfers. For obvious reasons I don't want to do that.
But if an unrelated timer interrupt happens between starting the transfer and reading the SPIF flag, the SPIF flag gets cleared even with SPI interrupts disabled.
That doesn't seem to be documented in the ATmega644 manual
Emphasis mine. It should only automatically clear it if the corresponding interrupt happens.SPIF is cleared by hardware when executing the
corresponding interrupt handling vector. Alternatively, the SPIF bit is cleared by first reading the
SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).
I started messing with the code to diagnose why the transfers randomly stopped after a while so I added an extra long loop to force the issue to happen:
Code: Select all
SPDR = value;
for(;--timeout;){ //long 64K loop to have an interrupt happen between SPDR and SPSR check
++__vram_start[0];
asm volatile("nop" : : :"memory");
}
while(true){
byte s = SPSR;
++__vram_start[2];
if(s & 0x80){
break;
}
//...
Code: Select all
SPDR = value;
while(!(SPSR & 0x80));
return SPDR;
I can't find info on this behaviour.
Is that a CPU bug? Am I missing something else?
I guess I'll have to use a timer register instead and just assume the SPI transfer is done when the time runs out. Which is fine since I'm the master. It's not very pretty tho.