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.

Issues with DMTimer for AM335x SYS/BIOS Industrial SDK for ICE

Other Parts Discussed in Thread: SYSBIOS

Hello,

I am using the AM335x ICE with the Industrial SDK 1.0.0.2, with SYS/BIOS 6.33.00.19, on CCS 5.1.0.09000.  I am using the example EtherCAT project (ecat_appl).  Right now, I am trying to implement a timer that triggers every 250 microseconds.  Therefore, I am planning on using DMTimer3 for this purpose. I noticed that the ecat_appl example project is already using DMTimer2 for the system timer for SYS/BIOS.

I am trying to initialize DMTimer3 in main() in tiescappl.c, but I am having some difficulties with it. I am trying to implement the dmtimer by using the following StartweWare example applications for evmAM335x:  dmtimerCounter.c,  demoTimer.c, and demoMain.c.

In the StarterWare examples for the DMTimer, the ARM Interrupt Controller is always initialized by calling IntAINTCInit().  However, if I call this in main() in my application, it causes the interrupts for the DMTimer2 (SYS/BIOS system timer) to not be serviced. The program hangs, even though interrupts are enabled for DMTimer2 (it is configured by SYS/BIOS).  I have verified this by seeing that the INTC_PENDING_IRQ2 register (0x482000D8) has a value of 0x00000010, and the DMTimer2 IRQSTATUS register (0x48040028) has a value of 0x00000002, indicating that the IRQ is pending.  It seems that IntAINTCInit() is preventing the DMTimer2 ISQ from being serviced, even though IntAINTCInit() is called before any interrupt configuration or peripheral configuration for DMTimer2.

I have tried working around this issue by simply not calling IntAINTCInit().  This makes me nervous because IntAINTCInit() is always called in the dmtimer examples.  The issue I am experiencing now is that the HWI for DMTimer3 is not being being called, even though the interrupt IRQ for DMTimer3 is pending.  I have enabled the interrupt at the system level and the peripheral level, and have registered the ISR for DMTimer3, so I am not sure what is wrong. Here is the code I have for main() in tiescappl.c:

Void main()

{

DISABLE_ESC_INT()

// just to make sure we can't get early Ecat IRQs...

Task_Params taskParams;

Task_Params_init(&taskParams);

taskParams.

priority = 4;

tsk1 = Task_create (task1, &taskParams, NULL);

mmuInit();

// needed first

SetBoardType(AM335X_BOARD_TYPE_ICE );

//AM335X_BOARD_TYPE_ICE : AM335X_BOARD_TYPE_IDK

led_init();

PINMUX_Config();

timer2Init();

boardType = GetBoardType();

if(AM335X_BOARD_TYPE_IDK == boardType)

PowerPWM();

ICSS_Init();

PRUSSPinMux_Config(0x01);

// PRUSS pinmuxing

spiInit();

// C2000 communication for motor current reads

 

//---------------------!!! my code begins here !!!-----------------------------

/* This function will enable clocks for the DMTimer3 instance */

DMTimer3ModuleClkConfig();

/* Initialize the ARM Interrupt Controller */

// TODO: Note: Initializing the ARM Interrupt Controller should be done, according to examples, but for some reason it is causing issues with DMTimer2 for the SYS/BIOS system timer

//IntAINTCInit();

/* Registering ADC_Timer_ISR */

IntRegister(SYS_INT_TINT3, ADC_Timer_ISR);

/* Set the priority */

IntPrioritySet(SYS_INT_TINT3, 0, AINTC_HOSTINT_ROUTE_IRQ);

/* Enable the system interrupt */

IntSystemEnable(SYS_INT_TINT3);

/* Enable IRQ in CPSR */

IntMasterIRQEnable();

/* Configure the DMTimer for Auto-reload and no-compare mode */

DMTimerModeConfigure(SOC_DMTIMER_3_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);

/* Load the counter with the initial count value */

DMTimerCounterSet(SOC_DMTIMER_3_REGS, ADC_TIMER_INITIAL_COUNT);

/* Load the load register with the reload count value */

DMTimerReloadSet(SOC_DMTIMER_3_REGS, ADC_TIMER_RLD_COUNT);

/* Stop/Reset the DMTimer */

Stop_ADC_Timer();

/* This function will enable the interrupt for the DMTimer3 instance */

DMTimerIntEnable(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_EN_FLAG);

//----------------------------------------!!! my code ends here !!!-------------------------------------------------------

 

if( AM335X_BOARD_TYPE_ICE == boardType )

{

uartInstance = 5;

}

else if(AM335X_BOARD_TYPE_IDK == boardType)

{

uartInstance = 3;

}

UartOpen(uartInstance,NULL);

UARTPutString(uartInstance,"TI EtherCAT Demo Application Build - ");

UARTPutString(uartInstance,APPL_BUILD_VER);

//Disable PRUs - This is to ensure PRUs are not running when application is not initialized

PRUSSDRVPruDisable(0);

PRUSSDRVPruDisable(1);

BIOS_start();

}

 

I would like some help setting up DMTimer3 properly.

 

Thanks.

 

  • Hey,

    I`m not a expert in SYS/BIOS, but I could not find where you enable your HWI and connect it with DMTimer3.

    I think it should be sth like this:

    .....

     Timer = Timer_create(isr_hwi1, 1000, &timerParams, &eb);

    .......

  • Jonathan,

    generally I can't recommend to use Starterware INTC functions in combination with Sys/Bios without looking at the sources. Sys/Bios has it's own methods of treating interrupts and you shouldn't mix that without understanding the side effects. That is also why many of the (OS-agnostic) Starterware examples only have limited use for Sys/Bios projects.

    Regards.

  • I have tried calling a SYS/BIOS API function for creating a device-specific DMTimer for the AM335x.  The issue is that if I configure any registers for DMTimer3 before calling the Timer_create() function, SYS/BIOS hangs/aborts and complains that the timer is not available. So apparently I cannot touch the DMTimer3 registers before calling Timer_create().  However, if I remove all of my register-configuration functions based on the StarterWare, SYS/BIOS gives me a data abort because it couldn't access the timer registers to create the DMTimer.  So I at least need to enable the clock for the DMTimer3 peripheral by calling DMTimer3ModuleClkConfig(), which is a StarterWare function, since SYS/BIOS is unable to configre the DMTimer3 unless the clock is already enabled that peripheral.

    The issue now is that the DMTimer3 interrupt still does not appear to be enabled, since my ISR is never called, and if I check the INTC_MIR2 register (0x482000C4), I can see that the DMTimer3 interrupt (int num 69) is masked/disabled at the system/INTC level, while the DMTimer2 interrupt (int num 68) is unmasked/enabled: the value of the INTC_MIR2 register is 0xFFFFFFEF.  If DMTimer3 was also enabled, it would be 0xFFFFFFCF.  So SYS/BIOS is somehow not enabling the DMTimer3 interrupt for the INTC, even though I am calling the SYS/BIOS API functions for creating DMTimer3.

    Now my code in main() looks like this:

    Void main()

    {

    DISABLE_ESC_INT()

    // just to make sure we can't get early Ecat IRQs...

    Task_Params taskParams;

    Task_Params_init(&taskParams);

    taskParams.

    priority = 4;

    tsk1 = Task_create (task1, &taskParams, NULL);

    mmuInit();

    // needed first

    SetBoardType(AM335X_BOARD_TYPE_ICE );

    //AM335X_BOARD_TYPE_ICE : AM335X_BOARD_TYPE_IDK

    led_init();

    PINMUX_Config();

    timer2Init();

    boardType = GetBoardType();

    if(AM335X_BOARD_TYPE_IDK == boardType)

    PowerPWM();

    ICSS_Init();

    PRUSSPinMux_Config(0x01);

    // PRUSS pinmuxing

    spiInit();

    // C2000 communication for motor current reads

     

    //---------------------!!! my code begins here !!!-----------------------------

    /* This function will enable clocks for the DMTimer3 instance */

    DMTimer3ModuleClkConfig();

     

    /* Removed other StarterWare DMTimer3 configuration functions */

     

    // Create DMTimer3 with SYS/BIOS API calls

    Timer_Handle ADC_Timer;

    Timer_Params ADC_Timer_Params;

    Error_Block eb;

    Error_init(&eb);

    Timer_Params_init(&ADC_Timer_Params);

    ADC_Timer_Params.

    period = 500;

    ADC_Timer_Params.

    periodType = Timer_PeriodType_MICROSECS;

    ADC_Timer_Params.

    arg = 0;

    ADC_Timer_Params.

    startMode = Timer_StartMode_USER;

    ADC_Timer = Timer_create(1, ADC_Timer_ISR, &ADC_Timer_Params, &eb);

    if ((ADC_Timer == NULL) || (Error_check(&eb))) {

    System_abort(

    "Timer create failed");

    }

     

    //----------------------------------------!!! my code ends here !!!-------------------------------------------------------

     

    if( AM335X_BOARD_TYPE_ICE == boardType )

    {

    uartInstance = 5;

    }

    else if(AM335X_BOARD_TYPE_IDK == boardType)

    {

    uartInstance = 3;

    }

    UartOpen(uartInstance,NULL);

    UARTPutString(uartInstance,"TI EtherCAT Demo Application Build - ");

    UARTPutString(uartInstance,APPL_BUILD_VER);

    //Disable PRUs - This is to ensure PRUs are not running when application is not initialized

    PRUSSDRVPruDisable(0);

    PRUSSDRVPruDisable(1);

    BIOS_start();

    }

     

  • Do you call

    Timer_start(tADC_Timer);

    everywhere? I have had the same problem,  but this was a problem of the configuration. You should ask this in the SYS/BIOS forum. If you use a clock instead of a timer it should work.

  • Hi,

    I could use DMTimer3 in my application. Here's the code snippet that you can compare with your configuration and see if it works for you too.

    void timer_init(void)
    {

    Hwi_Params hwiParams;

    /* This function will enable clocks for the DMTimer3 instance */
    DMTimer3ModuleClkConfig();


    Hwi_Params_init(&hwiParams);
    hwiParams.arg = SYS_INT_TINT3;
    hwiParams.priority = 0;
    Hwi_create(SYS_INT_TINT3,(Hwi_FuncPtr)timer_isr, &hwiParams, NULL);

    /* Load the counter with the initial count value */
    DMTimerCounterSet(SOC_DMTIMER_3_REGS, TIMER_INITIAL_COUNT);

    /* Load the load register with the reload count value */
    DMTimerReloadSet(SOC_DMTIMER_3_REGS, TIMER_RLD_COUNT);

    /* Configure the DMTimer for Auto-reload and compare mode */
    DMTimerModeConfigure(SOC_DMTIMER_3_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);

    Hwi_enableInterrupt(SYS_INT_TINT3);

    DMTimerIntEnable(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_EN_FLAG);
    DMTimerEnable(SOC_DMTIMER_3_REGS);

    }

    Regards,

    Amit

  • Hi Amit,

    this does not work in my code. I got an exception and the system is aborted.Your timer is not configured in compare mode like described in the comment.

    I dont know what is going wrong, but why do you use a hwi and not a timer?

    Thanks.

  • Hi Michael,

    What exception did you get and from where? Is it when you try to access DMTimer3 register (SOC_DMTIMER_3_REGS), if yes, then you might have to add this entry in mmuInit() function in sys_mmu.c driver and rebuild the sys_bios_driver.lib

    Yeah, it is actually configured for no-compare mode. 

    I am creating hardware interrupt for timer and associating a timer_isr with it.

    I was actually able use the DMTimer3 for getting timer tick of 1ms, so it gives interrupt every 1ms.

    Regards,

    Amit

  • The Console output is this:

    [CortxA8] in handle: 0x0.
    Main stack base: 0x800148e0.
    Main stack size: 0x2000.
    R0 = 0x800108b8  R8  = 0xffffffff
    R1 = 0x44e00000  R9  = 0xffffffff
    R2 = 0x00000002  R10 = 0xffffffff
    R3 = 0x80016824  R11 = 0xffffffff
    R4 = 0x00000001  R12 = 0x800148d4
    R5 = 0x8002326c [CortxA8]  SP(R13) = 0x80016880
    R6 = 0x2000011f  LR(R14) = 0x800032e8
    R7 = 0xffffffff  PC(R15) = 0x80001fb2
    PSR = 0x2000019f
    ti.sysbios.family.arm.exc.Exception: line 174: E_dataAbort: pc = 0x80001fb2, lr = 0x800[CortxA8] 032e8.
    xdc.runtime.Error.raise: terminating execution

    in sys_mmu.c is a line

    Mmu_setFirstLevelDesc((Ptr)0x48000000, (Ptr)0x48000000 , &attrs);  // Timer

    must I add 

    Mmu_setFirstLevelDesc((Ptr)0x48042000, (Ptr)0x48042000, &attrs); 

    for DMTimer 3?

  • Can you put a break point in the beginning of this timer_init function and do single stepping to see if it is throwing exception on any of timer related function calls? Or else, you can add these PC, SP and LR values in the core register PC, SP and LR values resp. It should give you the call stack and the point of failure.

    If we know what is causing this exception then we can handle it.

  • Michael Rinker said:

    must I add 

    Mmu_setFirstLevelDesc((Ptr)0x48042000, (Ptr)0x48042000, &attrs); 

    No, the first level MMU pages are 1 MB in size and L4 range includes the DM3Timer regs. But is this block enabled (clocked)? Check this using Memory view. If you can access the regs manually then it is fine and you have another issue. Then check the code what it is doing at that point.

    Regards.

  • Ok. Thank you, I have forgotten to call mmuInit(). Now the isr is working. How could I configure the 1ms? with the reload values?

  • I think if DMTimer3 is getting clock from CLK_M_OSC = 24MHz  and no prescaler is set (default staterware setting) then you have to give count and reload count as (0xFFFFFFFF- 24000) because it is an upcounter.

    You can check this and see if it gives you 1ms tick.

  • Ok. I will check and try it. With DMTimer2 it should be even able to do this.