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.

Hwi Interrupt on Sitara AM3359 (TMDXICE3359)

Other Parts Discussed in Thread: AM3359, SYSBIOS

Hi!

I am trying to use the interrupt on a Sitara AM3359 chip. To do so, I am configuring my interrupt options coming from a timer. Since I cannot use the interrupt functions of Starterware, I am using the Hwi functions. Here is the code (in red is what is related to interrupt stuff):

Void taskFxn(UArg a0, UArg a1)
{
    char t_str[32];
    // Enable DMTimer3
                /* This function will enable clocks for the DMTimer3 instance */
                DMTimer3ModuleClkConfig();
                /* 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);
                DMTimerIntEnable(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_EN_FLAG);
                DMTimerEnable(SOC_DMTIMER_3_REGS);

    while(1)
    {
        Task_sleep(250);
        UARTPutString(uartInstance,t_str);
    }

}
Void main()

{
    Hwi_Params hwiParams;

    Task_Handle task;
    Error_Block eb;

    System_printf("enter main() \n");

    // Initialize memory
    mmuInit(applMmuEntries);

    // Pin muxing
    AM335X_INDCOMM_MUX iceMux[] = {
        // SPI1 pinmux
        { 0x0994 , 3 , AM335X_PIN_OUTPUT },    //    spi1_d0_mux2/SIMO    mcasp0_fsx
        { 0x0998 , 3 , AM335X_PIN_INPUT_PULLUP },    //    spi1_d1_mux2/SOMI    mcasp0_axr0
        { 0x0990 , 3 , AM335X_PIN_OUTPUT | AM335X_PIN_INPUT_PULLDOWN },    //    spi1_sclk_mux2/CLK    mcasp0_aclkx . IMPORTATN: You need to enable both, input and output. Input clock is feed back into the RX logic of SPI.
        { 0x099c , 7 , AM335X_PIN_OUTPUT },    //    spi1_cs0_mux4: HVS SPI1 CS in GPIO mode
        { 0x09A0 , 7 , AM335X_PIN_OUTPUT },    //    gpio3[18]    mcasp0_aclkr -> INDUS_LDn
        {0xFFFFFFFF,0,0}
    };
    PINMUX_Config(iceMux);

    // Enable Outputs Leds
    led_init();
    // Enable Industrial Inputs
    spiInit();


    Error_init(&eb);
    task = Task_create(taskFxn, NULL, &eb);
    if (task == NULL) {
        System_printf("Task_create() failed!\n");
        BIOS_exit(0);
    }

    Hwi_Params_init(&hwiParams);
    hwiParams.arg = SYS_INT_TINT3;
    hwiParams.priority = 0;
    hwiParams.enableInt = FALSE;
    Hwi_create(SYS_INT_TINT3, DMTimerIsr, &hwiParams, NULL);
    Hwi_enableInterrupt(SYS_INT_TINT3);

    UartOpen(uartInstance, NULL);

    BIOS_start();     /* enable interrupts and start SYS/BIOS */
}
Void DMTimerIsr(UArg arg)
{
    /* Disable the DMTimer interrupts */
    DMTimerIntDisable(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_EN_FLAG);

    /* Clear the status of the interrupt flags */
    DMTimerIntStatusClear(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_IT_FLAG);

    UARTPutString(uartInstance,"We are in DMTimerIsr!\n");

    /* Enable the DMTimer interrupts */
    DMTimerIntEnable(SOC_DMTIMER_3_REGS, DMTIMER_INT_OVF_EN_FLAG);
}

The timer is working great. I can see it incrementing. And when the timer overflows, the program is stuck somewhere wrong, it is not is the main() neither in the DMTimerIsr().

Would you guys have an idea of what's wrong with my code ?

Thanks,
Have a nice week-end,
Paul

PS:
am335x_sysbios_ind_sdk_1.0.0.8
bios_6_35_00_20
xdctools_3_24_06_63

  • Anyone? Thanks,
    Paul

  • Paul,

    To clarify… you look at the timer registers and see the timer is counting, but on the *first* interrupt the program goes somewhere unexpected?  

    If so, I’m wondering if maybe the wrong interrupt ID is used, and another interrupt handler is triggering instead.  Can you set a breakpoint on the symbol “ti_sysbios_family_arm_a8_intcps_Hwi_nonPluggedHwiHandler__I” and see if the CPU breaks there? 

    If not there, is it maybe activating another configured interrupt handler?  If not that, can you try to determine where the CPU is "stuck"?

    Also, I’m wondering if you’ve looked at using a SYS/BIOS Timer instead of programming up the dmtimer explicitly?  (Different timing services are described in Chapter 5 of the SYS/BIOS User’s Guide.)  Unless you need something that the Timer module doesn’t provide, that should be easier to use because SYS/BIOS will automatically manage the underlying timer peripheral for you.

    Scott

  • Hi Scott,

    I don't know much about SYS/BIOS yet, i'll take a look about the SYS/BIOS Timer.

    Yes, you're right. I'm looking at the timer counter register, and the program is always crashing at the first overflow. I am definitely sure that the interrupt is the good one because when I comment the lines for activating the interrupt, nothing happens (counter reload and restart counting). I can see where the CPU breaks *every time* in the Disassembly:           ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm__I

    My guess is that it's not jumping to the right ISR address. If you can tell me more, I'm listening ! :D

    Thanks,

    Paul

  • Hi Paul,

    There is a description of backtracking from an exception here: http://processors.wiki.ti.com/index.php/SYS/BIOS_FAQs#4_Exception_Dump_Decoding_Using_the_CCS_Register_View

    If you don’t see exception output to the CCS console, you can see the register values in the exception tab for the Hwi module, in ROV. 

    If you set the corresponding PC, SP, and LR register values, where does the call stack indicate the exception occurred?

    Thanks,
    Scott

  • Hello Scott,

    I have tried what you suggest me to do but I have trouble. First, I cannot see any exception output to the CCS console. In fact my program is looping between two addresses which are (when I press F5 in the assembly tab) :

              ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm__I:
    8000c478:   800069DC LDRHID          R6, [R0], -R12
    [...]
    80019410:   E59FF018 LDR             PC, 0x80019430

    And when I go to the ROV tab once the Timer has ended counting, the Hwi part, I have a problem, I have an error:

    Received exception from ROV server:
    Target memory read failed at adress: 0x6162206b, length: 8
    This read is an INVALID address according to the application's section map. The application is likely either uninitialized os corrupt.

    I don't have that error is I pause the program before the interruption happens.

    Therefore I am pretty lost to do what you suggested. If you have any other idea, Don't hesitate for sharing!

    Thanks again,
    Paul

  • Hi guys,

    I finally succeed to make the interrupts working well by setting it up statically in the *.cfg file. Here are the lines I added:

    var ti_sysbios_family_arm_a8_intcps_Hwi = xdc.useModule('ti.sysbios.family.arm.a8.intcps.Hwi');
    var ti_sysbios_family_arm_a8_intcps_Hwi0Params = new ti_sysbios_family_arm_a8_intcps_Hwi.Params();
    ti_sysbios_family_arm_a8_intcps_Hwi0Params.instance.name = "ti_sysbios_family_arm_a8_intcps_Hwi0_TEST";
    ti_sysbios_family_arm_a8_intcps_Hwi0Params.priority = 2;
    Program.global.ti_sysbios_family_arm_a8_intcps_Hwi0_TEST = ti_sysbios_family_arm_a8_intcps_Hwi.create(69, "&DMTimerIsr", ti_sysbios_family_arm_a8_intcps_Hwi0Params);

    So, can you tell me what is the code to use in C to be able to configure interrupt in the same way ? To remind you, that's what I tried unsuccessfully:

    #include <ti/sysbios/family/arm/a8/intcps/Hwi.h>
       
    Hwi_Handle hwiDMTimer3;

        Hwi_Params hwiParams;
        Hwi_Params_init(&hwiParams);
        hwiParams.eventId = 69;
        hwiParams.priority = 0;
        hwiDMTimer3 = Hwi_create(69, DMTimerIsr, &hwiParams, &eb);
        if (hwiDMTimer3 == NULL) {
            System_printf("Hwi_create() failed!\n");
            BIOS_exit(0);
        }

    Thanks,
    Paul

  • While checking what was different between the two way of doing, I noticed the priority parameter was not the same. Apparently, I cannot use priority level 0, instead of what is written everywhere in the Sitara TRM.

    Thanks for your time ;)

    Cheers,
    Paul

  • Paul,

    Sorry for the delay in responding.  

    On an A8 there should be nothing special about using interrupt priority of zero, other than it will be the highest priority interrupt.  

    I asked around about this, and one suggestion was that the UARTPutString() call - if it is waiting to push all characters out the UART - may take too long such that another timer interrupt is immediately pending and ready to be serviced after this interrupt, causing continuous interrupt processing.  Another thought is that since this interrupt has the highest priority, if it preempts another UART function call, and causes reentry, then maybe that is a problem for the UART functions?

    Can you try commenting out that UARTPutString() call when using interrupt priority of zero, and see if there is still a problem?

    Also, can you confirm that using a priority of “2” in the dynamic creation case indeed works? 

    And that using a priority of “0” in the static creation case fails too?

    Thanks,
    Scott

  • Hi Scott,

    I have commented every part of my program referring to UART, then tried what you asked for.

    I have the exact same behavior if dynamically configured or static configured.

    I can use priority starting at 1. In any case, while putting priority 0, it's crashing. I got that exception:
    ti.sysbios.family.arm.exc.Exception: line 176: E_dataAbort: pc = 0x800072b0, lr = 0x80007168.
    xdc.runtime.Error.raise: terminating execution

    I see only one difference I can notice between with and without the UART:
     [*] With: program is stuck in some Assembly code as I already explained before.
     [*] Without: program is crashing and I got the exception hereabove.

    Paul