TMS320F28335: SPI comunnication issue

Part Number: TMS320F28335

Hi,

I am having trouble configuring SPI on a TMS320F28335. It is configured as a slave, and the MCBSP protocol is used for this. I am also using DMA for communication with an ESP32-C3 programmed as an SPI master.

The MCBSP is configured for 128-byte transmissions, and the DMA handles 12 transmissions of 128 bytes each (for a total of 1,536 bytes).

However, I receive the first 128-byte word in the ESP at the end of the buffer. In other words, the ESP's receive buffer stores the second 128-byte word and the first one as if they were the last 128 bytes.

Below, I will attach the TMS320 configuration code.#define NUM_MESSAGE_WIM (128U)        /*Number of message in the communication*/
#define WIM_MESSAGE_LENGTH_BYTES (12U)    /*Number of Bytes each word*/
#define TOTAL_BYTES (NUM_MESSAGE_WIM * WIM_MESSAGE_LENGTH_BYTES)struct MCBSP_REGS ApplyWimSpiInterfaceSlaveConfiguration(volatile struct MCBSP_REGS mcbspRegs)
{    mcbspRegs.SPCR2.all = 0x0000;        // Reset FS generator, sample rate generator & transmitter    mcbspRegs.SPCR1.all = 0x0000;        // Reset Receiver, Right justify word, Digital loopback dis.
    mcbspRegs.SPCR1.bit.DLB = 0;         // Loopback mode deactivated    mcbspRegs.PCR.bit.CLKXM = 0;         // it is driven by the SPI master
    mcbspRegs.PCR.bit.SCLKME = 0;        // Sample rate generator input clock mode bit.
    mcbspRegs.PCR.bit.FSXM = 0;          // Slave does not transmit frame synch. It is driven by the SPI master
    mcbspRegs.PCR.bit.FSXP = 1;          // Tx frame-synchronization pulses are active low (CS)
    mcbspRegs.PCR.bit.FSRM = 0;          // Rx frame synchronization is supplied by an external source via the FSR pin.    mcbspRegs.SPCR1.bit.CLKSTP = 3;      // Clock stop mode, without clock delay    /** Together with CLKXP/CLKRP determines clocking scheme*/
    mcbspRegs.PCR.bit.CLKXP = 1;         // Transmit data is sampled on the rising edge of CLKX.
    mcbspRegs.PCR.bit.CLKRP = 1;         // Receive data is sampled on the falling edge of MCLKR.    /** Setup time on the FSX signal*/
    mcbspRegs.RCR2.bit.RDATDLY = 0U;     // Setup time on reception
    mcbspRegs.XCR2.bit.XDATDLY = 0U;     // Setup time on transmission    /**Word and Frame length*/
    mcbspRegs.RCR1.bit.RWDLEN1 = 0;      // 8-bit per word transmitted
    mcbspRegs.RCR1.bit.RFRLEN1 = NUM_MESSAGE_WIM - 1U;      // 1-word per frame transmitted    mcbspRegs.XCR1.bit.XWDLEN1 = 0;      // 8-bit per word received
    mcbspRegs.XCR1.bit.XFRLEN1 = NUM_MESSAGE_WIM - 1U;      // 1-word per frame received    mcbspRegs.SRGR2.all = 0x2000;        // CLKSM=1, FPER = 0 CLKG periods, FSGM=0 (sync. automatic)
    mcbspRegs.SRGR1.all = 0x0000;        // Frame Width = 1 CLKG period, CLKGDV = 1 (Slave)    /** In your McBSP configuration */
    /* Small delay to ensure receive is ready */
    _delay_loop();     /*Wait at least 2 SRG clock cycles*/
    initWimDmaContinuous(); /*Initialization of dma protocol*/
    _delay_loop();    mcbspRegs.SPCR2.bit.GRST = 0;        // Enable the sample rate generator
    mcbspRegs.SPCR2.bit.XRST = 0;        // Release TX from Reset
    mcbspRegs.SPCR1.bit.RRST = 0;        // Release RX from Reset
    mcbspRegs.SPCR2.bit.FRST = 0;    return mcbspRegs;
}void initWimDmaContinuous(void)
{    EALLOW;
    DmaRegs.DMACTRL.bit.HARDRESET = 1;        // Reset the whole DMA and abort any current access
    __asm(" NOP");                            // Only 1 NOP needed per Design
    DmaRegs.CH1.MODE.bit.CHINTE = 0;          // Interrupt disabled    /** Channel 1, McBSPB transmit */    DmaRegs.CH1.BURST_SIZE.all = 0;            // 1 word/burst
    DmaRegs.CH1.SRC_BURST_STEP = 0;           // no effect when using 1 word/burst
    DmaRegs.CH1.DST_BURST_STEP = 0;           // no effect when using 1 word/burst    DmaRegs.CH1.TRANSFER_SIZE = (TOTAL_BYTES)-1;     // Interrupt every 128 bursts/transfer * 12 bytes/word - 1    DmaRegs.CH1.SRC_TRANSFER_STEP = 1;        // Move to next word in buffer after each word in a burst
    DmaRegs.CH1.DST_TRANSFER_STEP = 0;        // Don't move destination address    uint8_t *srcAddrTx = &wimSpiTxBuffer[0];
    DmaRegs.CH1.SRC_ADDR_SHADOW = (uint32_t) srcAddrTx;       // Start source address = buffer
    DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (uint32_t) srcAddrTx;    DmaRegs.CH1.DST_ADDR_SHADOW = (uint32_t) &McbspaRegs.DXR1.all;          // Start destination address = McBSP DXR
    DmaRegs.CH1.DST_BEG_ADDR_SHADOW = (uint32_t) &McbspaRegs.DXR1.all;    DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;     // Clear peripheral interrupt event flag
    DmaRegs.CH1.CONTROL.bit.ERRCLR = 1;        // Clear sync error flag    DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF;      // Put to maximum - don't want destination wrap
    DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF;         // Put to maximum - don't want source wrap    DmaRegs.CH1.MODE.bit.ONESHOT = 0;
    DmaRegs.CH1.MODE.bit.CONTINUOUS = 1;       // Do not stop after each transfer.    DmaRegs.CH1.MODE.bit.SYNCE = 0;            // No sync signal
    DmaRegs.CH1.MODE.bit.SYNCSEL = 0;          // No sync signal    DmaRegs.CH1.MODE.bit.CHINTE = 0;           // Disable channel interrupt
    DmaRegs.CH1.MODE.bit.CHINTMODE = 0;        // Disable Interrupt at end of transfer
    DmaRegs.CH1.MODE.bit.PERINTE = 1;          // Enable peripheral interrupt event    DmaRegs.CH1.MODE.bit.PERINTSEL = DMA_MXEVTA;   // Peripheral interrupt select    DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;     // Clear any spurious interrupt flags    /** Channel 2, McBSPA Receive */    DmaRegs.CH2.MODE.bit.CHINTE = 0;           // Interrupt disabled    DmaRegs.CH2.BURST_SIZE.all = 0;            // 1 word/burst
    DmaRegs.CH2.SRC_BURST_STEP =  0;            // no effect when using 1 word/burst
    DmaRegs.CH2.DST_BURST_STEP = 0;             // no effect when using 1 word/burst    DmaRegs.CH2.TRANSFER_SIZE = (TOTAL_BYTES)-1;     // Interrupt every 128 bursts/transfer * 12 bytes/word - 1    DmaRegs.CH2.SRC_TRANSFER_STEP = 0;         // Don't move source address
    DmaRegs.CH2.DST_TRANSFER_STEP = 1;         // Move to next word in buffer after each word in a burst    DmaRegs.CH2.SRC_ADDR_SHADOW = (uint32_t) &McbspaRegs.DRR1.all;          // Start address = McBSPB DRR
    DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = (uint32_t) &McbspaRegs.DRR1.all;    uint8_t *dstAddrRx = &wimSpiRxBuffer[0];
    DmaRegs.CH2.DST_ADDR_SHADOW = (uint32_t) dstAddrRx;       // Start address = Receive buffer (for McBSP-A)
    DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (uint32_t) dstAddrRx;    DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;      // Clear peripheral interrupt event flag
    DmaRegs.CH2.CONTROL.bit.ERRCLR = 1;         // Clear sync error flag    DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF;           // Put to maximum - don't want destination wrap
    DmaRegs.CH2.SRC_WRAP_SIZE = 0xFFFF;         // Put to maximum - don't want source wrap    DmaRegs.CH2.MODE.bit.ONESHOT = 0;
    DmaRegs.CH2.MODE.bit.CONTINUOUS = 1;        // Do not stop after each transfer.    DmaRegs.CH2.MODE.bit.SYNCE = 0;            // No sync signal
    DmaRegs.CH2.MODE.bit.SYNCSEL = 0;          // No sync signal    DmaRegs.CH2.MODE.bit.CHINTE = 0;            // Disable channel interrupt
    DmaRegs.CH2.MODE.bit.CHINTMODE = 0;         // Disable Interrupt at end of transfer
    DmaRegs.CH2.MODE.bit.PERINTE = 1;           // Enable peripheral interrupt event    DmaRegs.CH2.MODE.bit.PERINTSEL = DMA_MREVTA;   // Peripheral interrupt select    DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;      // Clear any spurious interrupt flags
    EDIS;
}

 

Best regards

  • Hi Nacho,

    Can you scope the pins to see if the correct/expected data is being transmitted by the F2833x? This seems like it could be an issue with how the ESP32-C3 is receiving rather than with how the F2833x is transmitting data.

    Best Regards,

    Delaney 

  • Hello, Delany:

    I think I forgot to mention that this issue only occurs during the first transmission after turning on the devices.

    Therefore, I believe it is more of an issue with the transmission data after restarting than an issue with reception.

    The steps to reproduce the issue are as follows:

    First, I turn on the slaves.

    I wait about 5 seconds.

    Then I turn on the master.

    The first transmission I see in the master's RX buffer is offset. Therefore, the data I expected to see in position 2 is in the first position, and the data I expected to see in the first position is in the last position.

    When the master requests a new transmission, in this case all the data is in its correct position. This problem only occurs in the first transmission after turning on the devices.

    I have attached some screenshots from the Saleae logic analyser. Please note that the MISO message is encrypted with AES265.

  • Hi Nacho,

    To clarify, is the data you're seeing on the scope for the MISO line on the first transmission after power up (transmitted by the F2833x) what you expect to see? Does this data sequence differ from what you see in the ESP32-C3 receive buffer on the first transmission?

    This will help narrow down which device is the issue here - master or slave.

    Best Regards,

    Delaney

  • Hello, Delaney:

    The data sequence I can see in the ESP32-C3 receive buffer in the first transmission is the same as what I can see in the logic analyser on the MISO line in the first transmission.

    Kind regards.

  • Hi Nacho,

    I see, ok. This would be something with the F2833x then. I will loop in the MCBSP expert to take a look. 

    Best Regards,

    Delaney