View previous topic :: View next topic |
Author |
Message |
robert
Joined: 10 Aug 2006 Posts: 9
|
SPI losing bytes |
Posted: Tue Apr 17, 2007 4:15 am |
|
|
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
|
|
Posted: Tue Apr 17, 2007 6:27 am |
|
|
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
|
SPI lost bytes |
Posted: Tue Apr 17, 2007 6:53 am |
|
|
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
|
|
Posted: Tue Apr 17, 2007 10:13 am |
|
|
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
|
|
Posted: Tue Apr 17, 2007 2:38 pm |
|
|
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
|
|
Posted: Wed Apr 18, 2007 4:24 am |
|
|
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. |
|
|
|