Can i use SPIF flag inside an ISR() function?

I’m trying to use an ATTiny841 as SPI slave using interruptions. I’m already aware of what registers i need to set in order to activate SPI via interruptions, i’m also aware of how to handle ISR() on the code if a byte is received from the master, but i did not understand how should i respond and send some data to the master. Do the SPIF flag works inside the ISR function normally? Am i missing some delays in my code? Is my ISR function too long also?

volatile int var1 = 100;        
volatile int var2 = 0;      

void spi_init(){                                        //AS SLAVE  
  REMAP = (1 << SPIMAP);                   //Set SPI to work on the alternate ports
  DDRA = (1 << DDA0);                          //Set MOSI (PA1 pin) and CLK (PA3) as OUTPUT
  SPCR = (1 << SPE) | (1 << SPIE);       //Enable SPI, set as master and clock rate fck/16 (500khz)
}

ISR (SPI_STC_vect){             //SPI interruption
  byte c = SPDR;                   // grab byte from SPI Data Register
  byte var1b = var1;
  byte var2b = var2;
  if(c == "B"){                         //If master requested info
    SPDR = var1b;
    while(!(SPSR & (1<<SPIF)));     //Can i use this line of code inside ISR? Or should i just use a delay?
    SPDR = var2b;
    while(!(SPSR & (1<<SPIF))); 
  }

I don't think you can do that.

Can you find a tutorial/guide for SPI slave on atmega328 (that is, a normal arduino uno/nano/promini)? The SPI module is the same in both.

Thanks DrAzzy, i'm currently searching for tutorials on the atmega328. Just one more thing, do the SPIF flag triggers the ISR() function when sending data? or just when receiving?

I've never used SPI in slave mode, so I don't know - sorry. It wasn't clear to me from reading the datasheet either.

However it works on the atmega328(p), it works the same way on the attiny841; I just don't know what that behavior is.

Oh - and your comment says you're setting MOSI and SCK as OUTPUT (though only one pin is being set OUTPUT). But you want to set only MISO as OUTPUT, since that's the slave. This may only be a problem with the comment, but doublecheck this.

I think it should work. But if the Master does not read the bytes you will be stuck in an endless loop.

There are code examples of SPI master/slave pairs here (for the ATMega328p) :
http://www.gammon.com.au/forum/?id=10892

Maybe these translate well to the ATtiny841

DrAzzy:
I've never used SPI in slave mode, so I don't know - sorry. It wasn't clear to me from reading the datasheet either.

However it works on the atmega328(p), it works the same way on the attiny841; I just don't know what that behavior is.

Oh - and your comment says you're setting MOSI and SCK as OUTPUT (though only one pin is being set OUTPUT). But you want to set only MISO as OUTPUT, since that's the slave. This may only be a problem with the comment, but doublecheck this.

Indeed my comment is wrong! I'm sorry about that. I would like soo much to test the ISR behaviour, but my ATtiny's still haven't arrived.

Smajdalf:
I think it should work. But if the Master does not read the bytes you will be stuck in an endless loop.

I think maybe that's not true, because the SPIF flag will reset even if it do not read a message, and will be one just when it is actually receiving something. But again, i still can not test this on my own :frowning:

6v6gt:
There are code examples of SPI master/slave pairs here (for the ATMega328p) :
Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino

Maybe these translate well to the ATtiny841

I have used this link a lot while developing the SPI communication, but what i need is not covered by it, which would be how to awnser a message using interruptions, maybe i am looking at the problem from a wrong point of view, maybe i'm trying to do something impossible, still don't know

Smug:
I think maybe that’s not true, because the SPIF flag will reset even if it do not read a message, and will be one just when it is actually receiving something.

SPIF is 1 when a byte is transfered. But clock pulses are supplied by the Master. If the Master does not provide the clock pulses SPIF will be never set and you will wait forever. OTOH if the Master is stuck it may be irrelevant if Slave is stuck too.

I'm just looking at an attempt I made a couple of months ago to make an SPI slave with an ATTiny841. I gave up because the core grabbed another 80 bytes of RAM for SPI and I couldn't quite squeeze the application into the remaining space so used an ATMega328P instead.. These are the relevant bits of setup() and the ISR and maybe it helps :

void setup() {

       . . .
       . . . 
	// SPI  https://arduino.stackexchange.com/questions/33086/how-do-i-send-a-string-from-an-arduino-slave-using-spi

	// have to send on master in, *slave out*
	pinMode(MISO, OUTPUT);

	// turn on SPI in slave mode
	SPCR |= bit(SPE);

	// turn on interrupts  (also managed in loop)
	SPCR |= bit(SPIE);

        . . .
        . . . 
}



// ISR

#if defined(_xATTINY841)
ISR (SPI_vect)   //attiny841
#else 
ISR (SPI_STC_vect) // all except at841
#endif

{
  //
  //  Respond to client SPI request (we are SPI slave)
  //  https://arduino.stackexchange.com/questions/33086/how-do-i-send-a-string-from-an-arduino-slave-using-spi
  //
  //  1 from SPI master is data availability check. 2 from master = data request.
  //  The slave responds to a "1" by returning the length of the data set.

  static uint8_t *bptr ;  // points to structure that supplies data

  // inSpiEvent = true ;
  uint8_t c = SPDR;

  if (c == 1)  // 1 = data availablity request
    {
	  uint8_t reply ;
	  if ( newCall) {
		  reply = 84 ;
		  bptr = (uint8_t*) (& nsXDMF::tfr_call)   ;
		  newCall = false ;
	  }
	  else if ( newMsg ) {
		  reply = 5 ;
		  bptr = (uint8_t*) (& nsXDMF::tfr_message)   ;
		  newMsg = false ;
	  }
	  else if ( newRing ) {
		  reply = 3 ;
		  bptr = (uint8_t*) (& nsXDMF::tfr_ring)   ;
		  newRing = false ;
	  }
	  else reply = 0 ;  // no data
	  SPDR = reply  ;
    }
  else if ( c == 2 ) {  // 2 = data request
	  SPDR = *bptr++ ;

  }

}

It is based partly on Nick Gammon's example. I haven't included the macros, but it should at least be clear to you that the ISR has a special name for an ATTiny841