Background:
I have dedicated UART6 (RX PP0) on my TM4C129 to read serial data from another sensor. In terms of the data being received on the TM4C, the sensor sends out (n) frames, each 32 bytes in width, every 7ms. Baud on both sides is 115200.
Objective:
Speed is critical in this case, as the TM4C is responsible for performing other tasks, such as reading encoders and limit switches.
For this reason, I was thinking of taking my interrupt driven approach (see below), and trying to see if I can leverage DMA to basically create a pipe from the UART RX peripheral memory, into my own locally created buffer in SW.
Progress:
I have adapted the basic uart_echo example, but obviously changed things around, so that the data received is from the sensor, opposed to manual input from the user. I then print out the data on UART0 as it is coming in on UART6, and can view it in the serial console (RealTerm).
Question:
After reading up on DMA, and looking over the udma_demo example, I think this might be the best approach. However, I am struggling to adapt my existing code to use it. For example, I see plenty of code out there which sends data over UART TX, facilitated by DMA. But I don't see many examples of having DMA simply receive data from UART RX.
Note that udma_demo does something similar to what I want, but I can't seem to connect the dots. For example, one desirable trait of that sample application is that it has set DMA to use a sort of ping-pong approach. I read the docs in TivaWare, and think this would certainly work for my application in the sense that, while I am collecting those 32 bytes of data over the UART, I could be parsing the previously collected frame (32 bytes), and act accordingly, by the time the next 32 byte chunk comes along.
So I guess that's a long way of asking, is my thought process on how DMA can interact with UART RX valid (peripheral pipe idea mentioned above). And if so, what would be the best approach moving forward. Is there any other example within TivaWare that you can think of, which may help in this case?
Thanks!
Code for reference:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
uint32_t g_ui32SysClock;
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
void UARTIntHandler(void)
{
uint32_t ui32Status;
ui32Status = ROM_UARTIntStatus(UART6_BASE, true);
/* Clear interrupts */
ROM_UARTIntClear(UART6_BASE, ui32Status);
/* Read data */
while(ROM_UARTCharsAvail(UART6_BASE))
{
/* Should move to blocking charGet() */
ROM_UARTCharPutNonBlocking(UART0_BASE, ROM_UARTCharGetNonBlocking(UART6_BASE));
/* Toggle LED for testing */
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
SysCtlDelay(g_ui32SysClock / (1000 * 3));
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
}
}
int main(void)
{
/* 120Mhz */
g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
/* LED */
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
/* UART 6 */
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART6);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
/* UART 0 */
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
ROM_IntMasterEnable();
/* Configure As UART 6 on PP0/1 */
GPIOPinConfigure(GPIO_PP0_U6RX);
GPIOPinConfigure(GPIO_PP1_U6TX);
ROM_GPIOPinTypeUART(GPIO_PORTP_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* Configure As UART 1 on PA0/1 */
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* 115200 8-N-1 */
ROM_UARTConfigSetExpClk(UART6_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
ROM_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
/* Enable ISR */
ROM_IntEnable(INT_UART6);
ROM_IntEnable(INT_UART0);
ROM_UARTIntEnable(UART6_BASE, UART_INT_RX | UART_INT_RT);
while(1){}
}