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

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

Jump to solution
1,388 Views
zwilcox
Contributor IV

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); 
      }
   }
}


‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
Reply
1 Solution
1,227 Views
zwilcox
Contributor IV

Thanks for your reply.

Apparently it was a caching issue.   Clearing the cache resolved it :smileyhappy:

View solution in original post

0 Kudos
Reply
2 Replies
1,227 Views
lukaszadrapa
NXP TechSupport
NXP TechSupport

Hi,

I'm not sure what's wrong on your side but this minimalist code is working as expected. Loop mode is used in this test:

unsigned char rec_data[10];

void ESCI_A_Init(void)
{  
  ESCI_A.CR1.B.SBR = 64000000/16/9600;  
  ESCI_A.CR1.B.LOOPS = 1;  
  ESCI_A.CR1.B.TE = 1;  
  ESCI_A.CR1.B.RE = 1;  
  ESCI_A.CR2.R = 0x2800;              
}

void EDMA_ESCI_Receive(void)
{
  uint8_t rx_channel = 19;
 
  EDMA.TCD[rx_channel].SADDR = (vuint32_t)&ESCI_A.DR.R + 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)rec_data;        // 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 = 5;                    // Number of minor loop iterations
  EDMA.TCD[rx_channel].CITER = 5;                    // Number of minor loop iterations
  EDMA.TCD[rx_channel].D_REQ = 1;                        // Disable channel when major loop is done
  EDMA.TCD[rx_channel].INT_HALF = 0;                     // Interrupts is not used
  EDMA.TCD[rx_channel].INT_MAJ = 0;                      // Interrupt is enabled
  EDMA.TCD[rx_channel].MAJORE_LINK = 0;                  // Dynamic program is not used
  EDMA.TCD[rx_channel].E_SG = 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;
}
    
void main(void)
{
    unsigned int j;

    ESCI_A_Init();
    EDMA_ESCI_Receive();

    //send 5 characters and receive them via DMA

    for (j=0; j< 5; j++)
    {    
        while (ESCI_A.SR.B.TDRE == 0) {}       
        ESCI_A.SR.R = 0x80000000;              /* Clear TDRE flag */
        ESCI_A.DR.B.D = (unsigned char)j;          /* Transmit 8 bits Data */        
    }

    while(1)
    {
    }
}

Regards,

Lukas

0 Kudos
Reply
1,228 Views
zwilcox
Contributor IV

Thanks for your reply.

Apparently it was a caching issue.   Clearing the cache resolved it :smileyhappy:

0 Kudos
Reply