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.

CCS/EK-TM4C123GXL: TimerConfigure causing a Fault

Part Number: EK-TM4C123GXL

Tool/software: Code Composer Studio

Hi people,

I'm facing a problem, my program is designed to enable 3 timers. These 3 timers I'm splitting into pairs to generate a total of 6 periodic interrupts. The problem is that when I configure the last timer, it enters the Fault ISR as soon as the processor reads the TimerConfigure line. What's causing this? It's some limitation, or I'm missing some configuration?

Stack size is 4096, I tested with and without ROM, I'm using UART_BUFFERED.

The  main code is as it follows:

int main(void)
{
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    MAP_FPUEnable();
    MAP_FPULazyStackingEnable();
    MAP_IntMasterEnable();

    init_all_periph();

    config_UART(UART0, SYSTEM, 921600);
    
    config_LED();
    
    config_Display1602();
    
    config_TIMER0();
    
    config_TIMER1();
    
    config_TIMER2();
    
    config_WTIMER1();
   
    config_HibernateRTC();
    
    init_Cronometro();

    for(;;);
}

The code for initializing the peripherals:

inline void init_all_periph(void)
{
    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOA);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOA);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOB);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOB);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOC);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOC);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOC));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOD);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOD);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOE);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOF);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOF);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER1);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER1);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER1));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER2);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER2);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER2));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_WTIMER0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_WTIMER0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER0));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_PWM0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_PWM0);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_PWM1);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_PWM1);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_PWM1));

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_HIBERNATE);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_HIBERNATE);
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_HIBERNATE));
}

The code for initializing the timers is given below:

/*
 * TIMERA 3Hz
 * TIMERB 2Hz
 */
inline void config_TIMER0(void)
{
    MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC);

    MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, (MAP_SysCtlClockGet()/3) -1);
    MAP_TimerLoadSet(TIMER0_BASE, TIMER_B, (MAP_SysCtlClockGet()/2) -1);

    MAP_IntDisable(INT_TIMER0A);
    MAP_IntDisable(INT_TIMER0B);
    MAP_TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);
    MAP_IntPendClear(INT_TIMER0A);
    MAP_IntPendClear(INT_TIMER0B);
    MAP_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_IntPrioritySet(INT_TIMER0A, 0x40);
    MAP_IntPrioritySet(INT_TIMER0B, 0x60);

    MAP_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_IntEnable(INT_TIMER0A);
    MAP_IntEnable(INT_TIMER0B);

    while(!MAP_IntIsEnabled(INT_TIMER0A) || !MAP_IntIsEnabled(INT_TIMER0B));

    MAP_TimerEnable(TIMER0_BASE, TIMER_BOTH);
}

/*
 * TIMERA 100Hz
 * TIMERB 10Hz
 */
inline void config_TIMER1(void)
{
    MAP_TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC);

    MAP_TimerLoadSet(TIMER1_BASE, TIMER_A, (MAP_SysCtlClockGet()/100) -1);
    MAP_TimerLoadSet(TIMER1_BASE, TIMER_B, (MAP_SysCtlClockGet()/10) -1);

    MAP_IntDisable(INT_TIMER1A);
    MAP_IntDisable(INT_TIMER1B);
    MAP_TimerIntDisable(TIMER1_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);
    MAP_IntPendClear(INT_TIMER1A);
    MAP_IntPendClear(INT_TIMER1B);
    MAP_TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_IntEnable(INT_TIMER1A);
    MAP_IntEnable(INT_TIMER1B);

    while(!MAP_IntIsEnabled(INT_TIMER1A) || !MAP_IntIsEnabled(INT_TIMER1B));

    MAP_TimerEnable(TIMER1_BASE, TIMER_BOTH);
}

/*
 * TIMERA 1Hz
 * TIMERB 50Hz
 */
inline void config_TIMER2(void)
{
    MAP_TimerConfigure(TIMER2_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC);

    MAP_TimerLoadSet(TIMER2_BASE, TIMER_A, (MAP_SysCtlClockGet()/1) -1);
    MAP_TimerLoadSet(TIMER2_BASE, TIMER_B, (MAP_SysCtlClockGet()/50) -1);

    MAP_IntDisable(INT_TIMER2A);
    MAP_IntDisable(INT_TIMER2B);
    MAP_TimerIntDisable(TIMER2_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);
    MAP_IntPendClear(INT_TIMER2A);
    MAP_IntPendClear(INT_TIMER2B);
    MAP_TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);

    MAP_IntEnable(INT_TIMER2A);
    MAP_IntEnable(INT_TIMER2B);

    while(!MAP_IntIsEnabled(INT_TIMER2A) || !MAP_IntIsEnabled(INT_TIMER2B));

    MAP_TimerEnable(TIMER2_BASE, TIMER_BOTH);
}

Thanks!

  • What happens if you "exchange" the position of  "Config Timer0" (first) with that of  "Config Timer2"  (now last?)       (i.e. Exchange the "order of  code execution" w/in your "Config TIMERx" code blocks)

    The parallelism between your Timer code blocks is high/proper - changing the order of calls may prove revealing.        (and is quick/easy)

  • While your kind "Like" is always appreciated - your report of the "directed test's" outcome - far better enables the resolution of your issue.

    And the test I've devised for you could not be faster/simpler...    (cb1's "preferred" kind of test...)

  • Tried that, and it gave me the same problem, except that in this case if I use the step over in the debug mode, program runs fine. I guess that's because the interrupts from the previous timers was somehow disrupting the configuration. Then I just moved the TimerEnable calls after configuring the timers, and bam, problem solved. I would not have figured out without this simple hint you gave me, thanks! (and yes, a bit of luck, since exchanging the timer position I was able at least to bypass the fault condition)
  • The expression, "Damning w/faint praise" (somehow) comes to mind.        "SIMPLE hint" - did it not quickly/easily - just as promised - drive you to the solution?

    I did note that you had "enabled" the Timers (rather early) - yet the fact that "two of three" accepted that insult - led me to "hold fire."

    Yes "luck" did arrive - but only after some considered effort - and the result cannot be diminished -  you are AGAIN, "Up/Running..."

  • Hello, "Helder from the Sales department",

    I bet that if you had inspected the FaultISR when the error happened before, you'd find that the cause was not the timer enabling, but rather something else in the interrupt routine - that's even considering that it had already been registered...

    But the reason I really wanted to write is regarding this sequence:

    MAP_IntEnable(INT_TIMER1A);
    MAP_IntEnable(INT_TIMER1B);
    while(!MAP_IntIsEnabled(INT_TIMER1A) || !MAP_IntIsEnabled(INT_TIMER1B));

    Different than what happens when enabling a peripheral, the IntEnable() is pretty much a direct setting, and I'd say that, while the confirmation line does not hurt, it is not really necessary... (no criticism whatsoever, just a thought that came to mind).

    Cheers

    Bruno
  • Hi Bruno,

    Since I had a problem related to enabling a peripheral -and discovered after so much pain- I prefer to make things as "right" as possible. Didn't know about that though.

    Regards

    Helder