GB60 SPI problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

GB60 SPI problem

1,727 Views
gaminn
Contributor IV

Hello,

this is my interrupt routine I use to communicate in master mode:

 

interrupt VectorNumber_Vspi1 SPIISR(void) {  if(SPI1S_SPTEF && SPI1C1_SPTIE) { // sending data service    if(SPI_STEP_SEND == SPI_START_STATUS) {      SPI_COUNTER_SENT = 0;      SPI_STEP_SEND = SPI_DATA_TRANSMISION_STATUS;    } else {      SPI_COUNTER_SENT++;      }          if(SPI_DATA_DIRECTION) { // SPI is sending data, send our data from SPI_DATA buffer      SPI1S;      SPI1D = SPI_DATA[SPI_COUNTER_SENT];    } else { // SPI is receiving data, send 0xFF      SPI1S;      SPI1D = 0xFF;    }        if(SPI_COUNTER_SENT >= SPI_LENGTH - 1) {      SPI1C1 &= 0b11011111;      SPI_STEP_SEND = SPI_READY_STATUS;    }  }  if(SPI1S_SPRF && SPI1C1_SPIE) { // receiving data service    if(SPI_STEP_RECEIVE == SPI_START_STATUS) {      SPI_COUNTER_RECEIVED = 0;      SPI_STEP_RECEIVE = SPI_DATA_TRANSMISION_STATUS;    } else {      SPI_COUNTER_RECEIVED++;      }        if(!SPI_DATA_DIRECTION) { // SPI is receiving data, store data into the buffer      SPI1S_SPRF;      SPI_DATA[SPI_COUNTER_RECEIVED] = SPI1D;      } else { // SPI is sending data, flush received data      SPI1S_SPRF;      SPI1D;    }        if(SPI_COUNTER_RECEIVED >= SPI_LENGTH - 1) {      SPI1C1 &= 0b01111111;      SPI_STEP_RECEIVE = SPI_READY_STATUS;    }  }}

 

When I send data through SPI it means I send data and flush received data. When I receive data it means I receive data and send 0xFF.

 

I have problem, because data read is not serviced everytime it should be. For example I run function that writes data:

 

 

unsigned char SPIWrite(unsigned char *bufferS, word length) {  if(!SPIWaitForIdle() || !length) {    return 0;  }  SPI_STEP_SEND = SPI_START_STATUS;  SPI_STEP_RECEIVE = SPI_START_STATUS;  SPI_LENGTH = length;  SPI_DATA = bufferS;  SPI_DATA_DIRECTION = 1;  SPI1C1 = 0b11110000;  return 1; }

 

Writing data is OK, but receiving data is never ended (transaction never ends with SPI_STEP_RECEIVE = SPI_READ_STATUS). Data receiving is serviced only for the first time it should be serviced in ISR, no more times.

 

What is wrong with my ISR?

 

Thanks

 

Martin

Labels (1)
0 Kudos
4 Replies

409 Views
bigmac
Specialist III

Hello Martin,

 

Your use of interrupts for SPI master mode would give doubtful advantage, and seems to result in much more complex code than would otherwise be necessary.  Unless you have a slow SPI clock, the bus cycles required for each SPI transmission are likely to be comparable with the bus cycle overheads required to enter and exit the ISR.  My personal choice would be not to use interrupts, and to keep the SPI clock near maximum rate (usually not a problem for most SPI slave devices).

 

Note that the SPRF flag must be cleared after the completion of any byte transfer, even if you have no interest in the return data.  Otherwise an overrun condition will occur that will prevent further data transfer until the flag is cleared.  I am not sure whether this is properly occurring with your code.

 

You also seem to have enabled SPTEF interrupts, which makes the operation even more complex, and gives virtually zero benefit.  This will also increase the possibility of an overrun condition occurring, and data loss, in the event that any other ISR should delay the processing of the SPI ISR.  Better to enable SPRF interrupts only so that the next send byte is not loaded to the buffer until the previous transfer is completed, with the overrun timing issues eliminated. This will also mean that the SPTEF flag will always be set when the interrupt occurs, eliminating the need for the conditional test within the ISR.

 

Regards,

Mac

0 Kudos

409 Views
gaminn
Contributor IV

Hi, OK, so I will not use interrupts. I wrote this:

 

void SPIInit(void) {  PTED_PTED2 = 1;  PTEDD_PTEDD2 = 1;  SPI1BR = 0b01100110;  SPI1C1 = 0b01010000;}unsigned char SPITransfer(unsigned char data) {  while(!SPI1S_SPTEF);  SPI1D = data;  while(!SPI1S_SPRF);  return SPI1D;}unsigned char SPIWrite(unsigned char *bufferS, word length) {  int i;    for(i = 0 ; i < length ; i++) {    SPITransfer(bufferS[i]);  }  return 1; }unsigned char SPIRead(unsigned char *bufferS, word length) {  int i;    for(i = 0 ; i < length ; i++) {    bufferS[i] = SPITransfer(0xFF);  }  return 1;}

But it does the same - SPI1S_SPRF is never set and program never continues, it stops on while(!SPI1S_SPRF); line.

Message Edited by gaminn on 2009-07-26 01:08 PM
0 Kudos

409 Views
bigmac
Specialist III

Hello,

 

Are you attempting to monitor the state of the SPI1S and SPI1D registers during debug?  Perhaps you are single stepping through the function?  If so, these actions can result in the SPRF flag being cleared within the while loop, so that the loop never exits.  Does the function successfully complete when executing the function normally?

 

Regards,

Mac

 

0 Kudos

409 Views
gaminn
Contributor IV
You are right. I was debugging it...Sorry.
0 Kudos