Other Parts Discussed in Thread: ENERGIA
Hi everyone
I'm using Energia IDE (version 0101E0017) and my tivaware revision is 2.0.1.11577. I know they are pretty old versions, but they worked fine for the past. Yet, recently I use the UART DMA and found it doesn't work functionally. Hope you guys could help me with these:
1. I can't use UART7 DMA to transmit data to another tm4c123gxl launchpad, no byte was received, but when using UART0 DMA, the correct amount of data could be transferred to my laptop. Here is my code. The first part is UART0 DMA which works fine, the second part is UART7 DMA which does not work, and the third part is the reception part which uploaded to another launchpad.
// using uart0 dma in basic mode, data can be transmitted. #include <stdint.h> #include <stdbool.h> #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/udma.h" #include "inc/hw_uart.h" #define TX_BUFFER_SIZE 256 byte txBuffer[TX_BUFFER_SIZE]; // uDMA control table aligned to 1024-byte boundary #pragma DATA_ALIGN(controlTable, 1024); uint8_t controlTable[1024]; void setup() { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // 80MHz for(uint32_t ui32Idx = 0; ui32Idx < TX_BUFFER_SIZE; ui32Idx++) { txBuffer[ui32Idx] = 65; // 'A' } UARTConfiguration(); UDMAConfiguration(); } void UARTConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX); UARTEnable(UART0_BASE); UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX); } void UDMAConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(&controlTable[0]); uDMAChannelAssign(UDMA_CH9_UART0TX); uDMAChannelAttributeDisable(UDMA_CH9_UART0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelAttributeEnable(UDMA_CH9_UART0TX, UDMA_ATTR_USEBURST); uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(txBuffer)); uDMAChannelEnable(UDMA_CH9_UART0TX); } void loop(){} // using uart7 dma in basic mode, no data be transmitted. #include <stdint.h> #include <stdbool.h> #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/udma.h" #include "inc/hw_uart.h" #define TX_BUFFER_SIZE 256 byte txBuffer[TX_BUFFER_SIZE]; // uDMA control table aligned to 1024-byte boundary #pragma DATA_ALIGN(controlTable, 1024); uint8_t controlTable[1024]; void setup() { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // 80MHz for(uint32_t ui32Idx = 0; ui32Idx < TX_BUFFER_SIZE; ui32Idx++) { txBuffer[ui32Idx] = 65; // 'A' } UARTConfiguration(); UDMAConfiguration(); } void UARTConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART7); GPIOPinConfigure(GPIO_PE0_U7RX); GPIOPinConfigure(GPIO_PE1_U7TX); GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTConfigSetExpClk(UART7_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); UARTFIFOLevelSet(UART7_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); UARTIntEnable(UART7_BASE, UART_INT_TX | UART_INT_RX); UARTEnable(UART7_BASE); UARTDMAEnable(UART7_BASE, UART_DMA_RX | UART_DMA_TX); } void UDMAConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(&controlTable[0]); uDMAChannelAssign(UDMA_CH21_UART7TX); uDMAChannelAttributeDisable(UDMA_CH21_UART7TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelAttributeEnable(UDMA_CH21_UART7TX, UDMA_ATTR_USEBURST); uDMAChannelControlSet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelTransferSet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART7_BASE + UART_O_DR), sizeof(txBuffer)); uDMAChannelEnable(UDMA_CH21_UART7TX); } void loop(){}
// this part is for another launchpad to receive data from uart7, then send the data to laptop through uart0
void setup() { Serial.begin(115200); Serial7.begin(115200); Serial7.setBufferSize(8192, 8192); } void loop() { if (Serial7.available() > 0) { char ch = Serial7.read(); Serial.write(ch); } }
2. As mentioned in problem 1, even the correct amount of data could be transferred to laptop, but sometime the data bytes are garbled (shown in the picture).
The garbled data pattern is always 12 bytes and the bytes would not change their value or position. So I did some tests with basic mode and ping-pong mode, below shows the ping-pong mode code.
// ping pong mode for uart data sending
#include <stdint.h> #include <stdbool.h> #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/udma.h" #include "inc/hw_uart.h" #define PINGPONG_BUFFER_SIZE 128 byte pingBuffer[PINGPONG_BUFFER_SIZE]; byte pongBuffer[PINGPONG_BUFFER_SIZE]; // uDMA control table aligned to 1024-byte boundary #pragma DATA_ALIGN(controlTable, 1024); uint8_t controlTable[1024]; void setup() { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // 80MHz for(uint16_t i = 0; i < PINGPONG_BUFFER_SIZE; i++) { pingBuffer[i] = 65; // 'A' pongBuffer[i] = 66; // 'B' } UARTConfiguration(); UDMAConfiguration(); } void UARTConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE); UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); UARTIntRegister(UART0_BASE, UART0IntHandler); UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX); UARTEnable(UART0_BASE); UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX); } void UDMAConfiguration() { SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); uDMAEnable(); uDMAControlBaseSet(&controlTable[0]); uDMAChannelAssign(UDMA_CH9_UART0TX); uDMAChannelAttributeDisable(UDMA_CH9_UART0TX, UDMA_ATTR_ALL); uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pingBuffer)); uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pongBuffer)); uDMAChannelEnable(UDMA_CH9_UART0TX); } void UART0IntHandler() { uint32_t DMAMode; UARTIntClear(UART0_BASE, UART_INT_TX | UART_INT_RX); DMAMode = uDMAChannelModeGet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT); if(DMAMode == UDMA_MODE_STOP) { uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pingBuffer)); } DMAMode = uDMAChannelModeGet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT); if(DMAMode == UDMA_MODE_STOP) { uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pongBuffer)); } } void loop(){}
In two modes by changing the value of PINGPONG_BUFFER_SIZE and TX_BUFFER_SIZE respectively, results are shown below.
buffer size | basic mode (txBuffer) | position | ping pong mode (ping buffer) | position | ping pong mode (pong buffer) | position |
128 | X (all 0x65) | X | X (all 0x65) | X | X (all 0x66) | X |
256 | O | 0x88~0x93 | X (all 0x65) | X | O | 0x87~0x92 |
512 | O | 0x88~0x93 | X (all 0x65) | X | X (all 0x66) | X |
1024 | X (all 0x65) | X | X (all 0x65) | X | X (all 0x66) | X |
In basic mode, I found that garbled data seems to appear at same position, so I reduce txBuffer size to 128 bytes, since 128 is smaller than 136 (0x88), garbled data should not appear. As expected, those data did not show up, nor they did not appear when txBuffer size is set to 1024. So strange!
Similar situation happened in ping pong mode...
Thank you for your time of reading this, I sincerely hope anyone of you could help to explain about the strange bytes, how could it happen, how to fix this, and why UART7 DMA does not work.