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.

BEAGLEBK: DMTimer Example using Starterware - NOT WORKING!!! - BeagleBone Black + TIRTOS V6

Part Number: BEAGLEBK

Hi,

I am trying to use the example code for DMTimer to initialize the timer in interrupt mode. It is not working, I am not able to generate the interrupt and not hitting the break point inside the callback function. Please review the code and help me solve the issue.

static volatile uint32_t gDmtimerIsrFlag = 0;
 
/** \brief Application default configuration */
static const dmtimerAppCdt_t DMTIMER_APPCDT_DEFAULT =
{
    10U,                         /* cntValue */
    {
        (uint32_t)DMTIMER_MODE_CFG_AUTORLD_CMP_DISABLE,/* configMode */        
        0xFF000000U,            /* timerInitialCount */
        0xFF000000U,            /* timerReloadCount */        
        0x0U,                   /* isClockPrescalerEnabled */       
        0x0U,                   /* ClockPrescalerRatio */
        INTC_TRIG_HIGH_LEVEL,   /* trigType */              
        100U,                   /* intrLine */        
        1U,                     /* intrEnable */       
        (uint32_t)DMTIMER_INTR_MASK_OVF, /*intrFlag  */
        NULL,                   /* pFnIntrHandler */
        NULL,                   /* pUserParam */
        2U,                     /* instNum */
        (uint32_t)NULL          /* instAddr */               
    }
};

void Timer_App()
{
    int32_t status = S_PASS;
    /* Initialize the global object with Countdown timer application. */
    gDmtimerCdtApp = DMTIMER_APPCDT_DEFAULT;
    /* Enable cache memory and MMU */
    /*MMUConfigAndEnable();
    CACHEEnable(CACHE_IDCACHE, CACHE_INNER_OUTER);*/

   // status = BOARDInit(NULL);

    /* Initialize the UART console */
   /* CONSOLEUtilsInit();
     Select the console type based on compile time check
    CONSOLEUtilsSetType(CONSOLE_UTILS_TYPE_UART);
    
    DEBUG_MSG("\n StarterWare DMTIMER - Countdown timer Application!!\n");
    DEBUG_MSG("BOARDInit status [0x%x]\n", status);*/
    
    /* Print SOC & Board Information. */
 //   SOCPrintInfo();
  //  BOARDPrintInfo();

    /* Perform initialization of Interrupt controller*/
    status = INTCInit(FALSE);
   
    if (S_PASS == status)
    {      
       /*Find the instance on which to run this application or else dmtimer 
         instance 2 will be used as default. */
        status = DmtimerAppGetInstNum(&gDmtimerCdtApp);
        if (S_PASS == status)
        {
            /* Get SoC info -instance base address and interrupt line number*/
            status = DmtimerAppGetSocInfo(&gDmtimerCdtApp);
            if (S_PASS == status)
            {
                /* Initialise the application parameters */
                DMTIMERAppCountdownTimerInit(&gDmtimerCdtApp);  
                /* Countdown timer use case with count down from 10 to 0 */
                DMTIMERAppCountdownTimerRun(&gDmtimerCdtApp);
    
                DEBUG_MSG("\n Application Complete \n",__LINE__, __FILE__);
            }
            else
            {
                DEBUG_MSG("\n Application not supported in this SOC - \
                exiting app! \n",__LINE__, __FILE__);
            }    
        }
        else
        {
            DEBUG_MSG("\n This example is not supported on this SOC as\
            no dmtimer instance could be found to support this example\
            - exiting app! \n",__LINE__, __FILE__);
        }
    }
    else
    {
        DEBUG_MSG("Interrupt configuration failed - exiting app!\n",__LINE__, __FILE__);
    }    
    while (1); 
}

/*
* DMTimer interrupt service routine. This ISR sets the shared variable on 
* hitting an overflow interrupt - this is not a generic ISR
*/
void DmtimerAppCountdownIsr(uint32_t intrId, uint32_t cpuId, void* pUserParam)
{
    dmtimerAppCdt_t *pCountdownTimerObj = 
                                (dmtimerAppCdt_t *)pUserParam; 
    /* Disable the DMTimer interrupts */
    DMTimerIntDisable(pCountdownTimerObj->dmtimerObj.instAddr,
        DMTIMER_INTR_MASK_OVF);

    /* Clear the status of the interrupt flags */         
    DMTimerIntStatusClear(pCountdownTimerObj->dmtimerObj.instAddr,
                                        DMTIMER_INTR_MASK_OVF);
    gDmtimerIsrFlag = 1U;

    /* Enable the DMTimer interrupts */
    DMTimerIntEnable(pCountdownTimerObj->dmtimerObj.instAddr,
                                            DMTIMER_INTR_MASK_OVF);                                          
}
void DMTIMERAppCountdownTimerInit(dmtimerAppCdt_t *pCountdownTimerObj)
{
    /*initialize the object ISR function pointer  with application ISR*/
    pCountdownTimerObj->dmtimerObj.pFnIntrHandler = &(DmtimerAppCountdownIsr); 
    /*initialise the ISR user param with address of Countdown timer object */
    pCountdownTimerObj->dmtimerObj.pUserParam = (void*)pCountdownTimerObj; 
    
    /* call the peripheral config API */
    DMTIMERAppInit((dmtimerAppCfg_t*)&(pCountdownTimerObj->dmtimerObj));   
}

void DMTIMERAppCountdownTimerRun(dmtimerAppCdt_t *pCountdownTimerObj)
{
  //  DEBUG_MSG("\n  DMTIMER DOWN COUNTER: ",__LINE__, __FILE__);
    /* Start the DMTimer */
    DMTIMEREnable(pCountdownTimerObj->dmtimerObj.instAddr, TRUE);

    while(pCountdownTimerObj->cntValue)
    {
        if(gDmtimerIsrFlag == 1)
        {
        //    DEBUG_MSG("\b%d",(pCountdownTimerObj->cntValue - 1),__LINE__, __FILE__);
            pCountdownTimerObj->cntValue--;
            gDmtimerIsrFlag = 0U;
        }
    }
}

The instance number is changing from 2 to 7. I have added the peripheral MMU in my main.cfg  file for both DMTimer2 and DMTimer7 as follows:

/* DMTimer Base addresses*/
var peripheralBaseAddr = 0x4804A000;

/* Configure the corresponding MMU page descriptor accordingly */
Mmu.setFirstLevelDescMeta(peripheralBaseAddr,
                          peripheralBaseAddr,
                          peripheralAttrs);           
                          
var peripheralBaseAddr = 0x48040000;

/* Configure the corresponding MMU page descriptor accordingly */
Mmu.setFirstLevelDescMeta(peripheralBaseAddr,
                          peripheralBaseAddr,
                          peripheralAttrs);    

Please help I have been struggling to make this example project work since last 3 days.

Thank you,
Arshiya Tabassum
  • Hi Arshiya ,

    The Starterware DMTimer example works for me OOB.

    I build the example as follows:

    • debug: gmake -s dmtimer_app_cdt PLATFORM=am335x-evm PROFILE=debug KW_BUILD=no
    • release: gmake -s dmtimer_app_cdt PLATFORM=am335x-evm PROFILE=release KW_BUILD=no

    The resulting binaries are located in R:\<PDK>\packages\ti\starterware\binary\dmtimer_app_cdt\bin\am335x-evm\gcc

    How does your program fail?

    The Starterware DMTimer example isn't RTOS based. It appears you're attempting to integrate the DMTimer example into an RTOS-based application. 

    RTOS doesn't enable the clocks to DMTimer7 by default, so you'll need to handle this.

    This should be handled in the GEL file or SBL.

    Please see this thread on this topic: https://e2e.ti.com/support/processors/f/791/t/657370?RTOS-PROCESSOR-SDK-AM335X-Timers-crash-on-Initialization

    Regards,
    Frank

  • Hi Frank,

    I appreciate your quick repsonse. Thank you for providing the similar thread reference. 

    Just a quick recap of my problem:

    I am trying to build the DMTimer example on BeagleBone Black provided in the starterware folder of TI RTOS V6: "processor_sdk_rtos_am335x_6_03_00_106"

    If you remember, we had a correspondence regarding the usage of ePWM from starterware. You told me I need to account for the board related changes for building the example in RTOS. I was able to successfully use ePWM on my RTOS.

    Link to ePWM thread: https://e2e.ti.com/support/processors/f/791/p/926586/3456232#3456232

    I assumed for DMTimer as well, I can follow the same steps I did for ePWM example and it would work for me since it is starterware as well. 

    So, I followed the steps, I am able to build the example in CCS but my problem is with the interrupt. I am not able to see the interrupt being generated and not going inside the callback. 

    Following your suggestion, I added the timer clock for all the Timers (0 to 7) in the GEL file. But still its not generating a callback.

    Is there anything else apart from adding the DMTimer clocks in GEL file I need to do to make this example work given that I am able to step through each API correctly?

    I look forward to your response.

    Thank you,

    Arshiya Tabassum

  • Hi Arshiya,

    Starterware is bare metal and doesn't use RTOS. In general, the Starterware examples are bare metal and don't use RTOS.

    ePWM

    The Starterware ePWM example doesn't work OOB on BBB, but it should be possible to update this code for BBB. This example is bare metal and doesn't use RTOS.

    RTOS doesn't provide support for ePWM, but ePWM Starterware code can be ported into an RTOS application. The general procedure is documented in <PDK>\packages\ti\starterware\examples\dcan\readme.txt.

    DMTimer

    The Starterware DMTimer example works OOB on BBB. This example is bare metal and doesn't use RTOS.

    RTOS provides support for DMTimers 2-7, please see:

    • <BIOS>/docs/cdoc/ti/sysbios/timers/dmtimer/Timer.html
    • <BIOS>/docs/cdoc/ti/sysbios/timers/dmtimer/doc-files/TimerTables.html

    Instead of porting Starterware DMTimer code into an RTOS application, I recommend using RTOS API functions.

    The GEL file should handle the DMTimer PRCM. You can adjust the the values written to CLKSEL_TIMERx_CLK in the GEL file to select the clock source for DMTimer x (please see the TRM, Figure 8-21. Timer Clock Selection). You can also adjust the clock selection at run-time at the start of your application by writing directly to the CLKSEL_TIMERx_CLK register.

    This is an example of using the RTOS Timer APIs.

    .cfg file:

    var Timer = xdc.useModule('ti.sysbios.timers.dmtimer.Timer')
    
    

    .c file:

                        #include <ti/sysbios/hal/Timer.h>
    
                        Int main()
                            Timer_Params timerParams;
                            Error_Block eb;
    
                            Error_init(&eb);
                            
                            Timer_Params_init(&timerParams);
                            timerParams.extFreq.hi = 0;
                            timerParams.extFreq.lo = 24000000; // BBB xtal freq
                            timerParams.period = 1000;
                            timerParams.periodType = Timer_PeriodType_MICROSECS;
                            timerParams.arg = (UArg)p;
                            timerParams.startMode = Timer_StartMode_USER;
                            timerParams.runMode = Timer_RunMode_CONTINUOUS;
                            
                            // See <BIOS>/docs/cdoc/ti/sysbios/timers/dmtimer/doc-files/TimerTables.html for SYS/BIOS Timer IDs
                            //  Timer ID 1 is DMTimer 3
                            //  Timer ID 2 is DMTimer 4
                            //  ...
                            //  Timer ID 5 is DMTimer 7
                            hTimer = Timer_create(1, &timerISR, &timerParams, &eb);
    
                            Timer_start(hTimer);
    
                            BIOS_start();
    
                        /* ISR */
                        Void timerISR(UArg p)
                        {
                            timerIsrCnt++;
                        }
    

    Regards,
    Frank

  • Hi Frank,

    Thank you for your response and providing the detailed breakdown of timer API usage. I appreciate it!

    The only reason I was following the starterware example of DMTimer was because I wanted to see how to use the Interrupt Controller (AINTC) for generating interrupts for ePWM.

    Can you please if possible explain, how to generate interrupts on ePWM ?

    So far, I have followed the steps as below as directed in AM335x TRM section 15.2.2.2 

    1. Disable global interrupts - INTCDisableIntr()

    2. Disable ePWM interrupts - EPWMEtIntrDisable()

    3. Initialize peripheral registers - Followed ePWM example and initialized all necessary registers

    4. Clear any spurious ePWM flags - EPWMEtIntrClear()

    5. Enable ePWM interrupts - EPWMEtIntrEnable()

    6. Enable global interrupts - INTCEnableIntr()

    And, last but not the least, I have enabled the Event Trigger module of ePWM and configured the source as TBCNT=TBPRD event.

    I am using the API EPWMEtIntrStatus() to check the status and see that no interrupt is generated. 

    Please guide me to see what else I am missing to successfully generate interrupt on my ePWM. 

    Thank you,

    Arshiya Tabassum

  • Hi Arshiya,

    For ePWM I see you still have an open thread here: https://e2e.ti.com/support/processors/f/791/t/926586

    Can you please post this ePWM query on there? I'll respond by Thu. Thanks for your patience.

    It seems you're OK with DMTimer, so I'll close this thread.

    Regards,
    Frank