CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI losing bytes

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
robert



Joined: 10 Aug 2006
Posts: 9

View user's profile Send private message

SPI losing bytes
PostPosted: Tue Apr 17, 2007 4:15 am     Reply with quote

Hi all,

Has anyone come across this and have any idea why?

I am using 2 18f24j10 devices both as SPI slaves looking at the same SPI stream. The stream is fixed 183 byte packets and i use the below function to receive them. I'm using the registers as i had dumped the built in functions in case they were responsible. I put a breakpoint on the overrun check and it is never reached. What I get is random whole bytes being dropped. I can see that on a scope as I toggle an output on each received byte and the output change is perfectly synced at the end of the byte with the exception of the missing byte. Its usually about 1 per packet never a dropped bit.

Any ideas anyone?


Code:


void get_spi_block()
{
   int i = 0;

   ssp1con1 &= 0xbf;                       // clear overrun
   if (master_slave)                       // slave processor
   {
      while (i < 183)
      {
         if (ssp1stat & 1)                 // data ready
         {
            if (ssp1con1 & 0x40)           // overrun
               break;
            output_bit(PIN_H0,x++&1);      // toggle a bit
            loaderbuffer[i++] = ssp1buf;   // transfer data
         }
      }
   }                                        // master processor
   else
   {
      while (i < 183)
      {
         if (ssp1stat & 1)
         {
            if (ssp1con1 & 0x40)
               break;
            output_bit(PIN_H1,x++&1);
            loaderbuffer[i++] = ssp1buf;
         }
      }
   }
   x = 0;
}


PS
The code is common to both processors an input pin configs either a master uP or a slave uP. The spi code is repeated to ensure highest transfer speed (~ 1Mbit)
mskala



Joined: 06 Mar 2007
Posts: 100
Location: Massachusetts, USA

View user's profile Send private message

PostPosted: Tue Apr 17, 2007 6:27 am     Reply with quote

What is calling this function, and are you using interrupts to control it? What is the setup of the SS? Check the rest of your compiled listing for areas where the compiler has turned off interrupts.
robert



Joined: 10 Aug 2006
Posts: 9

View user's profile Send private message

SPI lost bytes
PostPosted: Tue Apr 17, 2007 6:53 am     Reply with quote

hi mskala,

no interrupts, function is call from a polling loop waiting for a byte to be received.
The packets are sent at fixed time intervals ~ 18.6ms and recieved packets are synced to the gap between packets.

full code is
Code:


---- main portion ----

   setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_SS_DISABLED);



   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

   wait_for_spi_gap();

   while(1)
      get_spi_block();      
}

int8 x;
void wait_for_spi_gap()
{
   int8 m;

   set_timer1(0xb000);
   enable_interrupts(INT_TIMER1);

   while (spi_data_is_in() == FALSE);   //ensure in a packet
   m = spi_read();
   enable_interrupts(GLOBAL);
   while(timout == FALSE)            // now wait for a gap
   {
      set_screen();
      if (spi_data_is_in() == TRUE)
      {
         m = spi_read();
         set_timer1(0xb000);
      }
   }
   timout = FALSE;
   disable_interrupts(GLOBAL);
   output_bit(PIN_H0,x++&1);
}


void get_spi_block()
{
   int i = 0;

   ssp1con1 &= 0xbf;                       // clear overrun
   if (master_slave)                       // slave processor
   {
      while (i < 183)
      {
         if (ssp1stat & 1)                 // data ready
         {
            if (ssp1con1 & 0x40)           // overrun
               break;
            output_bit(PIN_H0,x++&1);      // toggle a bit
            loaderbuffer[i++] = ssp1buf;   // transfer data
         }
      }
   }                                        // master processor
   else
   {
      while (i < 183)
      {
         if (ssp1stat & 1)
         {
            if (ssp1con1 & 0x40)
               break;
            output_bit(PIN_H1,x++&1);
            loaderbuffer[i++] = ssp1buf;
         }
      }
   }
   x = 0;
}


This is just test code to get the SPI to sync
I can get it to sync with a repeated static data pattern
When the byte is missed the SDO output is correct.
mskala



Joined: 06 Mar 2007
Posts: 100
Location: Massachusetts, USA

View user's profile Send private message

PostPosted: Tue Apr 17, 2007 10:13 am     Reply with quote

I don't see anything wrong, and if traces/cables were an issue you would be losing bits. Also I didn't see any errata from microchip related to this.
Ttelmah
Guest







PostPosted: Tue Apr 17, 2007 2:38 pm     Reply with quote

One comment. You need to read the SSPBUF to clear the overrun condition, as well as clearing the bit in the condition register.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Apr 18, 2007 4:24 am     Reply with quote

Just a wild guess, but maybe the PIC errata is not complete. In the past it has been observed that known bugs in one chip family were also present in other chip families but not (yet) added to all errata documents.

One specific bug I'm thinking about is the one present in the PIC18F87J10 series: http://ww1.microchip.com/downloads/en/DeviceDoc/80246b.pdf
Quote:
9. Module: MSSP
When the MSSP peripherals are configured for
SPI mode, the Buffer Full bit, BF (SSPxSTAT<0>),
should not be polled in software to determine when
the transfer is complete.

Work around
Copy the SSPxSTAT register into a variable and
perform the bit test on the variable. In Example 3,
SSP1STAT is copied into the working register
where the bit test is performed.

EXAMPLE 3: MSSP1
Code:
loop_MSB:
MOVF SSP1STAT, W
BTFSS WREG, BF
BRA loop_MSB


A second option is to poll the Master Synchronous
Serial Port Interrupt Flag bit, SSP1IF (PIR1<3>).
This bit can be polled and will set when the transfer
is complete.


It's very easy to implement the second option mentioned above, you only have to replace the test for ssp1stat by a test for the PIR1 flag. Even when it doesn't improve things it wouldn't hurt to leave this test in.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group