Chaining SPI exchanges using interrupts on Atmega2560

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am hoping that someone can give me some pointers on running SPI interrupts on the Atmega2560.

The scenario is:
- there is a dual uart chip on the other end of the SPI bus
- I am trying to control it via interrupt code

What happens is:
1]- I kick off the task by writing to SPDR in the main code
2]- the interrupt (SIG_SPI) fires:
3]- I read SPSR
4]- workout the next byte to write
5]- write this byte to SPDR
6]- leave the interrupt
7]- the interrupt fails to fire again <-- this is the problem, I would expect to be able to chain together exchanges (the UART chip works in a FIFO mode)

Below is the routine routine I am using to test (it's pretty minimal):

static volatile uint8 sTestByte;
SIGNAL(SIG_SPI) {
	if (sInterruptTask != NULL) {
		uint8 byte = SPSR; // probably not necessary?
		sInterruptTask->inByte = SPDR; // cache away in global struct
		if (sTestByte > 10) {
			// stop loading bytes
			sTestByte = 0;
		} else {
			SPDR = sTestByte++;
		}
	}
}

Prior to the initial write to SPDR:
- SPCR = 0xD0 and SPSR = 0x01
- SREG = 0x82

I do not see the SPIF bit set while in the interrupt
- but if I step through the code I see it set when I write the next byte to SPDR

Neither do I see the Global Interrupt Enable (SREG bit7) set whilst I am in the SIG_SPI interrupt, but I presume it must be set as otherwise the interrupt would not have fired?

Any clues as to what I am doing wrong? or what I can do to make this work?

What would happen if somewhere in my main code briefly disabled interrupts while the byte was being shifted out?
-I would expect SPIF to be set and the SIG_SPI to be executed when interrupts were re-enabled

Thanks for your help.
Best regards,

sd

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Its probably not the cause of your problem, but if you are using gcc, the "signal()" construct is deprecated. Wasn't there something about requiring an reti or sei or something at the end of signal() type ints in order to re-enable interrupts. What ever it was, you don't need it with the modern interrupt construct in gcc.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim

Thanks for the pointers!

It might well be something along those lines
- as for (numerous/practical/political) reasons concerning supporting an old product we are still compiling with avr-gcc version 4.1.1
- the net result of this is that I don't believe I can make use of the ISR_ attributes but I'll try and remove the references to SIGNAL in the bits of the code base I am using at the moment

I guess I run the risk of nesting these if I manually re enable SEI prior to leaving the interrupt
- but I'll give it a go

Thanks again
sd

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There have been a few threads on this in the last year or so. If you just search the site for signal, you ought to get some better pointers than I can give.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net