AnsweredAssumed Answered

MPC5566:  UART RX DMA doesn't put in destination buffer

Question asked by Zachary Wilcox on May 21, 2019
Latest reply on May 23, 2019 by Zachary Wilcox

I'm attempting to set the DMA for the RX of the UART/ESCI.

The DMA finishes but the destination buffer never received the that was received.

 

Why is it the DMA finishes but doesn't put the data in the destination buffer address?

 

Edit:  I can receive over the uart by polling the CR1 register or interrupting when the UART received.

Edit:  After the DMA is finished, I print of the status register.  The status register is 0xE0_01_C0_00

// DMA channel used for ESCI
#define DMA_ESCIA_TX 18
#define DMA_ESCIA_RX 19

#define DMA_ESCIB_TX 34
#define DMA_ESCIB_RX 35

void esci_init_default(struct ESCI_tag pEsci)

    pEsci->CR1.R = 0x0005000C;
            // SCI Baud rate : 1000.0000 khz
            // Loop Selected : Disable
            // Receiver Source : Transmitter connected Internal
            // Data Format : 8 bits long
            // Wake-up condition : Idle Line wakeup
            // Idle Line Type : Count at Start bit
            // Parity Bit : Disable
            // Parity Type : Even
            // Transmit Interrupt Enable : Disable
            // Transmission Complete Interrupt : Disable
            // Receive Full Interrupt : Enable
            // Idle Line Interrupt : Disable
            // Transmitter : Enable
            // Receiver : Enable
    uint8_t tx_channel = pEsci == &ESCI_A ? DMA_ESCIA_TX : DMA_ESCIB_TX;
    uint8_t rx_channel = pEsci == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;

    EDMA.TCD[tx_channel].DONE = 1;
    EDMA.TCD[rx_channel].DONE = 1;

    pEsci->CR2.R = 0x2C00;  // enable DMA
                // Fast Bit Error detection : Disable
            // Bit-Error Stop : Enable
            // Bit Error Interrupt : Disable
            // Activate Rx DMA Channel : Enable
            // Activate Tx DMA Channel : Enable
            // Break Transmit Character Length : 10 bit
            // Bit Error Sample Mode : RT clock 9
            // SCI bit error stop : Disable
            // Overrun error Interrupt : Disable
            // Noise flag Interrupt : Disable
            // Frame Error Interrupt : Disable
            // Parity flag Interrupt : Disable
     pEsci->LCR.R = 0x00000000;
            // LIN bus wake-up : Enabled
            // Wake-up delimiter time : 4
            // LIN Debug Mode : Disabled
            // LIN Mode : Disabled
            // Double Stop Flags : Disabled
            // Activate Parity Generation : Disabled
            // RxREG Ready Interrupt : Disabled
            // TxREG Ready Interrupt : Disabled
            // Rx Wakeup Interrupt : Disabled
            // Slave timeout error Interrupt : Disabled
            // Physical bus error Interrupt : Disabled
            // CRC Error Interrupt : Disabled
            // Checksum error Interrupt : Disabled
            // Frame Complete Interrupt : Disabled
            // Overflow Interrupt : Disabled
}

void EDMA_ESCI_Receive(struct ESCI_tag* eSCI, uint8_t *bufptr, uint32_t count)
{

  uint8_t rx_channel = eSCI == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;
  EDMA.TCD[rx_channel].SADDR = (vuint32_t)&eSCI->DR + 1; // Load address of source data
  EDMA.TCD[rx_channel].SSIZE = 0;                        // Read 2**0 = 1 byte per transfer
  EDMA.TCD[rx_channel].SOFF = 0;                         // Do not increment source addr
  EDMA.TCD[rx_channel].SLAST = 0;                        // After major loop, reset src addr
  EDMA.TCD[rx_channel].SMOD = 0;                         // Source modulo feature not used

  EDMA.TCD[rx_channel].DADDR = (vuint32_t)bufptr;        // Load address of destination
  EDMA.TCD[rx_channel].DSIZE = 0;                        // Write 2**0 = 1 byte per transfer
  EDMA.TCD[rx_channel].DOFF = 1;                         // Increment destination addr
  EDMA.TCD[rx_channel].DLAST_SGA = 0;                    // After major loop, no dest addr change
  EDMA.TCD[rx_channel].DMOD = 0;                         // Destination modulo feature not used
 
  EDMA.TCD[rx_channel].NBYTES = 1;                       // Transfer 1 byte per minor loop
  EDMA.TCD[rx_channel].BITER = count;                    // Number of minor loop iterations
  EDMA.TCD[rx_channel].CITER = count;                    // Number of minor loop iterations
  EDMA.TCD[rx_channel].DREQ = 1;                        // Disable channel when major loop is done
  EDMA.TCD[rx_channel].INTHALF = 0;                     // Interrupts is not used
  EDMA.TCD[rx_channel].INTMAJ = 1;                      // Interrupt is enabled
  EDMA.TCD[rx_channel].MAJORELINK = 0;                  // Dynamic program is not used
  EDMA.TCD[rx_channel].ESG = 0;
  EDMA.TCD[rx_channel].BWC = 0;                          // Default bandwidth control- no stalls
  EDMA.TCD[rx_channel].START = 0;                        // Initialize status flags
  EDMA.TCD[rx_channel].DONE = 0;
  EDMA.TCD[rx_channel].ACTIVE = 0;
 
  // Enable the rx_channel
  EDMA.SERQR.R = rx_channel;
}

int EDMA_ESCI_IsRxDMADone(struct ESCI_tag* eSCI)
{

    uint8_t rx_channel = eSCI == &ESCI_A ? DMA_ESCIA_RX : DMA_ESCIB_RX;

     return (EDMA.TCD[rx_channel].DONE == 1);
}

int esci_setBaudRate(struct ESCI_tag* pEsci , int baudRate)
{
    if (pEsci == NULL) return -1;

    pEsci->CR1.B.SBR = (BD_CPU_CLK_HZ / (16 * baudRate)); //set baud rate

    return ((BD_CPU_CLK_HZ)/(16 * pEsci->CR1.B.SBR));
}

#define COMMAND_BUFFER_SIZE 3
uint8_t  dma_buffer[COMMAND_BUFFER_SIZE] = {0};

void main(void)
{
   esci_init_default(&ESCI_A);
   esci_setBaudRate(&ESCI_A, 9600);  // works

   memset(dma_buffer, 0x55, COMMAND_BUFFER_SIZE);
   EDMA_ESCI_Receive(&ESCI_A, dma_buffer, 1);
   while(1)
   {
     if(EDMA_ESCI_IsRxDMADone(&ESCI_A))
     {
         WriteUARTN(&ESCI_A.SR.R, 4);
         //this just prints whatever was memset :(
         WriteUARTN(dma_buffer, COMMAND_BUFFER_SIZE);
      memset(dma_buffer, 0x55, COMMAND_BUFFER_SIZE);
         EDMA_ESCI_Receive(&ESCI_A, dma_buffer, 1);
      }
   }
}


Outcomes