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
