• AVR Freaks

Hot!C18 -> XC8 SPI buffer weirdness

Author
ProfessorChaos
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2019/01/15 09:40:47
  • Location: 0
  • Status: offline
2019/07/03 06:02:01 (permalink)
0

C18 -> XC8 SPI buffer weirdness

I am porting the following code from C18 to XC8. It uses SPI to communicate with a 3208 A2D chip - in this case doing a conversion on channel 0 of the chip.
 
PIR3bits.SSP2IF = 0; 
SSP2BUF = 0x06;
while(!PIR3bits.SSP2IF) ;
            
PIR3bits.SSP2IF = 0;
junk = SSP2BUF;          // Had to add this or I never got the upper 4 bits of the conversion
SSP2BUF = 0x00;
while(!PIR3bits.SSP2IF);

PIR3bits.SSP2IF = 0;
Result = SSP2BUF & 0x0F;  // upper nibble of the conversion
Result <<= 8;
SSP2BUF = 0;
while(!PIR3bits.SSP2IF);

PIR3bits.SSP2IF = 0;
Result += SSP2BUF;  // lower 8 bits of the conversion

 
When I first built this (without the commented line above), Result would contain the lower 8 bits of the conversion, but never the upper 4 bits. After banging around for a while, I found that the first assignment to Result was always whatever I had written to the SSP2BUF on the second line.
 
Eventually, I discovered that the inserting the "junk = SSP2BUF" line above fixed the problem. However, I'm still a little confused about why this code worked in C18 and not in XC8.
 
Also, is it generally good practice to always read the SSP2BUF before writing to it?
post edited by ProfessorChaos - 2019/07/03 06:03:51
#1

9 Replies Related Threads

    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11243
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/03 10:10:47 (permalink)
    +1 (1)
    junk = SSP2BUF;

     
    You can just do
     
    SSP2BUF;
     
    there's no need for the assignment.  Which PIC are you using?
    #2
    du00000001
    Just Some Member
    • Total Posts : 2887
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/03 11:11:26 (permalink)
    +1 (1)
    At least it doesn't hurt to dummy-read SPIBUF prior initiating a new transfer sequence - just in case. This will remove any "bodies" not consumed during prior exchanges.
    Are you aware that every SPI transfer results in a byte received - whether the chip addressed does "answer" or not ?

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #3
    ProfessorChaos
    New Member
    • Total Posts : 20
    • Reward points : 0
    • Joined: 2019/01/15 09:40:47
    • Location: 0
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/09 10:20:07 (permalink)
    +1 (1)
    jtemples
    junk = SSP2BUF;

     
    You can just do
     
    SSP2BUF;
     
    there's no need for the assignment.  Which PIC are you using?




    That's interesting, I did not know that. I assume that works because SSP2BUF is declared volatile?
     
    I'm using the PIC18F8723.
    #4
    NKurzman
    A Guy on the Net
    • Total Posts : 17597
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/09 10:29:29 (permalink)
    +1 (1)
    ProfessorChaos
    jtemples
    junk = SSP2BUF;

     
    You can just do
     
    SSP2BUF;
     
    there's no need for the assignment.  Which PIC are you using?




    That's interesting, I did not know that. I assume that works because SSP2BUF is declared volatile?
     

     
    Correct
     
    #5
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11243
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/09 10:29:37 (permalink)
    +1 (1)
    I assume that works because SSP2BUF is declared volatile?

     
    Correct.
    #6
    ProfessorChaos
    New Member
    • Total Posts : 20
    • Reward points : 0
    • Joined: 2019/01/15 09:40:47
    • Location: 0
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/09 10:40:11 (permalink)
    0
    du00000001
    At least it doesn't hurt to dummy-read SPIBUF prior initiating a new transfer sequence - just in case. This will remove any "bodies" not consumed during prior exchanges.
    Are you aware that every SPI transfer results in a byte received - whether the chip addressed does "answer" or not ?



    Yes, I know how SPI works.
     
    The real question I have is why the original code (that skips the first read of SPIBUF) works when built under C18 but doesn't under XC8.
     
    Also, I did try reading SPIBUF before I send the first byte (the idea there was to "empty out" the buffer) and that didn't work either. There is some stuff in docs in the MSSP section about the SPIBUF being "double buffered when receiving" that got me thinking something like this might be the problem. (As an aside, not really sure what the documentation means by "when receiving" - do they mean "as a slave" or something else? You are always clocking a byte in when you are clocking one out in SPI, right?)
    post edited by ProfessorChaos - 2019/07/09 10:44:01
    #7
    Aussie Susan
    Super Member
    • Total Posts : 3607
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/09 19:27:40 (permalink)
    +1 (1)
    The 'when receiving' part refers to the fact that the MSSP module (at least in SPI mode) always exchanges values/bits - as it sends out one bit it is receiving the comparable bit from the other device.
    As a slave, the code has to write a value to the buffer before the exchange is started. As a master, writing to the buffer initiates the exchange. In either case (for these older-style SPI implementations) if you were to write another value to the buffer while the exchange is occurring, then you can corrupt the value being sent. However the module can 'assume' that the firmware is doing the right thing in terms of timing the writing to the buffer and the exchange process..
    On the 'receive' side, the module cannot make that assumption. It is quote possible for the exchange to be started (either as the master by writing to the buffer, or as the slave by the master starting to send clocks) and for the firmware to read from the buffer while the exchange is in progress. The value that is read is the complete value that was last received, regardless of what is in the shift register at that time. Therefore, they are saying that the 'receive' side is effectively double buffered.
    As to any difference between C18 and XC8, I don't know the answer. However I do know that in master mode, the module will continue to work if you don't read the last received buffer before the next exchange is complete. IIRC you will get the 'buffer overflow' bit set but that does not stop the module. However on the slave side, if the overflow bit is set then it will stop working until the bit is cleared by the firmware.
    Susan
    #8
    ProfessorChaos
    New Member
    • Total Posts : 20
    • Reward points : 0
    • Joined: 2019/01/15 09:40:47
    • Location: 0
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/10 08:42:04 (permalink)
    0
    This is a helpful response, at least in breaking down the issues in a coherent fashion. I added some comments/followup questions.
     
    Aussie Susan
    The 'when receiving' part refers to the fact that the MSSP module (at least in SPI mode) always exchanges values/bits - as it sends out one bit it is receiving the comparable bit from the other device.

    I get the general point here, but I still wonder why the manual specifically uses the "when receiving" distinction. The MSSP module is always receiving as it is transmitting, right? Why bother with this unnecessary terminology?
     
    As an aside, I don't think the problem I was seeing before I added the first read of the SPIBUF was due to any double-buffering because I tried doing two consecutive reads of the SPIBUF after sending the second control byte and that didn't fix the problem.
     
    Aussie Susan
    As a slave, the code has to write a value to the buffer before the exchange is started. As a master, writing to the buffer initiates the exchange. In either case (for these older-style SPI implementations) if you were to write another value to the buffer while the exchange is occurring, then you can corrupt the value being sent. However the module can 'assume' that the firmware is doing the right thing in terms of timing the writing to the buffer and the exchange process..

    Yes, this is why the SSPOV bit is only set when in Slave mode - the assumption is that in Master mode, the software is controlling the timing, so there shouldn't ever be a problem.
     
    Aussie Susan
    On the 'receive' side, the module cannot make that assumption. It is quote possible for the exchange to be started (either as the master by writing to the buffer, or as the slave by the master starting to send clocks) and for the firmware to read from the buffer while the exchange is in progress. The value that is read is the complete value that was last received, regardless of what is in the shift register at that time. Therefore, they are saying that the 'receive' side is effectively double buffered.

    Here is where I get a bit confused about the distinction between slave/master and "receive" side. The master controls the pace of the clock, so it doesn't really need any double buffering since it can guarantee that the next byte won't be transferred before the incoming byte is read.
     
    Aussie Susan
    As to any difference between C18 and XC8, I don't know the answer. However I do know that in master mode, the module will continue to work if you don't read the last received buffer before the next exchange is complete. IIRC you will get the 'buffer overflow' bit set but that does not stop the module. However on the slave side, if the overflow bit is set then it will stop working until the bit is cleared by the firmware.
    Susan



    According to the manual, the overflow bit only operates in Slave mode. Again, probably because the assumption is that Master has complete control over the transfer timing, so it should never encounter an overflow if it is coded correctly. On the Slave side, you might have timing issues (interrupt latency or whatever) that could create overflows if the Master is really pumping out the bytes.
     
    Why this happens only with this particular piece of code (and only when built by XC8) remains a mystery. I've got a nearly identical piece of code in different XC8 project that reads the same chip over SPI and it skips the first read and works just fine.
     
    It's not a critical problem because the code now works fine with the fix shown above - I'm just curious as to why it failed in this circumstance.
    #9
    Aussie Susan
    Super Member
    • Total Posts : 3607
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: C18 -> XC8 SPI buffer weirdness 2019/07/10 20:42:25 (permalink)
    +1 (1)
    ProfessorChaos
    Here is where I get a bit confused about the distinction between slave/master and "receive" side. The master controls the pace of the clock, so it doesn't really need any double buffering since it can guarantee that the next byte won't be transferred before the incoming byte is read.

    The hardware is basically the same whether the module is configured as the master or the slave. I'm guessing that it would make the silicon design more complex to try to make the 'slave' mode double buffered but the 'master' side not.
    Also you need to consider exactly how the module is being used. It could well be that, for the master, the 'send' side is being driven by an ISR but the 'receive' side is not min which case you are in a similar situation to the 'slave' in that the exchange could be triggered at some indeterminate time with respect to reading the buffer. (I can't really think of a case where this would be useful but it is still possible I suppose.)
    Susan
    #10
    Jump to:
    © 2019 APG vNext Commercial Version 4.5