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.

TM4C1294NCPDT: Sending Data Over UART

Part Number: TM4C1294NCPDT


Hi,

I am sending the data over UART and I am checking it onto the terminal. while receiving the data I am getting the garbage value , i am not getting where I am making the mistake.
When I am putting the brakpoint at loine number 534 and 578 the data is receiving as desired.


#0000#0fff
#0002#0fff
#0000#0fff
#0000#0fff


but when we removed the breakpoint i am getting the garbage value.

#0001########
#######
##0002#0fff
#0000####f##########
###0001#0fff
#0002########
###
###f##0000#0ffc
#0001####f##########
###0002#0fff
#0000########
#######f##0000#0fff
#0003####f##########
###0001#0fff
#0000########
#######f##0001#0fff

below is my Code.

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_emac.h"
#include "inc/hw_udma.h"
#include "inc/hw_adc.h"
#include "driverlib/flash.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/rom.h"
#include "driverlib/adc.h"
#include "driverlib/uart.h"
#include "driverlib/pin_map.h"
#include "driverlib/timer.h"
#include "driverlib/udma.h"
#include "drivers/pinout.h"
#include "utils/lwiplib.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip/inet.h"




//
// The variable g_ui32SysClock contains the system clock frequency in Hz.
//
//*****************************************************************************
uint32_t g_ui32SysClock;


// Definition for ADC buffer size.
//
//*****************************************************************************
#define ADC_SAMPLE_BUF_SIZE     64
#define Channels                 2

//*****************************************************************************
//
// The control table used by the uDMA controller.  This table must be aligned
// to a 1024 byte boundary.
//
//*****************************************************************************
#if defined(ewarm)
#pragma data_alignment=1024
uint8_t pui8ControlTable[1024];
#elif defined(ccs)
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];
#else
uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
#endif

//*****************************************************************************
//
// Global buffers to store ADC sample data.
//
//*****************************************************************************
static uint16_t pui16ADCBuffer1[ADC_SAMPLE_BUF_SIZE][Channels];
static uint16_t pui16ADCBuffer2[ADC_SAMPLE_BUF_SIZE][Channels];

//*****************************************************************************
//
// Each possible state of the fill status for an ADC buffer.
//
//*****************************************************************************
enum BUFFER_STATUS
{
    EMPTY,
    FILLING,
    FULL
};
uint8_t k=0;
//*****************************************************************************
//
// Global variable to keep track of the fill status of each ADC buffer.
//
//*****************************************************************************
static enum BUFFER_STATUS pui32BufferStatus[2];

//*****************************************************************************
//
// The count of uDMA errors.  This value is incremented by the uDMA error
// handler.
//
//*****************************************************************************
static uint32_t g_ui32DMAErrCount = 0u;

//*****************************************************************************


//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif



//*****************************************************************************
// User Defined Function Proto
void init_TIMER(void);




//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = MAP_UARTIntStatus(UART0_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    MAP_UARTIntClear(UART0_BASE, ui32Status);

    //
    // Loop while there are characters in the receive FIFO.
    //
    while(MAP_UARTCharsAvail(UART0_BASE))
    {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        MAP_UARTCharPutNonBlocking(UART0_BASE,
                                   MAP_UARTCharGetNonBlocking(UART0_BASE));

        //
        // Blink the LED to show a character transfer is occuring.
        //
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay(g_ui32SysClock / (1000 * 3));

        //
        // Turn off the LED
        //
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    }
}


//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
{
    //
    // Loop while there are more characters to send.
    //
    while(ui32Count--)
    {
        //
        // Write the next character to the UART.
        //
        UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);

    }
       // UARTCharPutNonBlocking(UART0_BASE, '\n');
}


//*****************************************************************************
//
// The interrupt handler for uDMA errors.  This interrupt will occur if the
// uDMA encounters a bus error while trying to perform a transfer.  This
// handler just increments a counter if an error occurs.
//
//*****************************************************************************
void
uDMAErrorHandler(void)
{
    uint32_t ui32Status;

    //
    // Check for uDMA error bit.
    //
    ui32Status = uDMAErrorStatusGet();

    //
    // If there is a uDMA error, then clear the error and increment
    // the error counter.
    //
    if(ui32Status)
    {
        uDMAErrorStatusClear();
        g_ui32DMAErrCount++;
    }
}


//*****************************************************************************
//uDMA Configuration

void uDMAConfigure(void)
{
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        uDMAEnable();

        //
        // Point at the control table to use for channel control structures.
        //
        uDMAControlBaseSet(pui8ControlTable);

        //
        // Put the attributes in a known state for the uDMA ADC0 channel.  These
        // should already be disabled by default.
        //
        uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
                                    UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);

        //
        // Configure the control parameters for the primary control structure for
        // the ADC0 channel.  The primary control structure is used for the "A"
        // part of the ping-pong receive.  The transfer data size is 16 bits, the
        // source address does not increment since it will be reading from a
        // register.  The destination address increment is 16-bits.  The
        // arbitration size is set to one byte transfers.
        //
        uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 |
                              UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

        //
        // Configure the control parameters for the alternate control structure for
        // the ADC0 channel.  The alternate control structure is used for the
        // "B" part of the ping-pong receive.  The configuration is identical to
        // the primary/A control structure.
        //
        uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 |
                              UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);

        //
        // Set up the transfer parameters for the ADC0 primary control structure
        // The mode is set to ping-pong, the transfer source is the ADC Sample
        // Sequence Result FIFO 0 register, and the destination is the receive
        // "A" buffer.  The transfer size is set to match the size of the buffer.
        //
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                               &pui16ADCBuffer1, ADC_SAMPLE_BUF_SIZE * Channels);

        //
        // Set up the transfer parameters for the ADC0 primary control structure
        // The mode is set to ping-pong, the transfer source is the ADC Sample
        // Sequence Result FIFO 0 register, and the destination is the receive
        // "B" buffer.  The transfer size is set to match the size of the buffer.
        //
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                               &pui16ADCBuffer2,ADC_SAMPLE_BUF_SIZE * Channels);

        //
        // Set the USEBURST attribute for the uDMA ADC0 channel.  This will force
        // the controller to always use a burst when transferring data from the
        // TX buffer to the UART.  This is somewhat more efficient bus usage than
        // the default which allows single or burst transfers.
        //
        uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST);


        // Enables DMA channel so it can perform transfers.  As soon as the
        // channels are enabled, the peripheral will issue a transfer request and
        // the data transfers will begin.
        //
        uDMAChannelEnable(UDMA_CHANNEL_ADC0);

}





//*****************************************************************************
//
// Configure ADC0 and use Sequencer 3 to take temperature sensor sample
//
//*****************************************************************************
void
adcConfigure()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2 | GPIO_PIN_3);
    SysCtlDelay(80u);

    // Use ADC0 sequence 0 to sample channel 0 once for each timer period
    ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 8);
    SysCtlDelay(10); // Time for the clock configuration to set
    IntDisable(INT_ADC0SS0);
    ADCIntDisable(ADC0_BASE, 0u);
    ADCSequenceDisable(ADC0_BASE,0u);
   // With sequence disabled, it is now safe to load the new configuration parameters

    ADCSequenceConfigure(ADC0_BASE, 0u, ADC_TRIGGER_TIMER, 0u);
    ADCSequenceStepConfigure(ADC0_BASE,0u,0u,ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE,0u,1u,ADC_CTL_CH1 | ADC_CTL_END | ADC_CTL_IE);
    ADCSequenceEnable(ADC0_BASE,0u); //Once configuration is set, re-enable the sequencer
    ADCIntClear(ADC0_BASE,0u);
    //
    // Enables the DMA channel for the ADC0 sample sequence 0.
    //
    ADCSequenceDMAEnable(ADC0_BASE, 0);

    ADCIntEnable(ADC0_BASE, 0u);
    IntEnable(INT_ADC0SS0);
}

void uartConfigure(void)
{
    // Enable the peripherals used by this example.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    // Set GPIO A0 and A1 as UART pins.
    //
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    MAP_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    MAP_IntEnable(INT_UART0);
    MAP_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

}

uint32_t ui32Count;

//*****************************************************************************
//
// This example demonstrates the use of the Ethernet Controller and ADC
// peripheral.
//
//*****************************************************************************
int
main(void)
{



    //
    // Make sure the main oscillator is enabled because this is required by
    // the PHY.  The system must have a 25MHz crystal attached to the OSC
    // pins. The SYSCTL_MOSC_HIGHFREQ parameter is used when the crystal
    // frequency is 10MHz or higher.
    //
    SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);

    //
    // Run from the PLL at 120 MHz.
    // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
    // later to better reflect the actual VCO speed due to SYSCTL#22.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_240), 120000000);
    //
    // Initialize the buffer status.
    //
    pui32BufferStatus[0] = FILLING;
    pui32BufferStatus[1] = EMPTY;
    //
    // Configure the device pins.
    //
  //  PinoutSet(true, false);
    //
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

    //
    // Configure Port N1 for as an output for the animation LED.
    //
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

    //
    // Initialize LED to OFF (0).
    //
    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, ~GPIO_PIN_1);
    //
    // Configure UART.
    //
    uartConfigure();

    //
    // Clear the terminal and print banner.
    //



    //
    // Configure the ADC peripheral.
    //
    uDMAConfigure();
    adcConfigure();
    init_TIMER();


    //
    MAP_IntPrioritySet(INT_UART0,89);
    MAP_IntPrioritySet(INT_ADC0SS0,90);
    IntMasterEnable();

    TimerEnable(TIMER0_BASE, TIMER_A);
  //  UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
    //
    // Loop forever, processing the LED blinking.  All the work is done in
    // interrupt handlers.
    while(1)
    {




        // Check if the first buffer is full, if so process data.


        //
        if(pui32BufferStatus[0] == FULL)
        {

            uint16_t j,i;

            uint8_t UARTBuf[15];
            //
            // Process the data in pui16ADCBuffer1 and clear buffer entries.
            //

            for(i =0; i < ADC_SAMPLE_BUF_SIZE; i++)
            {

                for (j=0; j < Channels; j++ )
                {
                    usprintf((char *)UARTBuf, "#%04X",pui16ADCBuffer1[i][j]);
                    UARTSend(UARTBuf, strlen((char *)UARTBuf));
                    UARTCharPutNonBlocking(UART0_BASE, '\n');
                    pui16ADCBuffer1[i][j] = 0;
                }


            }





            pui32BufferStatus[0] = EMPTY;

            //
            // Enable for another uDMA block transfer.
            //
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                                   &pui16ADCBuffer1, ADC_SAMPLE_BUF_SIZE *Channels);
            //
            // Enable DMA channel so it can perform transfers.
            //
            uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);


        }



        //
        // Check if the second buffer is full, if so process data.
        //
        if(pui32BufferStatus[1] == FULL)
        {
            uint16_t j,i;

            uint8_t UARTBuf[15];
            for(i =0; i < ADC_SAMPLE_BUF_SIZE; i++)
            {

                for (j=0; j < Channels; j++ )
                {
                    usprintf((char *)UARTBuf, "#%04X",pui16ADCBuffer2[i][j]);
                    UARTSend(UARTBuf, strlen((char *)UARTBuf));
                    pui16ADCBuffer2[i][j] = 0;
                }

                UARTCharPutNonBlocking(UART0_BASE, '\n');
            }




            //
            // Indicate the Buffer data as been processed so new data can
            // be stored.

            //

            pui32BufferStatus[1] = EMPTY;

            //
            // Enable for another uDMA block transfer.
            //
            uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                                   &pui16ADCBuffer2, ADC_SAMPLE_BUF_SIZE *Channels);

            //
            // Enable DMA channel so it can perform transfers.
            //
            uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);


        }



    }

}


void init_TIMER()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
    // Set sample frequency to 1MHz (every 1uS)
    TimerLoadSet(TIMER0_BASE, TIMER_A, 65535);   //TODO: Timer Load Value is set here
    TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
    TimerControlStall(TIMER0_BASE, TIMER_A, true); //Assist in debug by stalling timer at breakpoints
}
void ADC0SS0IntHandler(void)
{

    //
    // Clear the Interrupt Flag.
    //
    ADCIntClear(ADC0_BASE, 0);
    if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT) ==
                            UDMA_MODE_STOP) &&
                           (pui32BufferStatus[0] == FILLING))
    {
        pui32BufferStatus[0] = FULL;
        pui32BufferStatus[1] = FILLING;
    }
    else if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT) ==
                                 UDMA_MODE_STOP) &&
                                (pui32BufferStatus[1] == FILLING))
    {
        pui32BufferStatus[0] = FILLING;
        pui32BufferStatus[1] = FULL;
    }

}


  • Hi,

      I think the problem is that you are calling UARTSend asynchronously with respect to the ADC samples that come in at every 1us. I think the UARTSend is unable to finish draining the RXFIFO fast enough before your UARTBuf is refilled with new data. For example, the UARTSend is trying to print the first '#' and before it can finish printing the remaining characters the UARTBuf is refilled with new data that starts with '#' again. In debug mode, you stop the operations and sort of allowing the UARTSend to finish before ADC is triggered again for interrupt. Note that UART is operating at 115200 baud while you are sampling ADC at 1Mhz rate and you are trying to send out the data at this rate.