Hi ,
We are using the MPC5674F with RX DMA for an SPI-based external CAN controller (MCP2518FD).We are able to transmit successfully using eDMA channel 12 for DSPI_B without issues.
For reception via DMA, we configured two channels:
The configuration is:
Channel 12 transmits a dummy message and then links to channel 13 for receiving.
Once reception is complete, channel 13 links back to channel 12, continuing the loop until 16 bytes are received.
The RX channel generates an interrupt at the end of reception of all 16 bytes.
We successfully receive messages from the slave, but some bytes in the RX DMA buffer are empty.
Example (Expected continuous data):
FF FF FF 1F 18 00 00 00 01 02 03 04 05 06 07 08
Observed (Bytes are empty in RX DMA buffer):
FF FF FF 1F 18 00 00 00 01 02 00 03 04 05 06 07 00
Debug window of CAN_RX_data
Observations:
A middle byte in rx buffer is consistently zero
The last byte also appear as zero
This issue does not occur in polling mode
FIFO is flushed before reception
Questions:
Is there a recommended DMA configuration or workaround to prevent RX DMA from skipping bytes when using MPC5674F with SPI and the MCP2518FD?
What is the best approach to reliably receive data via DMA without losing any bytes?
#define FRAME_SIZE_BYTES 4
#define NUM_ITERATIONS 16 // total number of 4-byte transfers
// Dummy data to send
uint32_t dummy_data = 0xFF;
vuint16_t can_rx_data[NUM_ITERATIONS + 1];
// ---------------- TX Channel 12 ----------------
void eDMA_TCD_tx4BYTE_init()
{
EDMA_A.TCD[12].SADDR = (vuint32_t)&dummy_data;
EDMA_A.TCD[12].SSIZE = 2; // 32-bit source
EDMA_A.TCD[12].SOFF = 0;
EDMA_A.TCD[12].SLAST = 0;
EDMA_A.TCD[12].SMOD = 0;
EDMA_A.TCD[12].DADDR = (vuint32_t)&DSPI_B.PUSHR.R;
EDMA_A.TCD[12].DSIZE = 2; // 32-bit dest
EDMA_A.TCD[12].DOFF = 0;
EDMA_A.TCD[12].DLAST_SGA = 0;
EDMA_A.TCD[12].DMOD = 0;
EDMA_A.TCD[12].NBYTES = FRAME_SIZE_BYTES;
EDMA_A.TCD[12].BITER = NUM_ITERATIONS ;
EDMA_A.TCD[12].CITER = NUM_ITERATIONS ;
EDMA_A.TCD[12].CITERE_LINK = 0;
EDMA_A.TCD[12].BITERE_LINK = 0;
// Minor-loop linking to RX channel
EDMA_A.TCD[12].MAJORE_LINK = 1;
EDMA_A.TCD[12].MAJORLINKCH = 13;
EDMA_A.TCD[12].D_REQ = 1;
EDMA_A.TCD[12].INT_HALF = 0;
EDMA_A.TCD[12].INT_MAJ = 0; // only RX channel triggers ISR
EDMA_A.TCD[12].E_SG = 0;
EDMA_A.TCD[12].BWC = 0;
EDMA_A.TCD[12].DONE = 0;
EDMA_A.TCD[12].ACTIVE = 0;
EDMA_A.CR.B.CLM = 1;
}
// ---------------- RX Channel 13 ----------------
void eDMA_TCD_rx4BYTE_init()
{
EDMA_A.TCD[13].SADDR = (vuint32_t)&DSPI_B.POPR.R + 2;
EDMA_A.TCD[13].SSIZE = 1; // 2 bytes
EDMA_A.TCD[13].SOFF = 0;
EDMA_A.TCD[13].SLAST = 0;
EDMA_A.TCD[13].SMOD = 0;
EDMA_A.TCD[13].DADDR = (vuint32_t)&can_rx_data[0];
EDMA_A.TCD[13].DSIZE = 1; // 2 bytes
EDMA_A.TCD[13].DOFF = 2; // 2 bytes
EDMA_A.TCD[13].DLAST_SGA = -(2 * NUM_ITERATIONS);
EDMA_A.TCD[13].DMOD = 0;
EDMA_A.TCD[13].NBYTES = 2; // 2 bytes
EDMA_A.TCD[13].BITER = NUM_ITERATIONS;
EDMA_A.TCD[13].CITER = NUM_ITERATIONS;
EDMA_A.TCD[13].CITERE_LINK = 0;
EDMA_A.TCD[13].BITERE_LINK = 0;
// Minor-loop linking back to TX channel
EDMA_A.TCD[13].MAJORE_LINK = 1;
EDMA_A.TCD[13].MAJORLINKCH = 12;
EDMA_A.TCD[13].D_REQ = 1;
EDMA_A.TCD[13].INT_HALF = 0;
EDMA_A.TCD[13].INT_MAJ = 1; // ISR triggers at end of full frame
EDMA_A.TCD[13].E_SG = 0;
EDMA_A.TCD[13].BWC = 0;
EDMA_A.TCD[13].DONE = 0;
EDMA_A.TCD[13].ACTIVE = 0;
}
// this will be called at event of RX gpio interrupt from slave
void bsp_ext_can_initiate_rx_dma()
{
// command + FIFO Address
uint16_t cmd_pckt = 0x3468;
uint8_t dummy = 0;
DSPI_B.RSER.B.RFDFDIRS = 1;
DSPI_B.RSER.B.TFFFDIRS = 1;
//enable chipselect
SIU.GPDO[105].B.PDO = 0;
//send command Rd command.
bsp_dspi_write_via_polling(&DSPI_B, (uint8_t *)&cmd_pckt, 2);
// Flush RX FIFO if there's any leftover data
while ((DSPI_B.SR.R & 0x00020000U) == 0x00020000U)
{
// Clear any residual data in the rx fifo
dummy =DSPI_B.POPR.R;
// Clear RFDF Receive FIFO Drain Flag
DSPI_B.SR.R |= 0x00020000U;
}
DSPI_B.RSER.R |= 1u << (31u - 6u); //TFFFRE
DSPI_B.RSER.R |= (1u << (31u - 14u)); //RFDFRE
//invoke CH12,13 for DMA
EDMA_A.SERQR.R = 13; // RX first (safe)
EDMA_A.SERQR.R = 12; // TX starts clock
}
void DMA_RX_end_ISR(void)
{
EDMA_A.CDSBR.R = 13; // Clear DONE status register
EDMA_A.CIRQR.B.CINT = 13; // Clear interrupt
DSPI_B.RSER.R &= ~(1u << (31u - 6u)); // Disable TFFRE
DSPI_B.RSER.R &= ~(1u << (31u - 14u)); // Disable RFDFRE
DSPI_B.SR.B.RFDF = 1; // Clear RX FIFO drain flag
/* Clear flags */
DSPI_B.SR.B.TCF = 1;
DSPI_B.SR.B.EOQF = 1;
/* Flush TX FIFO */
DSPI_B.MCR.B.CLR_TXF = 1;
DSPI_B.MCR.B.CLR_RXF = 1;
// disable cs
SIU.GPDO[105].B.PDO = 1;
}
let me know any additional details or information required for this problem
Thanks
Narendra.C
MPC5674F