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.

StarterWare timer interrupt issue

Other Parts Discussed in Thread: AM3359

Hi all,

I'm trying some bare-metal (no OS) programming on my BeagleBone (rev A6) with the aid of StarterWare on CCS v5.3. I'm trying to build a project, based on the DM timer counter example provided with StarterWare, that configures a timer and toggles the LED on the board every time the timer interrupt fires. 

My problem is that the timer interrupt (for timer 2) does not seem to fire. The code within the timer interrupt does not seem to execute, and a breakpoint that is placed within the ISR I defined never pauses execution. When I manually pause the execution and check the appropriate register location I see the timer counter value changing, so it seems apparent to me that the timer was configured and set up properly. However, it looks like something prevented my ISR setup from working. I find this especially strange because I don't have any additional code after setting up the timer interrupts that could have mangled the configuration.

Code follows, thanks in advance for any advice or suggestions.

/*
* main.c
*/

// Timer reference: dmTimerCounter.c example code file.
// See page 116 (PDF page 119) of the StarterWare users guide.

#include "dmtimer.h"
#include "interrupt.h"
#include "gpio_v2.h"

#include "soc_AM335x.h"
#include "beaglebone.h"

static void hardware_init();
static void timer_init();
static void timer_config(unsigned long, unsigned long);
static void isr_timer2();

int main(void) {
   // Set up hardware and peripherals.
   hardware_init();


   // Configure timer settings
   timer_config(0xF0000000u, 0xF0000000u);
   timer_init();


   // XXX: Turn on LED
   GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);

   // Enable timer interrupt
   DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

   // Turn on actual timer
   DMTimerEnable(SOC_DMTIMER_2_REGS);

   // Loop forever- all work takes place in ISRs.
   while(1) ;
}


static void hardware_init() {
   // Configure GPIO/LED
   GPIO1ModuleClkConfig();
   GPIO1Pin23PinMuxSetup();
   GPIOModuleEnable(SOC_GPIO_1_REGS);
   GPIOModuleReset(SOC_GPIO_1_REGS);

   /* Set GPIO 1.23 as output */
   GPIODirModeSet(SOC_GPIO_1_REGS, (23), GPIO_DIR_OUTPUT);
}

static void timer_init() {
   // Set up the configuration for the hardware timer.

   /* Enable clocks for DMTimer2 */
   DMTimer2ModuleClkConfig();

   /* Initialize ARM interrupt controller (AINTC) */
   IntAINTCInit();

   /* Register our ISR to DMTimer2's interrupt. */
   IntRegister(SYS_INT_TINT2, isr_timer2);

   /* Set the DMTimer2's interrupt priority to 0. */
   IntPrioritySet(SYS_INT_TINT2, 0, AINTC_HOSTINT_ROUTE_IRQ);

   /* Enable the DMTimer2 interrupt. */
   IntSystemEnable(SYS_INT_TINT2);

   /* Enable IRQ in CPSR (ARM program status register) */
   IntMasterIRQEnable();
}

static void timer_config(unsigned long initial, unsigned long reload) {
   // Configure timer
   // Note that instead of doing a count from 0 to some compare value, we are
   // preloading the timer with a given value and watching for it to overflow,
   // which is functionally identical.

   /* Configure the timer mode. */
   // Modes: autoreload (selected) versus one-shot mode. Does the timer automatically reset itself?
   // compare versus overflow (selected) mode. Does the timer ISR trip on equality to a value, or on overflow?
   DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);

   /* Load initial counter value into timer. */
   DMTimerCounterSet(SOC_DMTIMER_2_REGS, initial);

   /* Load reload counter value into timer, the value the timer gets every time it is reset. */
   DMTimerReloadSet(SOC_DMTIMER_2_REGS, reload);
}

// Interrupt vector for BeagleBone timer
static void isr_timer2() {
   static short int mode = 0;

   /* Disable the DMTimer interrupt */
   DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

   /* Clear the interrupt flags (IF) status */
   DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG);

   /* *********** ISR TASKS BEGIN *********** */
   if (mode == 0) {
      // Turn on LED
      GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);
      mode = 1;
   } else {
      // Turn off LED
      GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_LOW);
      mode = 0;
   }
   /* *********** ISR TASKS END *********** */

   /* Re-enable the DMTimer interrupt */
   DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
}

  • Hello,

    Your period with 24MHz clock and used initial/reload (0xF0000000) is now 11.1848 sek. Is it intentional ?

    Best regards,

    Mariusz.

  • Hi Mariusz,

    Thank you for your reply. I have been trying a variety of initial/reload values, some much less than a second and some that are several seconds. Unfortunately, all of these have failed to cause the timer interrupt to trigger, even as I can see the timer counter value (at 0x4804003C) "overflowing" (rolling over) as I pause execution repeatedly. I am wondering if there are any particular restrictions for the reload and initial values.

    My apologies in advance if I misunderstood your question. 

  • Hi Austin,

    your example works on my beaglebone. Could you please try the attached .out file ?

    Best regards,

    Mariusz.

    4101.dmtimerCounter.zip

  • Hi Mariusz,

    I really appreciate the time you took to try out my program! I am wondering what utility I should use to directly load a hex/bin file onto the BeagleBone, like the one you attached. I am familiar with the SmartRF Flash Programmer and the LM Flash Programmer for other TI parts (CC and Stellaris), but I wasn't able to find an equivalent that supports the BeagleBone. Or is there a way to load a .out file into the bone using CCS without debugging?

    Again, thank you very much!

    Austin

  • Hi Austin,

    please start the Debug mode and select from menu:  Run->Load Program, then browse and select the .out file.

    There is also Dmtimer example available for beaglebone in the StarterWare. Please import and run it also.

    Please check and compare its project configuration.

    The example can be imported from ...\build\armv7a\cgt_css\am335x\beaglebone

    In case the example also doesn't work, please recompile:

    - "platform"  :  ...\build\armv7a\cgt_css\am335x\beaglebone\platform

    - "system" :  ...\build\armv7a\cgt_ccs\am335x\system_config

    - "drivers" : ...\build\armv7a\cgt_ccs\am335x\drivers

    - "utils" : \build\armv7a\cgt_ccs\utils

    All above have to be imported with Project->Import existing...   Do not copy projects into the workspace !

    Please read the UserGuide located there  .../doc

    http://processors.wiki.ti.com/index.php/StarterWare_Getting_Started_02.00.XX.XX

    http://processors.wiki.ti.com/index.php/Quick_Start_Guide_StarterWare_02.00.XX.XX_%28supports_AM335x%29

    http://processors.wiki.ti.com/index.php/StarterWare_02.00.00.05_User_Guide

    Best regards,

    Mariusz

  • Hi Mariusz,

    Thank you for the advice. After changing my configuration settings, I was able to get both the dmtimer example code working, and my own code working in the dmtimer project. 

    I realized the key difference between my project and the dmtimer project was the fact that the linker referenced a .cmd file (it was called dmtimerCounter.cmd but the comments seemed to indicate it was a generic command file for TMS470). Once I configured my project's linker to reference that .cmd file as well things worked. I have one final question - I am just curious why I needed to include that .cmd file, and why AM3359.cmd (which is specified in general project options) wasn't sufficient. Is there a way to automatically include this TMS470 .cmd file into future projects, or will including (and modifying) it be a manual step?

  • Hi Austin,

      I am facing similar situation as explained earlier.

      DMTimer ISR is working in Starterware workspace.

      After i imported it to my custom workspace. I am not able to get ISR work.

       Kindly update what configurations settings did you do.

      Also am not able to compile with DMTimer.cmd as it throws Undefined "Entry" symbol error.

     kindly help as trying to make it work for two days but no respite

      

      

      

  • Hi Sandeep,

    Have you made progress on this query? 

    You would need to post this as a new query. For start could you check if the timer is running by checking the TCRR register. if yes then the next thing to check would be the interrupt status register. Please check the TISR Register for this. If the status shows that the interrupt has occured, then you would need to check whether the global interrupts are turned on. Since you have moved to your workspace , I suspect this ( global interrupt not on) to be the issue.

  • Hi,

    I have a similar problem, I have added utils, drive, platform and systems

    I cannot get the interrupts going for Timer (or uart).

    On further investigation i found that the timer module is working just fine and is giving a overflow status.

    The issue is with CPSR resistor in the cortex core.

    I am unable to enable interrupts by resetting the IRQ bit in the CPSR resistor.

    Where R0 = 0x40000110

    CPSR = 0x40000190

    When i do a  msr     CPSR, r0

    I still get CPSR = 0x40000190 where IRQ is disabled... 

    I am sure that I am missing something here,.. can anyone please help

    Code below for reference -

    #include "dmtimer.h"
    #include "interrupt.h"
    #include "gpio_v2.h"

    #include "soc_AM335x.h"
    #include "beaglebone.h"

    static void hardware_init();
    static void timer_init();
    static void timer_config(unsigned long, unsigned long);
    static void isr_timer2();

    int main(void) {
    // Set up hardware and peripherals.
    hardware_init();

    // Configure timer settings
    timer_config(0xF0000000u, 0xF0000000u);
    timer_init();


    // XXX: Turn on LED
    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);

    // Enable timer interrupt
    DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

    // Turn on actual timer
    DMTimerEnable(SOC_DMTIMER_2_REGS);

    asm(" mrs r0, CPSR");
    asm(" bic r0, r0, #0x80");
    asm(" msr CPSR, r0");

    // Loop forever- all work takes place in ISRs.
    while(1);
    }


    static void hardware_init() {
    // Configure GPIO/LED
    GPIO1ModuleClkConfig();
    GPIO1Pin23PinMuxSetup();
    GPIOModuleEnable(SOC_GPIO_1_REGS);
    GPIOModuleReset(SOC_GPIO_1_REGS);

    /* Set GPIO 1.23 as output */
    GPIODirModeSet(SOC_GPIO_1_REGS, (23), GPIO_DIR_OUTPUT);
    }

    static void timer_init() {
    // Set up the configuration for the hardware timer.

    /* Enable clocks for DMTimer2 */
    DMTimer2ModuleClkConfig();

    /* Initialize ARM interrupt controller (AINTC) */
    IntAINTCInit();

    /* Register our ISR to DMTimer2's interrupt. */
    IntRegister(SYS_INT_TINT2, isr_timer2);

    /* Set the DMTimer2's interrupt priority to 0. */
    IntPrioritySet(SYS_INT_TINT2, 0, AINTC_HOSTINT_ROUTE_IRQ);

    /* Enable the DMTimer2 interrupt. */
    IntSystemEnable(SYS_INT_TINT2);

    /* Enable IRQ in CPSR (ARM program status register) */
    // IntMasterIRQEnable();

    }

    static void timer_config(unsigned long initial, unsigned long reload) {
    // Configure timer
    // Note that instead of doing a count from 0 to some compare value, we are
    // preloading the timer with a given value and watching for it to overflow,
    // which is functionally identical.

    /* Configure the timer mode. */
    // Modes: autoreload (selected) versus one-shot mode. Does the timer automatically reset itself?
    // compare versus overflow (selected) mode. Does the timer ISR trip on equality to a value, or on overflow?
    DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);

    /* Load initial counter value into timer. */
    DMTimerCounterSet(SOC_DMTIMER_2_REGS, initial);

    /* Load reload counter value into timer, the value the timer gets every time it is reset. */
    DMTimerReloadSet(SOC_DMTIMER_2_REGS, reload);
    }

    // Interrupt vector for BeagleBone timer
    static void isr_timer2() {
    static short int mode = 0;

    /* Disable the DMTimer interrupt */
    DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);

    /* Clear the interrupt flags (IF) status */
    DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG);

    /* *********** ISR TASKS BEGIN *********** */
    if (mode == 0) {
    // Turn on LED
    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_HIGH);
    mode = 1;
    } else {
    // Turn off LED
    GPIOPinWrite(SOC_GPIO_1_REGS, (23), GPIO_PIN_LOW);
    mode = 0;
    }
    /* *********** ISR TASKS END *********** */

    /* Re-enable the DMTimer interrupt */
    DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
    }

    4861.IRQ CPSR.doc

  • I reinvented the wheel that austin invented.

    My timer interrupt issue's solution is what Austin identified earlier. I excluded the AM335x.cmd from build and included the DMTIMER.cmd file. On doing this the timer and serial interrupts started working and everything was fine. I cant understand why this is so but it is not very logical.
  • So what are the differences between both .CMD files?
  • Hello Mariusz,
    I was searching for the solution to a problem, and came across this.

    As is typical for TI information, this is now useless. There is no "Run->Load Program" in CCS.
    And the "Run -> Load - > Load Program is disabled"

    How does one load a program, now that TI has chosen to disabled that ability in CCS? (version 6.2)

    -CSW