This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello Team,
I'm Working on DMA Transfer to UART Peripheral in TM4C1294NCPDT(Customised Board). Facing issue while sending bytes from Pkt2(Array of size 312 bytes) to another Controller. But the Problem is DMA transfer function is not working as expected it is sending random bytes compared to actual bytes.
1) I'm Filling an Array in one Function to Transmit those bytes to another controller.
2) After Filling 312 bytes in an Array(Pkt2 named in Program), I'm Using " MAP_uDMAChannelEnable(UDMA_CH17_UART3TX);" to initiate DMA Transfer.
3) Where it is going wrong i was unable to recognise. Can Someone help me how DMA is working in this scenario and Help me to resolve this issue.
I want to send 312 data bytes from internal Array(Pkt2) to Another Micro-Controller without any data loss using DMA_Tx.
Attaching configuration for both DMA Rx and Tx and Also Output i got. Any help would be very thankful.
void Init_UART3() { // // Enable the GPIO Peripheral used by the UART. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Enable UART3. // SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3); // // Enable processor interrupts. // IntMasterEnable(); // // Configure GPIO Pins for UART mode. // GPIOPinConfigure(GPIO_PA4_U3RX); GPIOPinConfigure(GPIO_PA5_U3TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // Initialize the UART for console I/O. // MAP_UARTConfigSetExpClk(UART3_BASE, gu32SysClk, 230400, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_RXE; HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_TXE; // HWREG(UART3_BASE + UART_O_CTL) |= UART_CTL_LBE; // Make sure there is no junk left in the FIFO while (UARTCharGetNonBlocking(UART3_BASE) != -1); MAP_UARTFIFOEnable(UART3_BASE); MAP_UARTFIFOLevelSet(UART3_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); // Make sure there is no junk left in the FIFO while (UARTCharGetNonBlocking(UART3_BASE) != -1); } void Init_UART3_DMA(void) { MAP_uDMAChannelAssign(UDMA_CH16_UART3RX); MAP_uDMAChannelAssign(UDMA_CH17_UART3TX); // // Enable the UART for operation, and enable the uDMA interface for both TX // and RX channels. // MAP_UARTDMAEnable(UART3_BASE, UART_DMA_RX); MAP_UARTDMAEnable(UART3_BASE, UART_DMA_TX); // // Put the attributes in a known state for the uDMA UART1RX channel. These // should already be disabled by default. // MAP_uDMAChannelAttributeDisable(UDMA_CH16_UART3RX, UDMA_PRI_SELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); // // Configure the control parameters for the primary control structure for // the UART RX channel. The primary contol structure is used for the "A" // part of the ping-pong receive. The transfer data size is 8 bits, the // source address does not increment since it will be reading from a // register. The destination address increment is byte 8-bit bytes. The // arbitration size is set to 4 to match the RX FIFO trigger threshold. // The uDMA controller will use a 4 byte burst transfer if possible. This // will be somewhat more effecient that single byte transfers. // MAP_uDMAChannelControlSet(UDMA_CH16_UART3RX | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_2); MAP_uDMAChannelTransferSet( UDMA_CH16_UART3RX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void*) (UART3_BASE + UART_O_DR), gu16Array, sizeof(gu16Array) >> 1u); MAP_uDMAChannelAttributeEnable(UDMA_CH16_UART3RX, UDMA_PRI_SELECT | UDMA_ATTR_USEBURST); /* Tx DMA setting */ /* clear any previous defined attribute */ uDMAChannelAttributeDisable(UDMA_CH17_UART3TX , UDMA_PRI_SELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_REQMASK); MAP_uDMAChannelAttributeEnable(UDMA_CH17_UART3TX, UDMA_ATTR_USEBURST);// UDMA_PRI_SELECT /* set the control pars */ uDMAChannelControlSet(UDMA_CH17_UART3TX | UDMA_PRI_SELECT , UDMA_SIZE_16 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_2); uDMAChannelTransferSet(UDMA_CH17_UART3TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, Pkt2, (void *)(UART3_BASE + UART_O_DR), 312); ///////////////////////////////////////////////// MAP_UARTDMAEnable(UART3_BASE, UART_DMA_RX); MAP_UARTDMAEnable(UART3_BASE, UART_DMA_TX); MAP_uDMAChannelEnable(UDMA_CH16_UART3RX); // // Enable the UART DMA TX/RX interrupts. // MAP_UARTIntEnable(UART3_BASE, UART_INT_DMARX | UART_INT_DMATX); MAP_UARTEnable(UART3_BASE); // // Enable the UART interrupt. // MAP_UARTIntEnable(UART3_BASE, UART_INT_RX | UART_INT_RT); //UART_INT_RX | } uint16_t Pkt2[312]; int main() { Init_SysClk(); Init_GPIO(); Init_UART3(); Init_UART3_DMA(); //uint8_t lu8Index; uint8_t lu8Checksum; uint8_t inc = 0; uint16_t lu16PktIndex = 0; while(1) { // Preparing 312 bytes in Pkt2 Array for (i = 0; i < 52; i++) { Pkt2[lu16PktIndex] = gu8Command2; lu8Checksum ^= Pkt2[lu16PktIndex]; lu16PktIndex++; lu16PktIndex &= 0x01FF; Pkt2[lu16PktIndex] = gu8Data2 + inc; inc++; lu8Checksum ^= Pkt2[lu16PktIndex]; lu16PktIndex++; lu16PktIndex &= 0x01FF; OnTime1 = gu16SineArray[0][i]; //One ON Long Time OffTime1 = gu16SineArray[1][i]; Pkt2[lu16PktIndex] = (OnTime1 & 0x7F); lu8Checksum ^= Pkt2[lu16PktIndex]; lu16PktIndex++; lu16PktIndex &= 0x01FF; Pkt2[lu16PktIndex] = ((OnTime1 >> 7) & 0x03); Pkt2[lu16PktIndex] = Pkt2[lu16PktIndex] | ((OffTime1 << 2) & 0x7F); Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] & 0x7F); lu8Checksum ^= Pkt2[lu16PktIndex]; lu16PktIndex++; lu16PktIndex &= 0x01FF; Pkt2[lu16PktIndex] = ((OffTime1 >> 5) & 0x0F); Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] | ((Mode << 5) & 0x60)); Pkt2[lu16PktIndex] = (Pkt2[lu16PktIndex] & 0x7F); lu8Checksum ^= Pkt2[lu16PktIndex]; lu16PktIndex++; lu16PktIndex &= 0x01FF; lu8Checksum = lu8Checksum & 0x7F; Pkt2[lu16PktIndex++] = lu8Checksum; lu16PktIndex &= 0x01FF; } // After i = 52 initiating DAM transfer if (i >= 52) { MAP_uDMAChannelEnable(UDMA_CH17_UART3TX); } } }
Below is the DMA transferred Data which is very random/ Not Expected Data to transfer.
Helo Vamshi,
Trying using UDMA_SIZE_8 instead of UDMA_SIZE_16. I think you are getting garbage data because you are trying to send 16 bits when the buffer sends data in 8-bit increments. That is also why UDMA_ARB_4 is used instead of UDMA_ARB_2.
Best Regards,
Ralph Jacobi
Thank you for the reply Ralph Jacobi,
I have referred TM4C datasheet then i got to know that,
My Array size is 16 So, I have to use UDMA_SIZE_16 as well as source increment to UDMA_SRC_INC_16 only.
Here Major role is Arbitration which i need to set to UDMA_ARB_1 for not missing data.
" uDMAChannelControlSet(UDMA_CH17_UART3TX | UDMA_PRI_SELECT , UDMA_SIZE_16 |
UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1); "
The parameters in the above function resolved my issue.
Thank you,
Vamshi
Hello Vamshi,
Ahh I see, I didn't notice the mismatch on UDMA_SRC_INC_8 and UDMA_SRC_INC_16 for RX and TX. For the Arbitration, you may be able to use higher ones if you increase the RX FIFO trigger so it isn't flagging the DMA for transfer too quickly. Our example code uses UART_FIFO_RX4_8 and UART_FIFO_TX4_8 to then use UDMA_ARB_4.
Best Regards,
Ralph Jacobi