This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[C6720B] SPI slave boot problems

Other Parts Discussed in Thread: SPRC203

I have been struggling for the past several days trying to boot a TMS320C6720B using SPI slave boot mode.  I can successfully get through the Start-Word Syncrhronization (SWS) and the PING opcode and exchange, but can get no further.  The following exchanges are typical:

MCU sends 5853 and reads ffff (16-bit exchange),

MCU sends 5853 and reads 5253  (16-bit exchange; SWS complete),

MCU sends 5853590b and reads 52535253 (this and all remaining exchanges are 32-bit),

MCU sends 5853590b and reads 5253590b (PING exchange starts),

MCU sends 0000000a and reads 5253ffff (MCU sends PING count first time),

MCU sends 0000000a and reads ffff000a (MCU code strips off top 16 bits and calls this good; is this expected?)

MCU sends 00000001 and reads 0000000a,

MCU sends 00000001 and reads 00000001 (first PING value echoed properly),

MCU sends 00000002 and reads 00000001,

MCU sends 00000002 and reads 00000002 (second PING value echoed properly),

...

MCU sends 0000000a and reads 00000009,

MCU sends 0000000a and reads 0000000a (last PING value echoed properly, done with PING),

MCU sends 58535901 and reads 0000000a (MCU sends EnableCRC opcode, gets last PING value),

MCU sends 58535901 and reads 000a5901 (corrupted similar to PING count above; is this expected?),

MCU sends 58535901 and reads 5253ffff,

MCU sends 58535901 and reads ffffffff,

MCU sends 58535901 and reads ffffffff,

MCU sends 58535901 and reads ffffffff (this continues forever)

My questions:

1. Why is the PING count apparently echoed as 16 bits (ffff000a), not 32?  Is this expected?

2. Why is the response to the 58535901 opcode only correct in the low 16 bits?  Is this expected?

3. What did I do that started the endless ffffffff responses and how do I get out of it?

Note that I have performed the above exchanges from the MCU (an LPC2148) using both bit-banged SPI and hardware-implemented SPI with the same results.  I have confirmed the above exchanges at the MCU's I/O pins using an oscilloscope.  Every 32-bit exchange is sent as two 16-bit exchanges; MCU brings DSP's CS line high, then low (with suitable delay) between the two 16-bit exchanges.  The MCU code used above was based on the example code from the TI SPRC203 folder (BootUtils).

Karl

 

 

 

  • Karl,

    I am successfully booting an C6726 from an LPC2368, so don't dispair, it's possible!

    However, it took me quite some time to get it all figured out. Here are some tips:

    - My DSP gets a 12MHz clock, and with that I have to limit the initial SPI bit rate to 300KHz. I use 16-bit word length, CS MUST go low between words, and when sending a 32-bit word the 16 least-significant bits must be sent FIRST

    - What I do is send 2 words (discard whatever the DSP sends back simultaneously), then send 0xFFFF,FFFF to get the response back from the DSP. This may be the difference with your approach.

    So for the Start Word Sync:

    Send 0x5853, receive 0xFFFF

    Send 0x5853, receive 0x5253

    Send 0xFFFF, receive 0x5253

    Send 0xFFFF, receive 0x5253

    then for the Ping sequence:

    SIMO: 590B   5853    FFFF   FFFF   000A   0000    FFFF   FFFF   0001    0000    FFFF   FFFF

    SOMI: 5253    5253    590B   5253    FFFF   FFFF   000A   0000    000A   0000    0001    0000

     

    with SIMO being the data going TO the DSP, SOMI the data coming back.

     

    Hope this helps. Let me know if you need more info, I can send you scope shots etc. Note that it gets interesting once you get to the 'SET Command', last time I checked the documentation had the sequence of the parameters for that command messed up.

     

    Adriaan.

     

     

     

  • Thanks, Adriaan!  The key I was missing was sending the LSH of the 32-bit word first.  I can now get through the PING and the next command, and all responses so far are as expected.  It's full speed into the next obstacle...

         Karl

     

  • Glad I could help. I'll venture a guess that your next obstacle will be the SET command, which you need to get the PLL configured so you'll be able to up the SPI speed to get your code loaded at a reasonnable speed. I can get it to run at 3MHz.

    The trick is that the SET command needs to be followed by 4 parameter words described in the TI documentation, but in the following order:

    - type

    - address

    - data

    - wait cycles (sleep)

    Good luck.

    Adriaan.

  • Spot on, Adriaan!  The SET command does, indeed, require transfer of the four words to the DSP in an order that differs from the order in which they are written to the AIS file.  Note that the sample implementation (em_protocol.c) in TI's BootUtils folder does NOT alter the order of the words when it sends them to the DSP (the author calls a SET opcode a BOOT_TABLE opcode).  Note also that the sample program was written in the 2002-2004 timeframe.  I'm guessing that the bootloader code got changed and the required updates to the example were never added.

    Naturally, the bootloader app note (spraa69c.pdf) makes no mention of this vital information.  I pity the poor sods who had to discover this rearrangement by trial and error.

    Thanks for all your help on this effort.  I can now download a full app to the DSP, modify the PLL and EMIF register via an AIS file, and switch SPI clock rates on-the-fly during the app download.

    Anything else I should watch out for?

         Karl

     

  • Glad I could help.

    This booting has been the biggest issue I've run into with the C672x, other than installation issues of CCS.

    Just in case you're planning to use the SPI port to talk between ARM and DSP, once the DSP is running: you should use DMA ( dMAX ) for that, and when you do the documentation is wrong on the ESIZE bits in the EVENT13 register: these have to be set to 2 to transfer the 16-bit wide SPI words.

    Have fun,

    Adriaan.

  • Adriaan,

    Would you mind pointing out where specifically in the documentation the ESIZE is incorrectly defined? If this is the case we want to make sure it gets fixed. According to the dMAX guide depending on what type of transfer you configure will change the effect of ESIZE.

  • KarlLunt said:
    Spot on, Adriaan!  The SET command does, indeed, require transfer of the four words to the DSP in an order that differs from the order in which they are written to the AIS file.  Note that the sample implementation (em_protocol.c) in TI's BootUtils folder does NOT alter the order of the words when it sends them to the DSP (the author calls a SET opcode a BOOT_TABLE opcode).  Note also that the sample program was written in the 2002-2004 timeframe.  I'm guessing that the bootloader code got changed and the required updates to the example were never added.

    Naturally, the bootloader app note (spraa69c.pdf) makes no mention of this vital information.  I pity the poor sods who had to discover this rearrangement by trial and error.


    I have run into this problem with the SET command and reported this, but unfortunately the documentation has not yet been updated to reflect this. I know that this is a frustrating problem, but hopefully we can make this more easily available until everything is fixed.

  • Tim,

    My mistake. I reviewed the documentation, and found it to be correct. My apologies.

    I didn't relalize that the ESIZE enumeration was different for SPI than for General purpose transfers.

    Adriaan.

  • OK, thanks for clearing that up [:)]

  • Tim or anyone,

    I have a problem getting the bootloading to happen fast enough. SysClk 1-3 default to 32, 16, 11 MHz and should become 246, 123, 10 MHz after the SET commands are executed. I have checked SysClk3 (EMIF Clk) and it is not changing after the SET commands.

    I can speed up the SPI bus and interword delay after the SET commands, but I still need a 20 usec gap between each word written during the Section_Loads. One other oddity is that I had to put dummy 0xFFFF writes (just as you do after writing opcodes) between the SET parameters or it would hang on the SET opcode (the DSP returned 0x52535253 instead of 0x52535907). I suspect this is not a good thing to do, though; the DSP bootload code is written to respond to dummy writes after receiving an opcode, but probably not after receiving function parameters.

    Thanks for any help,

    Steve Gallagher

     

  • Here is a code snippet (part of my DSP setup) that processes the SET opcode during download.  This code module transfers about 20K bytes to the DSP in under 1/4 second; as part of the transfer, the DSP PLL is upshifted to 60 MHz and the SPI clock is upshifted accordingly.  pAddr points to the next 32-bit value in the DSP app to download.  sw_delay() is a spin-wait delay routine that waits the prescribed amount of time before sending the next word.  The module does not send any 0xffff dummy writes.  pll_configured determines the delay between two 16-bit exchanges with the DSP; if this value is FALSE, the MCU inserts a delay of about 1/2 msec between 16-bit words.  (I bet there's a way to make this block come through as code [fixed-width text] but I can't find it quickly...)

    /*
     *  state DSP_PROCESS_OPCODE_SET
     *
     *  This state writes a block of AIS data directly to a memory area of the DSP.
     *  This opcode is usually used to modify registers within the DSP, such as configuring
     *  the PLL and EMIF.
     *
     *  The last value in the 4-word table following a Set opcode is a Sleep value.  This
     *  value is the number of DSP clock cycles to delay before sending any other AIS
     *  commands.  If the DSP's PLL has not been configured, each count in the Sleep
     *  value equals 166 nsecs.  If the DSP's PLL has been configured, each count in
     *  the Sleep value equals 16.6 nsecs (assumes 60 MHz clock). 
     */
                case  DSP_PROCESS_OPCODE_SET:
                    SetAddr = *pAddr++;                        // first word after Set opcode is Addr in DSP memory
                    SetData = *pAddr++;                        // second word is data value
                    SetType = *pAddr++;                        // third word is type descriptor
                    SetSleep = *pAddr++;                    // fourth word is sleep count

                    ExchangeU32WithDSP(SetType);            // DSP wants type descriptor first...
                    ExchangeU32WithDSP(SetAddr);            // then address...
                    ExchangeU32WithDSP(SetData);            // then data...
                    ExchangeU32WithDSP(SetSleep);            // finally, sleep count

                    if (pllConfigured)  sw_delay((SetSleep/10) + 1);    // 60000 counts = 1 msec; argument must be at least one
                    else                sw_delay(SetSleep*2);            // 6000 counts = 1 msec
                    SETBlockTransferred = TRUE;                // show we have sent at least one Set opcode and data block
                    state = DSP_XCHANGE_SYNCWORD;
                    break;
               

  • Karl,

    Thanks for your quick response. The only difference I see with your code is that you are using the sleep arg to wait on the MCU side. I didn't think that was necessary since you have to poll on the next opcode anyway. I'll try that and see if it works.

    Thanks,

    Steve

  • Karl,

    I found my problem. Bad pointer arithmetic accessing the out-of-order parameters. Turns out I was telling the DSP to sleep for a very long time, and that's just what I was seeing.

    BTW, I am not delaying on the MCU side and it works fine.

    Thanks again,

    Steve Gallagher