[solved] SPIF gets cleared if ANY interrupt happens?

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
rv6502
Posts: 25
Joined: Mon Feb 11, 2019 4:27 am

[solved] SPIF gets cleared if ANY interrupt happens?

Post by rv6502 » 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
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).
Emphasis mine. It should only automatically clear it if the corresponding interrupt happens.

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;
		}
		//...
		
Used to be just a

Code: Select all

SPDR = value; 
while(!(SPSR & 0x80)); 
return SPDR;
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.
Last edited by rv6502 on Thu Oct 03, 2019 3:05 am, edited 1 time in total.

CunningFellow
Posts: 1175
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: SPIF gets cleared if ANY interrupt happens?

Post by CunningFellow » Fri May 31, 2019 8:23 am

What does the ASM in the LSS file look like for that C?

User avatar
Jubatian
Posts: 1355
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPIF gets cleared if ANY interrupt happens?

Post by Jubatian » Fri May 31, 2019 4:58 pm

Could you check what happens in the Uzebox emulator when attempting to trigger the behaviour? It might pinpoint something. However I also think that the SPI is a bit "wonky" in this regard, code to work with it feeling somewhat fragile (I mean when I was in the situation).

rv6502
Posts: 25
Joined: Mon Feb 11, 2019 4:27 am

Re: SPIF gets cleared if ANY interrupt happens?

Post by rv6502 » Fri May 31, 2019 11:17 pm

CunningFellow wrote:
Fri May 31, 2019 8:23 am
What does the ASM in the LSS file look like for that C?
The short function (that infinite-loops randomly waiting for the flag) without all the testing crap:

Code: Select all

000003f6 <_Z8SPI_Sendh>:
 3f6:	8e bd       	out	0x2e, r24	; 46
 3f8:	0d b4       	in	r0, 0x2d	; 45
 3fa:	07 fe       	sbrs	r0, 7
 3fc:	fd cf       	rjmp	.-6      	; 0x3f8 <_Z8SPI_Sendh+0x2>
 3fe:	8e b5       	in	r24, 0x2e	; 46
 400:	08 95       	ret
If I add cli() sei() doing SPI transfers without using the SPI interrupt works fine:

Code: Select all

000003f6 <_Z8SPI_Sendh>:
 3f6:	f8 94       	cli
 3f8:	8e bd       	out	0x2e, r24	; 46
 3fa:	0d b4       	in	r0, 0x2d	; 45
 3fc:	07 fe       	sbrs	r0, 7
 3fe:	fd cf       	rjmp	.-6      	; 0x3fa <_Z8SPI_Sendh+0x4>
 400:	78 94       	sei
 402:	8e b5       	in	r24, 0x2e	; 46
 404:	08 95       	ret
 

Code: Select all

uint8_t SPI_Send(uint8_t value) 
{
	cli();
	SPDR = value;
	while(!(SPSR & 0x80));
	sei();
	return SPDR;
}
IMG_20190531_193240.jpg
IMG_20190531_193240.jpg (111.7 KiB) Viewed 1289 times
But of course that messes up the video output when SPI transfers happens.

It really looks like any interrupts will clear the SPIF bit. Even with SPIE disabled.

User avatar
Jubatian
Posts: 1355
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPIF gets cleared if ANY interrupt happens?

Post by Jubatian » Sat Jun 01, 2019 9:02 am

I think you should really try to reproduce it in the emulator. This is so that if the behaviour happens to appear within either of them (Uzem or CUzeBox), we could figure out what is going on causing it (something probably elsewhere in the code, probably not even within yours, and not an actual HW problem). The reason why I have some doubts on whether SPIF would be unreliable in this manner is that the bootloader also uses it, and it appears to not have problems (Also this type of problem, if it was actually that common like it seems, should have been discovered long ago. It is just too common to use both timers and SPI).

CunningFellow
Posts: 1175
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: SPIF gets cleared if ANY interrupt happens?

Post by CunningFellow » Sat Jun 01, 2019 9:55 am

Or with the AVR Emulator in AVR Studio 4. It is meant to be perfect emulation of the chips its supports.

rv6502
Posts: 25
Joined: Mon Feb 11, 2019 4:27 am

Re: SPIF gets cleared if ANY interrupt happens?

Post by rv6502 » Mon Jun 03, 2019 10:59 pm

I downloaded AVR Studio but haven't had time to install and test it in wine.

Now it's not crashing with interrupts enabled... I'm not sure what changed but if it crashes again I'll try AVR Studio.

Starting to think it's something completely unrelated to SPI. *shrug*

rv6502
Posts: 25
Joined: Mon Feb 11, 2019 4:27 am

Re: SPIF gets cleared if ANY interrupt happens?

Post by rv6502 » Tue Jun 04, 2019 7:53 am

kind of off-topic but progress, I got 4 out of 6 SD cards initialising fine.

The SD protocol documentation is really terrible. incomplete flow charts, details of commands all over the place, ...

I'm really enjoying figuring this stuff out. Brings back memories.

CunningFellow
Posts: 1175
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: SPIF gets cleared if ANY interrupt happens?

Post by CunningFellow » Tue Jun 04, 2019 8:49 am

If it was only one of the six SD card that you couldn't get work you could probably just say it was a bad apple.

rv6502
Posts: 25
Joined: Mon Feb 11, 2019 4:27 am

Re: SPIF gets cleared if ANY interrupt happens?

Post by rv6502 » Fri Jun 07, 2019 10:13 pm

One of the ones that I can't init yet is the one the Uzebox kit came with :D

Kind of hard to dismiss it as a bad apple LOL

Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests