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.

TM4C123 ADC(Temperature) and UART Interrupt



Good Evening,

I have a sample program that introduces the use of an interrupt with UART. I am trying to modify it so that I can sample the ADC temperature but it gets stuck at an if statement. Within the modified code,  while debugging I get stuck at if(RingBufEmpty(&rxRingBuf) == false) which is inside main().

I should state that I have two boards, the one sampling temperature and the one receiving it. I'm struggling to see how to specify which board does what. But for debugging purposes, I turn on the one which transmits and program it first. I then shut it off, turn on the second receiving board and program that. I have then had luck turning back on the transmitting board.

I use a putty connection on the receiving board to see if I am in fact receiving anything. I use the debugger to follow the code around.

Hopefully you all can assist me with this!


The working code:

#include <stdint.h>
#include <stdbool.h>
#include <inc/hw_memmap.h>
#include <inc/hw_ints.h>
#include <driverlib/gpio.h>
#include <driverlib/sysctl.h>
#include <driverlib/uart.h>
#include <driverlib/timer.h>
#include <driverlib/interrupt.h>
#include <driverlib/pin_map.h>
#include "ringbuf.h"
#include "utils/uartstdio.h"
#include "utils/uartstdio.c"



#include "driverlib/debug.h"



// This is a dummy message formatted as a struct. Note that while the ISA
// is 32 bits the message is not perfectly aligned. I did this to demonstrate
// that the RT UART interrupt is required.
typedef struct {
    float voltage;
    uint32_t id;
    float otherVoltage;
    int32_t code;
    uint8_t random;
} message_t;

#define RING_BUF_SIZE            512

// Tx buffer and backend array.
static tRingBufObject txRingBuf;
static uint8_t txBuf[RING_BUF_SIZE];

// Rx buffer and back end array.
static tRingBufObject rxRingBuf;
static uint8_t rxBuf[RING_BUF_SIZE];

void UART1IntHandler(void)
{
    uint32_t intStatus;



    // Retrieve masked interrupt status (only enabled interrupts).
    intStatus = UARTIntStatus(UART1_BASE, true);

    // Clear interrupt(s) after retrieval.
    UARTIntClear(UART1_BASE, intStatus);

    // Important: Note that they're all IF statements. This is because you can have an NVIC
    // system interrupt that is composed of all three sub-interrupts below. If you use the standard
    // if-elseif-else then you might miss one and drop bytes.

    // The receive timeout interrupt fires when you have received bytes in your FIFO but have not
    // gotten enough to fire your Rx interrupt. This is because the FIFO level select determines when that
    // interrupt goes off.
    if((intStatus & UART_INT_RT) == UART_INT_RT)
    {
        // While there are bytes to read and there is space in the FIFO.
        while(UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false)
        {
            // Write a byte straight from the hardware FIFO into our Rx FIFO for processing later.
            RingBufWriteOne(&rxRingBuf, (uint8_t)UARTCharGet(UART1_BASE));
        }
    }

    // The Rx interrupt fires when there are more than the fifo level select bytes in the FIFO.
    if((intStatus & UART_INT_RX) == UART_INT_RX)
    {
        // While there are bytes to read and there is space in the FIFO.
        while(UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false)
        {
            // Write a byte straight from the hardware FIFO into our Rx FIFO for processing later.
            RingBufWriteOne(&rxRingBuf, (uint8_t)UARTCharGet(UART1_BASE));
        }
    }

    // The transmit interrupt fires when there are less than the FIFO level select bytes waiting to
    // be transmitted. This way you can add more ensuring it's continuous transmission.
    if((intStatus & UART_INT_TX) == UART_INT_TX)
    {
        // While there is space left in the FIFO and we have bytes queued up for sending.
        while(UARTSpaceAvail(UART1_BASE) == true && RingBufEmpty(&txRingBuf) == false)
        {
            // Remove a byte from the queued Tx FIFO and add it to our UART tx fifo.
            UARTCharPut(UART1_BASE, RingBufReadOne(&txRingBuf));

        }
    }
}

void Timer0IntHandler(void)
{
    int32_t intStatus;
    message_t msg;
    uint8_t * ptr,
              byte;

    // Retrieve timer interrupt status.
    intStatus = TimerIntStatus(TIMER0_BASE, true);

    // Clear interrupt.
    TimerIntClear(TIMER0_BASE, intStatus);

    // Check if the interrupt was the correct one (timeout).
    if((intStatus & TIMER_TIMA_TIMEOUT) == TIMER_TIMA_TIMEOUT)
    {
        // This message population is just a placeholder for where an ADC or
        // other sensor might be sampled.
        msg.voltage = 3.3F;
        msg.id = 1;
        msg.otherVoltage = 2.5F;
        msg.code = 200;
        msg.random = 7;

        // Cast the structure into a byte array.
        ptr = (uint8_t *)&msg;

        // Loop through the entire message.
        for(byte = 0; byte < sizeof(message_t); byte++)
        {
            // This part is pretty important... the UART Tx FIFO has a limited size
            // in fact it's smaller than our message. However the Tx interrupt will let us know
            // when we have less than 4 bytes remainign to send so we can stash the extra
            // bytes in our FIFO for later.

            // Is there space in the Tx FIFO?
            if(UARTSpaceAvail(UART1_BASE) == true)
            {
                // Put the byte into the Tx FIFO.
                UARTCharPut(UART1_BASE, ptr[byte]);


            }
            else
            {
                // Otherwise, stash the byte in our FIFO for when there's space.
                RingBufWriteOne(&txRingBuf, ptr[byte]);
            }
        }
    }
}

int main(void)
{
    // Run the microcontroller system clock at 80MHz.
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Enable peripheral and bank clocking.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralReset(SYSCTL_PERIPH_UART1);

    //#TEST Enables UART0 for console use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //Configure the pins, uh..., plated holes for UART0
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    // Initialize the UART for console I/O. on UART0/BASE0
    UARTStdioConfig(0, 9600, SysCtlClockGet());
    //Set the baud rate, 8 data bits, one stop bit and no parity for UART0
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,
        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    // Configure pin-muxing for the UART.
    GPIOPinConfigure(GPIO_PB0_U1RX);
    GPIOPinConfigure(GPIO_PB1_U1TX);
    GPIOPinTypeUART(GPIO_PORTB_BASE, (GPIO_PIN_0 | GPIO_PIN_1));

    // Configure the UART for 9600 8-N-1.
    UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 9600, (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE));
    UARTFIFOLevelSet(UART1_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    UARTEnable(UART1_BASE);

    // Initialize our FIFO's.
    RingBufInit(&txRingBuf, &txBuf[0], RING_BUF_SIZE);
    RingBufInit(&rxRingBuf, &rxBuf[0], RING_BUF_SIZE);

    // Enable the NVIC interrupt, clear the UART individual interrupts and then enable.
    IntEnable(INT_UART1);
    UARTIntClear(UART1_BASE, UARTIntStatus(UART1_BASE, false));
    UARTIntEnable(UART1_BASE, (UART_INT_TX | UART_INT_RX | UART_INT_RT));

    // Setup the timer to go off at 1Hz (periodically). This will be used to generate a message
    // for transmission.
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());
    IntEnable(INT_TIMER0A);
    TimerIntClear(TIMER0_BASE, TimerIntStatus(TIMER0_BASE, false));
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerEnable(TIMER0_BASE, TIMER_A);

    while(true)
    {
        //Check if we have received some bytes.
        if(RingBufEmpty(&rxRingBuf) == false)
        {
            // Did we receive enough bytes that it could be a message? In the real world you
            // need more complicated logic for multiple messages but this works for now.
            if(RingBufUsed(&rxRingBuf) == sizeof(message_t))
            {
                message_t receivedMsg;
                // Read the bytes into our received message structure.
                RingBufRead(&rxRingBuf, (uint8_t *)&receivedMsg, sizeof(message_t));


                // At this point we have a complete message. Note that bytes would have
                // to be endian swapped if it werent for the fact this is Little-Endian host
                // to little-endian host.
                bool stop;
                stop = true;
                UARTprintf("Code received is %d\n",receivedMsg.code);
            }
        }
    }

}

My modifications...

#include <stdint.h>
#include <stdbool.h>
#include <inc/hw_memmap.h>
#include <inc/hw_ints.h>
#include "inc/hw_types.h"
#include <driverlib/gpio.h>
#include <driverlib/sysctl.h>
#include <driverlib/uart.h>
#include <driverlib/timer.h>
#include <driverlib/interrupt.h>
#include <driverlib/pin_map.h>
#include "ringbuf.h"
#include "utils/uartstdio.h"
#include "utils/uartstdio.c"

#include "driverlib/debug.h"
#include "driverlib/adc.h"
#include "driverlib/sysctl.h"





// This is a dummy message formatted as a struct. Note that while the ISA
// is 32 bits the message is not perfectly aligned. I did this to demonstrate
// that the RT UART interrupt is required.
typedef struct {
    int32_t tempF;
} message_t;

#define RING_BUF_SIZE            512

// Tx buffer and backend array.
static tRingBufObject txRingBuf;
static uint8_t txBuf[RING_BUF_SIZE];

// Rx buffer and back end array.
static tRingBufObject rxRingBuf;
static uint8_t rxBuf[RING_BUF_SIZE];

uint32_t ui32ADC0Value[4];
uint32_t ui32TempAvg
uint32_t ui32TempValueC;
uint32_t ui32TempValueF;

void UART1IntHandler(void)
{
    uint32_t intStatus;



    // Retrieve masked interrupt status (only enabled interrupts).
    intStatus = UARTIntStatus(UART1_BASE, true);

    // Clear interrupt(s) after retrieval.
    UARTIntClear(UART1_BASE, intStatus);

    // Important: Note that they're all IF statements. This is because you can have an NVIC
    // system interrupt that is composed of all three sub-interrupts below. If you use the standard
    // if-elseif-else then you might miss one and drop bytes.

    // The receive timeout interrupt fires when you have received bytes in your FIFO but have not
    // gotten enough to fire your Rx interrupt. This is because the FIFO level select determines when that
    // interrupt goes off.
    if((intStatus & UART_INT_RT) == UART_INT_RT)
    {
        // While there are bytes to read and there is space in the FIFO.
        while(UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false)
        {
            // Write a byte straight from the hardware FIFO into our Rx FIFO for processing later.
            RingBufWriteOne(&rxRingBuf, (uint8_t)UARTCharGet(UART1_BASE));
        }
    }

    // The Rx interrupt fires when there are more than the fifo level select bytes in the FIFO.
    if((intStatus & UART_INT_RX) == UART_INT_RX)
    {
        // While there are bytes to read and there is space in the FIFO.
        while(UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false)
        {
            // Write a byte straight from the hardware FIFO into our Rx FIFO for processing later.
            RingBufWriteOne(&rxRingBuf, (uint8_t)UARTCharGet(UART1_BASE));
        }
    }

    // The transmit interrupt fires when there are less than the FIFO level select bytes waiting to
    // be transmitted. This way you can add more ensuring it's continuous transmission.
    if((intStatus & UART_INT_TX) == UART_INT_TX)
    {
        // While there is space left in the FIFO and we have bytes queued up for sending.
        while(UARTSpaceAvail(UART1_BASE) == true && RingBufEmpty(&txRingBuf) == false)
        {
            // Remove a byte from the queued Tx FIFO and add it to our UART tx fifo.
            UARTCharPut(UART1_BASE, RingBufReadOne(&txRingBuf));

        }
    }
}

void Timer0IntHandler(void)
{
    int32_t intStatus;
    message_t msg;
    uint8_t * ptr,
              byte;


    // Retrieve timer interrupt status.
    intStatus = TimerIntStatus(TIMER0_BASE, true);

    // Clear interrupt.
    TimerIntClear(TIMER0_BASE, intStatus);

    // Check if the interrupt was the correct one (timeout).
    if((intStatus & TIMER_TIMA_TIMEOUT) == TIMER_TIMA_TIMEOUT)
    {
        // This message population is just a placeholder for where an ADC or
        // other sensor might be sampled.
        msg.tempF = ui32TempValueF;

        // Cast the structure into a byte array.
        ptr = (uint8_t *)&msg;

        // Loop through the entire message.
        for(byte = 0; byte < sizeof(message_t); byte++)
        {
            // This part is pretty important... the UART Tx FIFO has a limited size
            // in fact it's smaller than our message. However the Tx interrupt will let us know
            // when we have less than 4 bytes remainign to send so we can stash the extra
            // bytes in our FIFO for later.

            // Is there space in the Tx FIFO?
            if(UARTSpaceAvail(UART1_BASE) == true)
            {
                // Put the byte into the Tx FIFO.
                UARTCharPut(UART1_BASE, ptr[byte]);


            }
            else
            {
                // Otherwise, stash the byte in our FIFO for when there's space.
                RingBufWriteOne(&txRingBuf, ptr[byte]);
            }
        }
    }
}

int main(void)
{
    // Run the microcontroller system clock at 80MHz.
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Enable peripheral and bank clocking.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralReset(SYSCTL_PERIPH_UART1);

    //#TEST Enables UART0 for console use.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //Configure the pins, uh..., plated holes for UART0
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    // Initialize the UART for console I/O. on UART0/BASE0
    UARTStdioConfig(0, 9600, SysCtlClockGet());
    //Set the baud rate, 8 data bits, one stop bit and no parity for UART0
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,
        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

    // Configure pin-muxing for the UART.
    GPIOPinConfigure(GPIO_PB0_U1RX);
    GPIOPinConfigure(GPIO_PB1_U1TX);
    GPIOPinTypeUART(GPIO_PORTB_BASE, (GPIO_PIN_0 | GPIO_PIN_1));

    // Configure the UART for 9600 8-N-1.
    UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 9600, (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE));
    UARTFIFOLevelSet(UART1_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    UARTEnable(UART1_BASE);

    // Initialize our FIFO's.
    RingBufInit(&txRingBuf, &txBuf[0], RING_BUF_SIZE);
    RingBufInit(&rxRingBuf, &rxBuf[0], RING_BUF_SIZE);

    // Enable the NVIC interrupt, clear the UART individual interrupts and then enable.
    IntEnable(INT_UART1);
    UARTIntClear(UART1_BASE, UARTIntStatus(UART1_BASE, false));
    UARTIntEnable(UART1_BASE, (UART_INT_TX | UART_INT_RX | UART_INT_RT));

    // Setup the timer to go off at 1Hz (periodically). This will be used to generate a message
    // for transmission.
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());
    IntEnable(INT_TIMER0A);
    TimerIntClear(TIMER0_BASE, TimerIntStatus(TIMER0_BASE, false));
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    TimerEnable(TIMER0_BASE, TIMER_A);

    //Enable the analog to digital converter. ADC0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    //use ADC0, sample sequencer 1, use the highest priority
    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
    //Configure all four steps in the ADC sequencer
    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_TS);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_TS);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_TS);
    //Sample the temperaturesensor(ADC_CTL_TS)and configure the interrupt flag(ADC_CTL_IE)
    //to be set when the sample is done. Tell the ADC logic that this is the last conversion on sequencer(ADC_CTL_END)
    ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);
    //Enable ADC sequencer 1.
    ADCSequenceEnable(ADC0_BASE, 1);

    ADCIntClear(ADC0_BASE, 1);
    ADCProcessorTrigger(ADC0_BASE, 1);

    while(!ADCIntStatus(ADC0_BASE, 1, false)) //Unknown time in this loop.
    {
    }
    ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
    ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;
    //Allows for whole number temperature. Does not allow for floating point values. Look at data sheet
    ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
    //ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
    ui32TempValueF = (ui32TempValueC * 9/5) + 32;

    while(true)
    {
        //Check if we have received some bytes.
        if(RingBufEmpty(&rxRingBuf) == false)
        {
            // Did we receive enough bytes that it could be a message? In the real world you
            // need more complicated logic for multiple messages but this works for now.
            if(RingBufUsed(&rxRingBuf) == sizeof(message_t))
            {
                message_t receivedMsg;
                // Read the bytes into our received message structure.
                RingBufRead(&rxRingBuf, (uint8_t *)&receivedMsg, sizeof(message_t));

                // At this point we have a complete message. Note that bytes would have
                // to be endian swapped if it werent for the fact this is Little-Endian host
                // to little-endian host.
                bool stop;
                stop = true;
                UARTprintf("Temperature received is %d\n",receivedMsg.tempF);
            }
        }
    }

}

  • If I move the sampling to where it is stated to be in the example...the code gets stuck at
    //Enable the analog to digital converter. ADC0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ...within main()


    void Timer0IntHandler(void)
    {
    int32_t intStatus;
    message_t msg;
    uint8_t * ptr,
    byte;

    // Retrieve timer interrupt status.
    intStatus = TimerIntStatus(TIMER0_BASE, true);

    // Clear interrupt.
    TimerIntClear(TIMER0_BASE, intStatus);

    // Check if the interrupt was the correct one (timeout).
    if((intStatus & TIMER_TIMA_TIMEOUT) == TIMER_TIMA_TIMEOUT)
    {
    // This message population is just a placeholder for where an ADC or
    // other sensor might be sampled.
    while(!ADCIntStatus(ADC0_BASE, 1, false)) //Unknown time in this loop.
    {
    }
    ADCSequenceDataGet(ADC0_BASE, 1, ui32ADC0Value);
    ui32TempAvg = (ui32ADC0Value[0] + ui32ADC0Value[1] + ui32ADC0Value[2] + ui32ADC0Value[3] + 2)/4;
    //Allows for whole number temperature. Does not allow for floating point values. Look at data sheet
    ui32TempValueC = (1475 - ((2475 * ui32TempAvg)) / 4096)/10;
    //ui32TempValueF = ((ui32TempValueC * 9) + 160) / 5;
    ui32TempValueF = (ui32TempValueC * 9/5) + 32;

    msg.tempF = ui32TempValueF;

    //Turn on Green LED to indicate temperatures are stored
    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3,8);
    SysCtlDelay(6000000);

    // Cast the structure into a byte array.
    ptr = (uint8_t *)&msg;

    // Loop through the entire message.
    for(byte = 0; byte < sizeof(message_t); byte++)
    {
  • Erik A said:
       // Important: Note that they're all IF statements. This is because you can have an NVIC
        // system interrupt that is composed of all three sub-interrupts below. If you use the standard
        // if-elseif-else then you might miss one and drop bytes.

    It's worse than that, it is quite possible for there to be multiples of the same to read.

    The timer interrupt conflicts with the uart interrupt. It might be possible to make that structure work but I would expect trouble.

    You only do a single conversion, I think.

    You receive on both micros but only transmit on one.

    Robert

    Using Syntaxhighlighter would be friendlier (see the </> in the upper right of advanced formatting)

  • Thank you for the speedy response Robert!

    The timer interrupt & uart interrupt exist in the sample code pasted first. I can get into the following chunk
    // Read the bytes into our received message structure.
    RingBufRead(&rxRingBuf, (uint8_t *)&receivedMsg, sizeof(message_t));

    and uartprint receivedMsg.code to PuTTY. (Seeing it in the debugger requires me to coordinate which board was programmed last)

    The conflict, would it simply be a chance of an issue or should I expect an issue every time?

    ...with that said, can you assist in removing either the timer interrupt or uart interrupt? All I care to do is sample the ADC and transmit it over UART via an interrupt. I'm getting very little help in terms of the sample code, so I'd be OK with any approach...as long as I have the means of asking questions.

    Thanks again and I look forward to further replies!
  • Hello Erik,

    Can you zip your project and attach the same? It makes tracing code execution easier

    Regards
    Amit
  • I zipped the project. There are two versions of main.c. Thank you for taking a look, I really appreciate it!


    main.c is the original

    main_adc.c is my attempt.

    On a side note. It was suggested to me that once I have the communication working, that I should convert my message to ascii and then remove the conversion on the receiving end. Would this be advisable?

    8507.UART.zip

  • One basic approach to serial transmit interrupt

    In Transmit Empty Interrupt

    if byte(s) in buffer

    send bytes

    else

    set prime_pump flag

    endif

    In send char/byte routine

    if prime_pump flag set

    disable interrupts

    clear prime_pump flag

    send byte

    enable interrupts

    else

    queue byte in buffer for transmit interrupt

    endif

    Robert

  • Thank you for the summary of what should be happening. I'll see if that assists me with overcoming my issue.

    In regards to my question about ascii, is it true that Code Composer/the tm4c don't support the itoa and atoi functions? It appears that these would have to be constructed from scratch if used.

    Thanks again, and I look forward to a response on the project.

  • In regards to my question about ascii, is it true that Code Composer/the tm4c don't support the itoa and atoi functions? It appears that these would have to be constructed from scratch if used.

    That would not be a "feature" of the compiler/IDE, but of the library you link against. There are usually several choices for this library (the "C standard library", clib), depending on your needs, and the code space (Flash) you can afford. However, none of the usual MCU implementations support the full POSIX range.

    AFAIK, the itoa() (and the whole ito<x> group) is implemented as macro in most (POSIX-compliant) cases. You could start with copying such a macro implementation. I'm not a CCS user, so I can't give specific hints here.

  • Hello,

    I'm just seeing if you've had a chance to check out the project I uploaded?


    Also, I discovered that I am getting stuck in the FaultISR every time I run this code. I found a forum post talking about the ADC and FaultISR but I wasn't able to get too much from it. I did make some changes as to where my code was implemented. I will upload the new version of main.c.

    I am looking to get this issue complete soon. I really hope you can help me overcome it.

    Thanks!

    //*****************************************************************************
    //
    // Startup code for use with TI's Code Composer Studio.
    //
    // Copyright (c) 2011-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    
    //*****************************************************************************
    //
    // Forward declaration of the default fault handlers.
    //
    //*****************************************************************************
    void ResetISR(void);
    static void NmiSR(void);
    static void FaultISR(void);
    static void IntDefaultHandler(void);
    
    //*****************************************************************************
    //
    // External declaration for the reset handler that is to be called when the
    // processor is started
    //
    //*****************************************************************************
    extern void _c_int00(void);
    
    //*****************************************************************************
    //
    // Linker variable that marks the top of the stack.
    //
    //*****************************************************************************
    extern uint32_t __STACK_TOP;
    
    //*****************************************************************************
    //
    // External declarations for the interrupt handlers used by the application.
    //
    //*****************************************************************************
    extern void UART1IntHandler(void);
    extern void Timer0IntHandler(void);
    
    //*****************************************************************************
    //
    // The vector table.  Note that the proper constructs must be placed on this to
    // ensure that it ends up at physical address 0x0000.0000 or at the start of
    // the program if located at a start address other than 0.
    //
    //*****************************************************************************
    #pragma DATA_SECTION(g_pfnVectors, ".intvecs")
    void (* const g_pfnVectors[])(void) =
    {
        (void (*)(void))((uint32_t)&__STACK_TOP),
                                                // The initial stack pointer
        ResetISR,                               // The reset handler
        NmiSR,                                  // The NMI handler
        FaultISR,                               // The hard fault handler
        IntDefaultHandler,                      // The MPU fault handler
        IntDefaultHandler,                      // The bus fault handler
        IntDefaultHandler,                      // The usage fault handler
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // SVCall handler
        IntDefaultHandler,                      // Debug monitor handler
        0,                                      // Reserved
        IntDefaultHandler,                      // The PendSV handler
        IntDefaultHandler,                      // The SysTick handler
        IntDefaultHandler,                      // GPIO Port A
        IntDefaultHandler,                      // GPIO Port B
        IntDefaultHandler,                      // GPIO Port C
        IntDefaultHandler,                      // GPIO Port D
        IntDefaultHandler,                      // GPIO Port E
        IntDefaultHandler,                      // UART0 Rx and Tx
        UART1IntHandler,                        // UART1 Rx and Tx
        IntDefaultHandler,                      // SSI0 Rx and Tx
        IntDefaultHandler,                      // I2C0 Master and Slave
        IntDefaultHandler,                      // PWM Fault
        IntDefaultHandler,                      // PWM Generator 0
        IntDefaultHandler,                      // PWM Generator 1
        IntDefaultHandler,                      // PWM Generator 2
        IntDefaultHandler,                      // Quadrature Encoder 0
        IntDefaultHandler,                      // ADC Sequence 0
        IntDefaultHandler,                      // ADC Sequence 1
        IntDefaultHandler,                      // ADC Sequence 2
        IntDefaultHandler,                      // ADC Sequence 3
        IntDefaultHandler,                      // Watchdog timer
        Timer0IntHandler,                       // Timer 0 subtimer A
        IntDefaultHandler,                      // Timer 0 subtimer B
        IntDefaultHandler,                      // Timer 1 subtimer A
        IntDefaultHandler,                      // Timer 1 subtimer B
        IntDefaultHandler,                      // Timer 2 subtimer A
        IntDefaultHandler,                      // Timer 2 subtimer B
        IntDefaultHandler,                      // Analog Comparator 0
        IntDefaultHandler,                      // Analog Comparator 1
        IntDefaultHandler,                      // Analog Comparator 2
        IntDefaultHandler,                      // System Control (PLL, OSC, BO)
        IntDefaultHandler,                      // FLASH Control
        IntDefaultHandler,                      // GPIO Port F
        IntDefaultHandler,                      // GPIO Port G
        IntDefaultHandler,                      // GPIO Port H
        IntDefaultHandler,                      // UART2 Rx and Tx
        IntDefaultHandler,                      // SSI1 Rx and Tx
        IntDefaultHandler,                      // Timer 3 subtimer A
        IntDefaultHandler,                      // Timer 3 subtimer B
        IntDefaultHandler,                      // I2C1 Master and Slave
        IntDefaultHandler,                      // Quadrature Encoder 1
        IntDefaultHandler,                      // CAN0
        IntDefaultHandler,                      // CAN1
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // Hibernate
        IntDefaultHandler,                      // USB0
        IntDefaultHandler,                      // PWM Generator 3
        IntDefaultHandler,                      // uDMA Software Transfer
        IntDefaultHandler,                      // uDMA Error
        IntDefaultHandler,                      // ADC1 Sequence 0
        IntDefaultHandler,                      // ADC1 Sequence 1
        IntDefaultHandler,                      // ADC1 Sequence 2
        IntDefaultHandler,                      // ADC1 Sequence 3
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // GPIO Port J
        IntDefaultHandler,                      // GPIO Port K
        IntDefaultHandler,                      // GPIO Port L
        IntDefaultHandler,                      // SSI2 Rx and Tx
        IntDefaultHandler,                      // SSI3 Rx and Tx
        IntDefaultHandler,                      // UART3 Rx and Tx
        IntDefaultHandler,                      // UART4 Rx and Tx
        IntDefaultHandler,                      // UART5 Rx and Tx
        IntDefaultHandler,                      // UART6 Rx and Tx
        IntDefaultHandler,                      // UART7 Rx and Tx
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // I2C2 Master and Slave
        IntDefaultHandler,                      // I2C3 Master and Slave
        IntDefaultHandler,                      // Timer 4 subtimer A
        IntDefaultHandler,                      // Timer 4 subtimer B
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // Timer 5 subtimer A
        IntDefaultHandler,                      // Timer 5 subtimer B
        IntDefaultHandler,                      // Wide Timer 0 subtimer A
        IntDefaultHandler,                      // Wide Timer 0 subtimer B
        IntDefaultHandler,                      // Wide Timer 1 subtimer A
        IntDefaultHandler,                      // Wide Timer 1 subtimer B
        IntDefaultHandler,                      // Wide Timer 2 subtimer A
        IntDefaultHandler,                      // Wide Timer 2 subtimer B
        IntDefaultHandler,                      // Wide Timer 3 subtimer A
        IntDefaultHandler,                      // Wide Timer 3 subtimer B
        IntDefaultHandler,                      // Wide Timer 4 subtimer A
        IntDefaultHandler,                      // Wide Timer 4 subtimer B
        IntDefaultHandler,                      // Wide Timer 5 subtimer A
        IntDefaultHandler,                      // Wide Timer 5 subtimer B
        IntDefaultHandler,                      // FPU
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // I2C4 Master and Slave
        IntDefaultHandler,                      // I2C5 Master and Slave
        IntDefaultHandler,                      // GPIO Port M
        IntDefaultHandler,                      // GPIO Port N
        IntDefaultHandler,                      // Quadrature Encoder 2
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // GPIO Port P (Summary or P0)
        IntDefaultHandler,                      // GPIO Port P1
        IntDefaultHandler,                      // GPIO Port P2
        IntDefaultHandler,                      // GPIO Port P3
        IntDefaultHandler,                      // GPIO Port P4
        IntDefaultHandler,                      // GPIO Port P5
        IntDefaultHandler,                      // GPIO Port P6
        IntDefaultHandler,                      // GPIO Port P7
        IntDefaultHandler,                      // GPIO Port Q (Summary or Q0)
        IntDefaultHandler,                      // GPIO Port Q1
        IntDefaultHandler,                      // GPIO Port Q2
        IntDefaultHandler,                      // GPIO Port Q3
        IntDefaultHandler,                      // GPIO Port Q4
        IntDefaultHandler,                      // GPIO Port Q5
        IntDefaultHandler,                      // GPIO Port Q6
        IntDefaultHandler,                      // GPIO Port Q7
        IntDefaultHandler,                      // GPIO Port R
        IntDefaultHandler,                      // GPIO Port S
        IntDefaultHandler,                      // PWM 1 Generator 0
        IntDefaultHandler,                      // PWM 1 Generator 1
        IntDefaultHandler,                      // PWM 1 Generator 2
        IntDefaultHandler,                      // PWM 1 Generator 3
        IntDefaultHandler                       // PWM 1 Fault
    };
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor first starts execution
    // following a reset event.  Only the absolutely necessary set is performed,
    // after which the application supplied entry() routine is called.  Any fancy
    // actions (such as making decisions based on the reset cause register, and
    // resetting the bits in that register) are left solely in the hands of the
    // application.
    //
    //*****************************************************************************
    void
    ResetISR(void)
    {
        //
        // Jump to the CCS C initialization routine.  This will enable the
        // floating-point unit as well, so that does not need to be done here.
        //
        __asm("    .global _c_int00\n"
              "    b.w     _c_int00");
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a NMI.  This
    // simply enters an infinite loop, preserving the system state for examination
    // by a debugger.
    //
    //*****************************************************************************
    static void
    NmiSR(void)
    {
        //
        // Enter an infinite loop.
        //
        while(1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a fault
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    FaultISR(void)
    {
        //
        // Enter an infinite loop.
        //
        while(1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives an unexpected
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    IntDefaultHandler(void)
    {
        //
        // Go into an infinite loop.
        //
        while(1)
        {
        }
    }
    

  • Hello Amit,

    Have you had a chance to look over the project I uploaded? I still haven't resolved the issue and I could use a hand.

    Thanks!

  • Hello Erik,

    My apologies on not coming back to the issue earlier. I had been busy with USB DMA Library implementation for another forum user.

    Regards
    Amit
  • Understood, thank you for the update! I look forward to your assistance!

  • I did come across Lab4 from the TI workshop that discusses an example of why a FAULTISR would occur. It doesn't really help me that much, but according to it I might not be initializing a peripheral correctly. Hopefully that helps shine some light on this code.

    Thanks again.

    engineering.purdue.edu/.../LM4F-LaunchPad-04 - Interrupts & Timers.pdf
  • ON that note, I believe I resolved the issue. I was trying to use an LED within the interrupt. However, I did not initialize the peripheral within the interrupt. Now I need to get the code to work as it should.

    Thanks for listening.
  • Hello Erik,

    I was trying to get the code working this morning. What is PB0 and PB1 connected to?

    Regards
    Amit
  • Hello Amit
    Thanks for the reply. PB1 is on a tm4c that collects temperature from the ADC. It uses PB1 as uart1 TX...

    PB0 is on the second tm4c that uses PB0 as uart1 RX. From there the data is shown on putty.

    You did see that I seemed to resolve the issue a few moments before your post? I did not have the LED GPIOF initalized. It gave me a fault instead of a compilation error unfortunately.
  • Hello Erik,

    Yes, I did. I know why the issue is occurring. During a previous run the Interrupt bit may have been set, and a new run is causing the CPU to jump to the interrupt handler while the port is not initialized.

    The correct approach would be to perform a System Reset instead of a CPU reset when reloading or re-running the code.

    Regards
    Amit