• AVR Freaks

Hot!SPI "Bidirection" Diagnosis (mimicking the PIC flash method)

Author
acharnley
Super Member
  • Total Posts : 617
  • Reward points : 0
  • Joined: 2016/05/01 06:51:28
  • Location: 0
  • Status: offline
2020/09/26 04:38:04 (permalink)
0

SPI "Bidirection" Diagnosis (mimicking the PIC flash method)

So I'm flashing and verifying PIC16 code from an ARM, working great without any issues. During normal operation the ARM Tx's data to the PIC every 1/4s, also working well. Now I need to transfer some flags and data from the PIC and since I've no pins free the intention is to mimic exactly what Microchip do and reconfigure the pins. I've implemented but hit a problem and would appreciate eyes over my code to see if I've made a cockup!
post edited by acharnley - 2020/09/26 04:51:09
#1

5 Replies Related Threads

    acharnley
    Super Member
    • Total Posts : 617
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: SPI "Bidirection" Diagnosis (mimicking the PIC flash method) 2020/09/26 04:40:25 (permalink)
    0
    I've debugging from the ARM side and only an LED to flash from the PIC side. Both routines are working well but the data transmitted by the PIC is always level high, i.e 0xFF. Here's what the ARM reports.
     
     (see attached)
     
    The struct is the same on both sides. There are two header values which I use for synchronisation. I'm not 100% sure this is the best way to do it but it works for now and is a question for another time.


     
    volatile struct {
      uint8_t headers[2];
      struct {
        uint8_t outputs;
        uint8_t capacitorBand:2;
        uint8_t storageBand:2;
        uint8_t frontPattern:4;
        uint8_t rearPattern:4;
        uint8_t padding:4;
      } rx;
      struct {
        uint8_t frequency;
        uint8_t storageVoltage;  // 51 == 5.1
        uint8_t uvlo:1;
        uint8_t storageBand:2;
        uint8_t bootstrapped:1;
        uint8_t padding:4;
      } tx;
    } glue = {
        .headers = { 0b10101010, 0b01010101 },
        .tx.uvlo = 1
    };
     

     
    Here's the PIC code which checks the headers, handles toggling the mode and loads the buffer. Have I screwed up loading the buffer for Tx mode? Perhaps setting SSP1DATPPS isn't enough for disabling SPI output mode?

    I've tried adding a suitable delay on the ARM side between RX and TX modes in case the PIC can't reconfigure fast enough. It made no difference.


     
    #define SPI_MODE_TX  RB7PPS = 0x15; DATDIR = 0; SSP1DATPPS = 0;
    #define SPI_MODE_RX RB7PPS = 0; DATDIR = 1; SSP1DATPPS =  0x0F;
     
        // SPI
        if (SPI_INT_FLAG) {
            CLRWDT();
            SPI_INT_FLAG = 0;
            
            if (spiSection == (uint8_t* ) &glue.headers) {
                if (SSP1BUF == *spiPos) {
                    spiPos++;
                    if (spiPos == (uint8_t* ) &glue.rx) {
                        spiSection = (uint8_t* ) &glue.rx;
                    }
                } else {
                    spiPos = (uint8_t* ) &glue.headers;
                }
            } else if (spiSection == (uint8_t* ) &glue.rx) {
                memcpy(spiPos, &SSP1BUF , sizeof(SSP1BUF));
                spiPos++;
                if (spiPos == (uint8_t* ) &glue.tx) {
                    spiSection = (uint8_t* ) &glue.tx;
                    SPI_MODE_TX;
                    memcpy(&SSP1BUF , spiPos,  sizeof(SSP1BUF));
                }
            } else {
                // full read?
                if (spiPos == (uint8_t*) &glue +  sizeof(glue) - 1) {
                    spiPos = (uint8_t*) &glue.headers;
                    spiSection = spiPos;
                    SPI_MODE_RX;
                    events.spi = 1;
                } else {
                    spiPos++;
                    memcpy(&SSP1BUF , spiPos,  sizeof(SSP1BUF));
                }
            }
            return;
        }
    }
     
     
     

     
    post edited by acharnley - 2020/09/26 04:54:02

    Attached Image(s)

    #2
    acharnley
    Super Member
    • Total Posts : 617
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: SPI "Bidirection" Diagnosis (mimicking the PIC flash method) 2020/09/26 14:05:07 (permalink)
    0
    Still unable to crack it. I've since corrected a bug and get the following:
     

     
    uvlo should = 1 and storageVoltage I've forced to value 234 for testing.

    The TX side is working and repeatedly so the loop code is good. Either I'm pushing to the SPI buffer incorrectly or setting SPIO incorrectly but both look fine to me.

    Oh and I've noticed frequency is always 0xFF while storageVoltage jumps between 0XFFFF, 128 and 255.

    <info> app: fr 255
    <info> app: sv 128
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 128
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 128
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 128
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 128
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 192
    <info> app: fr 255


    Attached Image(s)

    #3
    acharnley
    Super Member
    • Total Posts : 617
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: SPI "Bidirection" Diagnosis (mimicking the PIC flash method) 2020/09/27 06:21:02 (permalink)
    0
    I changed the code a little to discard the read buffer (don't know if it should matter, probably not).

    And modified the switch statement so the SPI input and output are always assigned to RB7 and direction controlled via TRIS.
     
    Also disabling SPI when changing though it shouldn't matter as the CLK won't be going during this time. The ARM gives 1ms between direction change which should be plenty for the PIC16F18545 (32MHz HSINTOSC).
     
    I noticed SSP1CON1bits.WCOL gets set on the first transaction probably related to the data that comes through. After that it's all 1's.
     

    struct glueProto {
    glue_mode_t mode;
    struct {
    uint8_t headers[2];
    uint8_t outputs;
    uint8_t capacitorBand;
    uint8_t storageBand;
    uint8_t frontPattern;
    uint8_t rearPattern;
    } tx;
    struct {
    uint8_t frequency;
    uint16_t storageVoltage;
    uint8_t uvlo;
    uint8_t storageBand;
    uint8_t state;
    } rx;
    };

     
    <info> app: fr 255
    <info> app: sv 33023
    <info> app: fr 0
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 65535
    <info> app: fr 255
    <info> app: sv 65535
     
    (where fr = rx.frequency and sv = rx.storageVoltage)
     
     

     
    #define SPI_MODE_TX SSP1CON1bits.SSPEN = 0; TRISBbits.TRISB7 = 0; SSP1CON1bits.SSPEN = 1
    #define SPI_MODE_RX SSP1CON1bits.SSPEN = 0; TRISBbits.TRISB7 = 1; SSP1CON1bits.SSPEN = 1
     
    if (SPI_INT_FLAG) {
    CLRWDT();
    SPI_INT_FLAG = 0;
    LATAbits.LATA1 = SSP1CON1bits.WCOL;
    SSP1CON1bits.WCOL = 0;

    if (spiSection == (uint8_t* ) &glue.headers) {
    if (SSP1BUF == *spiPos) {
    spiPos++;
    if (spiPos == (uint8_t* ) &glue.rx) {
    spiSection = spiPos;
    }
    } else {
    spiPos = (uint8_t* ) &glue.headers;
    }
    } else if (spiSection == (uint8_t* ) &glue.rx) {
    *spiPos = SSP1BUF;
    spiPos++;
    if (spiPos == (uint8_t* ) &glue.tx) {
    spiSection = spiPos;
    SPI_MODE_TX;
    SSP1BUF = *spiPos;
    }
    } else {
    discard = SSP1BUF;
    // done?
    if (spiPos == (uint8_t*) &glue + sizeof(glue) - 1) {
    spiPos = (uint8_t*) &glue.headers;
    spiSection = spiPos;
    SPI_MODE_RX;
    events.spi = 1;
    } else {
    spiPos++;
    SSP1BUF = *spiPos;
    }
    }
    return;
    }
    }

    #4
    NorthGuy
    Super Member
    • Total Posts : 6349
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: SPI "Bidirection" Diagnosis (mimicking the PIC flash method) 2020/09/27 07:19:10 (permalink)
    +3 (3)
    acharnley
    I noticed SSP1CON1bits.WCOL gets set on the first transaction probably related to the data that comes through. After that it's all 1's.

     
    This means you're sending too fast. After your write SPIBUF on the PIC, you must wait for the transaction to complete, then write the next one. Otherwise, you get WCOL.
    #5
    acharnley
    Super Member
    • Total Posts : 617
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: SPI "Bidirection" Diagnosis (mimicking the PIC flash method) 2020/09/29 14:50:57 (permalink)
    0
    I'm not seeing it, you can see in my code I do one write with 
    SSP1BUF = *spiPos;

    And then the next write will only occur when the next interrupt has fired (which means the data has left already).

    I've been on to Microchip support and the guy says it's not possible without switching the PIC to master, but I don't think he realises the PIC already does it in programming mode and besides which it only dictates who has control of the clock.

    To recap here's the code. I've been over and over it and can't see any issue.


    if (SPI_INT_FLAG) {
            CLRWDT();
            SPI_INT_FLAG = 0;
            // headers used for sync
            if (spiSection == (uint8_t* ) &glue.headers) {
                if (SSP1BUF == *spiPos) {
                    spiPos++;
                    if (spiPos == (uint8_t* ) &glue.rx) {
                        spiSection = spiPos;
                    }
                } else {
                    spiPos = (uint8_t* ) &glue.headers;
                }
            // data placed into struct, tx discarded by ARM
            } else if (spiSection == (uint8_t* ) &glue.rx) {
                *spiPos = SSP1BUF;
                spiPos++;
                if (spiPos == (uint8_t* ) &glue.tx) {
                    spiSection = spiPos;
                    SPI_MODE_TX;
                    SSP1BUF = *spiPos;
                }
             // data pushed from struct, rx discarded by PIC
            } else {
                discard = SSP1BUF;
                // done?
                if (spiPos == (uint8_t*) &glue +  sizeof(glue) - 1) {
                    spiPos = (uint8_t*) &glue.headers;
                    spiSection = spiPos;
                    SPI_MODE_RX;
                    events.spi = 1;
                } else {
                    spiPos++;
                    SSP1BUF = *spiPos;
                }
            }
            return;
        }

     
     
    post edited by acharnley - 2020/09/29 14:55:06
    #6
    Jump to:
    © 2020 APG vNext Commercial Version 4.5