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.

TM4C1231E6PZ processor hangs once Timer Interrupt is enabled

Other Parts Discussed in Thread: TM4C1231E6PZ

TM4C1231E6PZ 's GPIO and SSI functionality is working OK in our board.

When we try the timer interrupt - in ONE-SHOT or periodic mode- as indicated by your examples in the peripherals folder , it hangs and does not come out of the following loop:

//
// Wait for interrupt to occur
//
while(!g_bIntFlag)
{
}

The timer is set for 1 msec ; I tried higher time intervals also unsuccessfully.

With     IntEnable(INT_TIMER0B);    statement commented out ,other loop ( like the while loop in Blinky.c) following it runs.

Since the timer is fully an internal resource , I am at a loss to understand the problem.

  • Hello Nagaranjan,

    Did you check if the Timer interrupt is being triggered? Could the interrupt not being triggered be the reason for the value not changing?

    Thanks,
    Sai
  • Thanks for a very quick reply.

    The code is as per Timer examples in peripheral folder :

    As soon as the line below is un commented , it doesnot move further; It appears to me that the code either does not go the interrpt routine or dors not return from it. The ISR is simple as in your example - just setting a flag.

    ( Incidentally , the part was purchased from Mouser only this month ; The part number has TM4C1231E6PZI but no number after that; The data code is 42 implying it is Feb14 version ; I hope it is not a bug related to the silicon version).

    //IntEnable(INT_TIMER0B);

    The full c program is appended below ,for your review ( I can't see a way to attach files , so code is appended below):

    /*
    * main.c
    */
    #include <stdint.h>
    #include <stdbool.h>
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/inc/hw_memmap.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/inc/hw_ints.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/gpio.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/pin_map.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/ssi.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/sysctl.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/timer.h"
    #include "C:/ti/TivaWare_C_Series-2.1.2.111/driverlib/interrupt.h"

    //*****************************************************************************
    //
    // Number of bytes to send and receive through SPI Port
    //
    //*****************************************************************************
    #define NUM_SSI_DATA_DAC 1 // One 16 bit data for the DACs
    //*****************************************************************************
    //
    // Counter to count the number of interrupts that have been called.
    //
    //*****************************************************************************
    static volatile uint32_t g_ui32Counter = 0;
    static volatile uint8_t data_LED1=0;
    static volatile bool g_bIntFlag = false;

    //*****************************************************************************
    //
    // The interrupt handler for the Timer0B interrupt.
    //
    //*****************************************************************************
    void
    Timer0BIntHandler(void)
    {
    //
    // Clear the timer interrupt flag.
    //
    TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

    //
    // Set a flag to indicate that the interrupt occurred.
    //
    g_bIntFlag = true;

    //
    // Update the periodic interrupt counter.
    //
    g_ui32Counter++;

    }


    int main(void) {

    volatile uint32_t ui32Loop;
    uint32_t pui32DataTx[NUM_SSI_DATA_DAC];
    uint32_t pui32DataRx[NUM_SSI_DATA_DAC];
    uint32_t ui32Index;

    // We will use the driverlib - Reference code examples are:
    // GPIO: Blinky.c in Examples ( peripherals folder)
    // SPI code Ref: SPI_Master.c in Examples ( peripherals folder)
    // Timer : periodic_16bit.c in Examples ( peripherals folder)

    //
    // Set the clocking to run directly from the internal oscillator.
    // Changed from ref code : spi_master.c to use internal oscillator-INT instead of main

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_INT | SYSCTL_XTAL_16MHZ);

    //
    // The SSI0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);


    // Adopted from Blinky.c in example folder of TIVA Cware
    // Ports and pins changed for Trans5_v1p0 board
    // Enable the GPIO port that is used for the on-board LEDs.
    // LED1 : PJ0, LED2 : PJ1 (and LED3 : PB0)
    // Port A : 2 to5 are used for SPI-Details below
    // SPI_~CS~_DAC3 is PD1

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Check if the peripheral access is enabled , we will check only the last two , if it is done others must be too
    //
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
    {
    }
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD))
    {
    }

    //
    // Enable the GPIO pin for the LED1 (PJ0) ,LED2 (PJ1) , LED3 ( PB0) and SPI_~CS~_DAC ( PD1).
    //Set the direction as output, and
    // enable the GPIO pin for digital function.
    //
    GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_0);//LED1
    GPIOPinTypeGPIOOutput(GPIO_PORTJ_BASE, GPIO_PIN_1);//LED2
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0);//LED3
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1);//SPI_~CS~_DAC3

    //
    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);

    // Default value for cs
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1);// Be careful here , 0x01 wont work

    //
    // Configure the GPIO settings for the SSI pins. This function also gives
    // control of these pins to the SSI hardware.
    // The pins are assigned as follows:
    // PA5 - SSI0Tx
    // PA4 - SSI0Rx
    // PA3 - SSI0Fss ( unused in our Board ) - Chip selects used instead to select device
    // PA2 - SSI0CLK

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
    //
    // Configure and enable the SSI port for SPI master mode. Use SSI0,
    // system clock supply, idle clock level low and active low clock in
    // freescale SPI mode, master mode, 1MHz SSI frequency, and 16-bit data.
    // For SPI mode, you can set the polarity of the SSI clock when the SSI
    // unit is idle. You can also configure what clock edge you want to capture data on.
    // Change from Ref code: SSI_FRF_MOTO_MODE_1 instead of SSI_FRF_MOTO_MODE_0
    // for DAC captures data on neg edge and 8 bits to 16 bits

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1,
    SSI_MODE_MASTER, 1000000, 16);


    //
    // Enable the SSI0 module.
    //
    SSIEnable(SSI0_BASE);

    //
    // Read any residual data from the SSI port. This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk. This is done here
    // because the SPI SSI mode is full-duplex, which allows you to send and
    // receive at the same time. The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    //
    while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[0]))
    {
    }

    //
    // Initialize the data to send.0x4000 should give max output of 3.3V in AD5621 DAC
    // Qe will try with 0x2000 to get 1.65V out
    //
    pui32DataTx[0] = 0x2000;// 16 bit data ;0x4000 should give 3.3V and 0x2000 should give 1.65V ; Found OK


    // Before transmission pull CS of DAC3 Low

    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, 0x0);

    //
    // Send 1 word of 16 bits of data.
    //
    for(ui32Index = 0; ui32Index < NUM_SSI_DATA_DAC; ui32Index++)
    {
    //
    // Send the data using the "blocking" put function. This function
    // will wait until there is room in the send FIFO before returning.
    // This allows you to assure that all the data you send makes it into
    // the send FIFO.
    //
    SSIDataPut(SSI0_BASE, pui32DataTx[ui32Index]);
    }

    //
    // Wait until SSI0 is done transferring all the data in the transmit FIFO.
    //
    while(SSIBusy(SSI0_BASE))
    {
    }

    // After transmission pull CS of DAC3 High

    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1);

    //
    // The Timer0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    //
    // Configure Timer0B as a 16-bit periodic timer.
    //
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT);//TIMER_CFG_B_PERIODIC);

    //
    // Set the Timer0B load value to 1ms.
    //
    TimerLoadSet(TIMER0_BASE, TIMER_B, SysCtlClockGet() / 1000);

    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Configure the Timer0B interrupt for timer timeout.
    //
    TimerIntEnable(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

    //
    // Clear any pending interrupt flag.
    //
    TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

    //
    // Enable the Timer0B interrupt on the processor (NVIC).
    //
    //IntEnable(INT_TIMER0B);

    //
    // Initialize the interrupt counter.
    //
    g_ui32Counter = 0;

    //
    // Enable Timer0B.
    //
    TimerEnable(TIMER0_BASE, TIMER_B);

    //
    // Wait for interrupt to occur
    //
    //while(!g_bIntFlag)
    {
    }

    //
    // Loop forever.
    //
    while(1)
    {
    //
    // Turn oN the LED1 and 3 by writing 0 and turn off LED2 by writing 1 on the bit
    //

    GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_0, 0x0);
    GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_1, GPIO_PIN_1);// Be careful here , 0x01 wont work
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0x0);

    //
    // Delay for a bit.
    //
    for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
    {
    }

    //
    // Turn off the LED by writing 1 on the bit
    //

    GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_0, GPIO_PIN_0);
    GPIOPinWrite(GPIO_PORTJ_BASE, GPIO_PIN_1, 0x0);
    GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0);


    //
    // Delay for a bit.
    //
    for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
    {
    }
    }

    //return 0;
    }

  • The problem has been resolved.

    The Interrupt handler has to be registered as given in Sec 29.2.2.18 of driver lib document .

    Once the fillowing line was added the problem was resolved:

    TimerIntRegister(TIMER0_BASE, TIMER_B, Timer0BIntHandler);

    Surprisingly , this step is missing from your examples.

  • The "TimerIntRegister" function will configure the Interrupt handler dynamically.

    In TivaWare examples, the interrupt handler is configured, statically, by adding them to the interrupt vector table, in the startup code.

    Statically configuring the interrupts is the recommended method as the response time is faster than dynamic configuring. "Chapter 17 - Interrupt Controller" of the TivaWare Peripheral Driver Library User's Guide has more information about these two types of configuration.

    Thanks,

    Sai

  • Hi ,
    Thanks. The startup_ccs.c generatted automatically in my project ( as well as those present in the examples) map all interrupts to a IntDefaultHandler which in turn contains a perennial while(1) loop.This explains the behaviour observed by me that the processor hangs at this point.
    Am I to manually edit any source line in startup_ccs.c to map my interrupt to the handler and if so how?Where is it done in example projects?
    Thanks for your clarification and looking forward to your reply.
  • Hello Nagarajan,

    Yes the user is expected to manually edit the "startup_ccs.c" file using any editor. Since you are using CCS, the CCS editor can be used to edit this file.

    Thanks,
    Sai