|
|
View previous topic :: View next topic |
Author |
Message |
trick420
Joined: 04 Feb 2005 Posts: 3
|
Broken read_spi during migration from 16F877 to 18F458 |
Posted: Fri Feb 04, 2005 10:26 pm |
|
|
Hello everyone.
I'm having trouble with read_spi. I have a working 16F877 talking to a Ti DSP via SPI. The protocol is as follows:
PIC is master. We are using SS, but not as built in. We're toggling another pin external to the SPI interface. All communications are 3 bytes. For a write command, the first byte from the PIC contains the target register address. The second and third Bytes contain the data. For all 3 bytes, the DSP responds simultaneously with a 'don't care' byte, which is 0x55. No problem, works fine on either part.
For a read, the pic first sends a write_spi to the DSP that contains a read address bit and the target address. The DSP simultaneously responds with a 0x55. The pic then performs a read_spi(0) twice, and generates the appropriate clocks. During this time, the DSP sends back the requested two data bytes.
Simple enough. The 16F877 works flawlessly. The 18F458 doesn't work. In scoping the Rx, Tx, and CLK lines, the two systems are identical - the correct data is shown on the scope. If I step through the code and watch the SSPBUF register, the first byte on the read routine, which is a 0x55 that is generated from the write_spi appears in the register. The next byte that comes in with the read_spi does not appear in the register, and after calling read_spi, the variable gets assigned the first byte (0x55). The second call to read_spi gets the first read_spi byte.
Attached is the code:
Setup parameters from main();
setup_spi( SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_4 );
#asm
/* For 18F458 Only */
bcf SSPCON1,4
bcf SSPSTAT,7
bcf SSPSTAT,6
/* For 16F877 Only */
//bcf 0x14,4
//bcf 0x94,7
//bcf 0x94,6
#endasm
The read fuction used:
void ReadSPI()
{
output_low( PIN_C1 ); //on 16F, 0x55 gets ignored
spi_write( SByte1 );
output_high( PIN_C1 );
output_low( PIN_C1 );
S_in_1 = spi_read( 0 ); //on 16F, data byte 1 gets assigned to S_in_1. on 18F 0x55 from the write gets assigned to S_in_1
output_high( PIN_C1 );
output_low( PIN_C1 );
S_in_2 = spi_read( 0 ); //on 16F, data byte 2 gets assigned to S_in_2. On 18F data that should have been assigned to S_in_1 gets assigned to S_in_2.
output_high( PIN_C1 );
} /* end ReadSPI() */
Now, simply generating another read would get the last data byte, but the protocol says that each communication is 3 bytes, so generating a clock again actually sets the DSP to a read register 0, and thus puts the two processors out of sync.
I'm also using PCWH version 3.218
I'm at a loss on this. I'm convinced at this point that I'm dealing with a compiler bug. Any suggestions?
Thanks,
Jeff |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Feb 05, 2005 2:41 am |
|
|
1. If you're convinced it's a compiler bug, download vs. 3.191 and try it.
It may be different.
2. If it's a compiler bug, there's not all that much code in the CCS
spi_read() function. I looked at the .LST file, and there's only
five lines of ASM code in it. There's not that much to go wrong.
3. The fact that you have little blocks of #asm code in there, is
a little disturbing. It seems to me that if you're going to
adjust bits here and there in the SPI setup, then you ought to
write your own complete routine. Ideally it should be written
with C code which accesses registers declared with #byte statements.
4. There is a wacky SPI Buffer Full bug listed in the errata.
I stepped through the code in the simulator and I didn't see it.
It involves the BSR. I stepped through the code in the simulator
with PCH vs. 3.188 and the BSR was always at 0. So that bug
shouldn't apply. It's probably the same in your version, but check it.
5. I would look at it on the scope first, and make sure that the edge
relationships are exactly the same between the two PICs.
6. Also look at the amount of setup and hold time between the chip
select edges and the data and clock. I wonder if you're running
the 18F458 with a higher frequency crystal than the 16F877 ?
7. Also, the 18F458 generates tighter ASM code than the 16F877.
It doesn't have all those bank selects and GOTO statements in it.
If you're running at 4 MHz, each instruction takes 1 or 2 usec, and
that might be significant. Does the DSP have a hardware SPI ?
If so, look at the timing requirements in the data sheet.
I think we might be dealing with a subtle timing bug, unless using
vs. 3.191 fixes it. |
|
|
trick420
Joined: 04 Feb 2005 Posts: 3
|
|
Posted: Mon Feb 07, 2005 1:11 pm |
|
|
PCM programmer wrote: | 1. If you're convinced it's a compiler bug, download vs. 3.191 and try it.
It may be different.
|
It is different... Buggy in a completely different way, and still not working correctly. I can retrieve the correct data with this by calling the series of write_spi, read_spi, read_spi three times. Also, the calls to read_spi() have to be with empty parenthesis for this to work. If I call the routine with read_spi( 0 ); as the documentation indicates, it doesn't work any better that the latest compiler does. Also, the 3.191 version will not talk with my LCD correctly (also SPI related), so I can't use this version even if I wanted to.
PCM programmer wrote: |
2. If it's a compiler bug, there's not all that much code in the CCS
spi_read() function. I looked at the .LST file, and there's only
five lines of ASM code in it. There's not that much to go wrong.
|
There's only one line in my .lst that is related to the read_spi() :
MOVFF FC9,4C
That's it. I can't imagine that read_spi is that simple. It's no different that writing S_in_2 = *SSPBUF where SSPBUF is #defined in the header file. Both generate the same assembler code, and neither works.
PCM programmer wrote: |
3. The fact that you have little blocks of #asm code in there, is
a little disturbing...
|
It's legacy code. I didn't write it. I did however change it to use the CCS setup call completely. Had no effect on the code whatsoever...
PCM programmer wrote: |
4. There is a wacky SPI Buffer Full bug listed in the errata.
I stepped through the code in the simulator and I didn't see it.
It involves the BSR. I stepped through the code in the simulator
with PCH vs. 3.188 and the BSR was always at 0. So that bug
shouldn't apply. It's probably the same in your version, but check it.
|
No, It doesn't appear.
PCM programmer wrote: |
5. I would look at it on the scope first, and make sure that the edge
relationships are exactly the same between the two PICs.
|
Did this. The waveforms generated for either Pic, and the responses from the DSP are identical. The correct data is coming into the PIC, and the timing is spot-on.
PCM programmer wrote: |
6. Also look at the amount of setup and hold time between the chip
select edges and the data and clock. I wonder if you're running
the 18F458 with a higher frequency crystal than the 16F877 ?
|
Nope. Both parts are running in identical environments. Both are on 3.579545 MHz clocks. Both are running the exact same code. I just switch the parts in the emulator (Ice2000) and recompile for the desired part.
PCM programmer wrote: |
7. Also, the 18F458 generates tighter ASM code than the 16F877.
It doesn't have all those bank selects and GOTO statements in it.
If you're running at 4 MHz, each instruction takes 1 or 2 usec, and
that might be significant. Does the DSP have a hardware SPI ?
If so, look at the timing requirements in the data sheet.
I think we might be dealing with a subtle timing bug, unless using
vs. 3.191 fixes it.
|
Again, this falls to the timing of the scope readings. They're identical between the parts. The problem seems to be in the PIC itself, as the data coming into the part is not making it into the program. I did a side by side compare of the .asm generated by both compiles, and while the write_spi commands were only marginally different (and I'm not having a problem with the write_spi call), the read_spi .asm is identical, and is shown above.
Jeff |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 07, 2005 2:21 pm |
|
|
Quote: | There's only one line in my .lst that is related to the read_spi() :
MOVFF FC9,4C |
If I compile this small test program,
Code: | #include <18F458.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
//===================================
void main()
{
char c;
c = spi_read(0);
while(1);
} |
then I get this ASM code for the spi_read(0) statement:
Code: | 0000 00342 .................... c = spi_read(0);
0016 50C9 00343 MOVF FC9,W
0018 6AC9 00344 CLRF FC9
001A A0C7 00345 BTFSS FC7.0
001C EF0D F000 00346 GOTO 001A
0020 CFC9 F006 00347 MOVFF FC9,06 |
This is with PCH vs. 3.188. If you're not getting that code, then
something is wrong. Try compiling the test program above with
vs. 3.191. You should get very similar code.
Quote: | I just switch the parts in the emulator (Ice2000) and recompile for the desired part. |
Bing. This part right here sets off alarm bells. You're not really running
the PIC, you're running the emulator. You're running whatever bugs
the emulator may have. I would switch to a real PIC. Then, you're
only dealing with the PIC's bugs, not the PIC+emulator bugs. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 07, 2005 6:02 pm |
|
|
Here's some additional information.
Download the errata document for the ICE 2000:
http://ww1.microchip.com/downloads/en/DeviceDoc/80078b.pdf
It says that in i2c Master mode, any opcode of the format xxC9
will clear the SSPSTAT buffer bit. Isn't that sort of what you're seeing ?
This errata is for i2c Master mode, but some of the hardware
for that mode is also used in the SPI mode, and it wouldn't
surprise me if it affected SPI as well.
What do we see in the spi_read(0) function ?
We see tons and tons of opcodes with xxC9 in them.
Code: | 0000 00342 .................... c = spi_read(0);
0016 50C9 00343 MOVF FC9,W
0018 6AC9 00344 CLRF FC9
001A A0C7 00345 BTFSS FC7.0
001C EF0D F000 00346 GOTO 001A
0020 CFC9 F006 00347 MOVFF FC9,06 |
This is why I don't trust ICE. There is always some bug to mess
you up, and then not only do you have to debug the ICE bugs,
then you have to debug it all over again when you run it on the
actual chip. |
|
|
trick420
Joined: 04 Feb 2005 Posts: 3
|
|
Posted: Wed Feb 09, 2005 9:48 am |
|
|
PCM programmer wrote: | Here's some additional information.
Download the errata document for the ICE 2000:
http://ww1.microchip.com/downloads/en/DeviceDoc/80078b.pdf
It says that in i2c Master mode, any opcode of the format xxC9
will clear the SSPSTAT buffer bit. Isn't that sort of what you're seeing ?
This errata is for i2c Master mode, but some of the hardware
for that mode is also used in the SPI mode, and it wouldn't
surprise me if it affected SPI as well.
|
Thanks PCM Programmer. There's a couple of lines of .asm to fix the bug on the errata sheet - It seems to be working now - I just #defined the .asm code for use with the emulator.
Jeff |
|
|
|
|
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
|