Missing data Using XDMAC to send and receive over USART

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to send three bytes of data over USART (RS232) to a PanelPilot and receive three bytes on the same USART on the E70 using the XDMAC. To test my code I have connected the TXD2 and RXD2 pins on the E70 Xplained board (PD15 and PD16) and expect to get the same three bytes back again in "usart_receive_buffer".

 

However, this is not what I am finding. I am seeing the expected data on the logic analyser connected to TXD2/RXD2 but it is not coming into usart_receive_buffer. I am seeing the last byte in USART2->US_RHR so the connection is ok. Some data is intermittently coming through to the receive buffer, but usually not in the order it is sent.

 

Any ideas what could be going wrong?

 

Here is the code I have used to setup two channels of the XDMAC:

void XDMAC_setup(void) {
    // USART2 TX DMA Channel
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CDA = (uint32_t)&USART2->US_THR;				// Destination address is US_THR
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CBC = 2;							// Single microblock at a time
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CC = (XDMAC_CC_TYPE_PER_TRAN |				// memory to peripheral transcation
        XDMAC_CC_MBSIZE_SINGLE |									// Memory burst size 1
        XDMAC_CC_SAM_INCREMENTED_AM |								        // Source address increment (buffer)
        XDMAC_CC_DAM_FIXED_AM |									        // Dest address fixed (US_THR)
        XDMAC_CC_DSYNC_MEM2PER |									// Mem to peripheral transfer
        XDMAC_CC_CSIZE_CHK_1 |									        // Chunk size 1
        XDMAC_CC_DWIDTH_BYTE |									        // 8 bit data width
        XDMAC_CC_SIF_AHB_IF0 |									        // See datasheet section 19.2.3 for system bus connections
        XDMAC_CC_DIF_AHB_IF1 |
        XDMAC_CC_PERID(DMA_USART2_TX_PERID));
    XDMAC->XDMAC_GE |= 1 << DMA_CH_USART2_TX;								// enable TX channel
    //
    // USART2 RX DMA Channel
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CSA = (uint32_t)&USART2->US_RHR;				// Source address is US_THR
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDA = (uint32_t)&usart_receive_buffer;		        // Destination address is buffer
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CBC = 2;							// Single microblock at a time
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CC = (XDMAC_CC_TYPE_PER_TRAN |				// not memory to memory transaction
        XDMAC_CC_MBSIZE_SINGLE |									// Memory burst size 1
        XDMAC_CC_SAM_FIXED_AM |										// Source address fixed (US_RHR)
        XDMAC_CC_DAM_INCREMENTED_AM |									// Dest address increment (buffer)
        XDMAC_CC_DSYNC_PER2MEM |									// peripheral to mem transfer
        XDMAC_CC_CSIZE_CHK_1 |										// Chunk size 1
        XDMAC_CC_DWIDTH_BYTE |										// 8 bit data width
        XDMAC_CC_SIF_AHB_IF1 |										// See datasheet section 19.2.3 for system bus connections
        XDMAC_CC_DIF_AHB_IF0 |
        XDMAC_CC_PERID(DMA_USART2_RX_PERID));

    num_samples = 3;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDA = (uint32_t)&usart_receive_buffer;		// Destination address is buffer
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CUBC = num_samples;				// Set microblock size to be the size requested
    xdmaint = XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CIS;					// Clear any pending interrupts for this channel
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CNDC = 0;						// Clear a bunch of registers we need to clear before enabling DMA
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDS_MSP = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CSUS = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDUS = 0;
    XDMAC->XDMAC_GE = 1 << DMA_CH_USART2_RX;							// enable RX channel
}

And here is the function I am using to send the data and setup the DMA to send and receive over USART2:

void XDMAC_USART_transfer(void) {
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDA = (uint32_t)&usart_receive_buffer;		 // Destination address is buffer
    num_samples = 3;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CUBC = num_samples;				 // Set microblock size to be the size requested
    xdmaint = XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CIS;					 // Clear any pending interrupts for this channel
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CNDC = 0;						 // Clear a bunch of registers we need to clear before enabling DMA
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDS_MSP = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CSUS = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_RX].XDMAC_CDUS = 0;
    xdmac_channel_enable(XDMAC, DMA_CH_USART2_RX);						 // enable RX channel
    //
    usart_send_buffer[0] = 0xAB;
    usart_send_buffer[1] = 0xCD;
    usart_send_buffer[2] = 0xEF;
    //
    num_samples = 3;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CSA = (uint32_t)&usart_send_buffer;		 // Source address is TX buffer
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CUBC = num_samples;				 // Set microblock size to be the size requested
    xdmaint = XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CIS;					 // Clear any pending interrupts for this channel
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CNDC = 0;						 // Clear a bunch of registers we need to clear before enabling DMA
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CDS_MSP = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CSUS = 0;
    XDMAC->XDMAC_CHID[DMA_CH_USART2_TX].XDMAC_CDUS = 0;
    //
    SCB_CleanInvalidateDCache_by_Addr((uint32_t)&usart_send_buffer, num_samples * sizeof(uint32_t));
    __DSB();
    __ISB();
    //
    xdmac_channel_enable_interrupt(XDMAC, DMA_CH_USART2_TX, XDMAC_CIE_BIE);			 // End of Block interrupt is enabled
    xdmac_channel_enable(XDMAC, DMA_CH_USART2_TX);
    xdmac_enable_interrupt(XDMAC, DMA_CH_USART2_TX);
}

 

Last Edited: Mon. Mar 9, 2020 - 09:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

try to CleanInvalidateDCache on your receive buffer after DMA transfer is complete.

 

Regards

Markus