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.

MSP-EXP432E401Y: How to get time in a HWI thread?

Part Number: MSP-EXP432E401Y
Other Parts Discussed in Thread: SYSBIOS

A timer's callback function creates a thread:

Task_Params taskParams;

Task_Params_init(&taskParams);
taskParams.priority = TASK_PRIO_MEDIUM;
taskParams.stackSize = THREADSTACKSIZE;
Task_create(timer_run, &taskParams, NULL);

This thread calls clock_gettime and within this function Hwi_disable is called which leads to an exception:

void timer_run(UArg arg0, UArg arg1)
{
    struct timespec tm;
    struct tm *now;

    clock_gettime(CLOCK_REALTIME, &tm);
    
    ...
}

In other threads I can call clock_gettime without any problems but not in this case. I supposed this is because the thread has been created by a Hwi thread? This is not logical as the creator should have no impact on the new thread but at least I have no other explanation.

Any idea how I can resolve that problem and get CLOCK_REALTIME within that thread?

Thank you and regards
Peter

  • This thread calls clock_gettime and within this function Hwi_disable is called which leads to an exception:

    Hi,

      Do you mean Hwi_disable is called when clock_gettime is executed? You mentioned that in other threads you have no issue to call clock_gettime. For those working cases, aren't Hwi_disable also called the same way? I just wanted to make sense how would Hwi_disable have an effect in one way vs another. 

  • Hi Charles,

    Yes, Hwi_disable is always called by clock_gettime:
    clock_gettime calls Seconds_getTime which calls Seconds_SecondsProxy_getTime which at it first line of code has "key = Hwi_disable();".

    Hwi_disable is always called the same way. The only difference is the context. For testing, I have placed always the same code

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    at different locations of the application:

    1. main-function just before BIOS_start() -> OK
    2. A thread which is started by the main function with the below parameters -> OK
      taskParams.stackSize = THREADSTACKSIZE;
      taskParams.priority = TASK_PRIO_MEDIUM;
      t_net = Task_create(net_init, &taskParams, NULL);
    3. The callback function of a timer -> OK (this has surprised me)
    4. The thread which is dynamically created by the timer -> FAIL (ti_sysbios_family_arm_m3_Hwi_excHandlerAsm__I)

    Although other functions including semaphores and mailboxes work fine in that thread, it makes me believe that there is something wrong about that thread causing it to crash when Hwi_disable is being called.

    To explain the desired behavior: I need to run a function checking if there are any time-based rules to be executed every minute. As it is not a promising idea to run rule processing in an interrupt callback, I am using a separate thread for that. In addition, as in a theoretical worst-case processing could last longer than one minute, I have the time callback create a new thread on each call with the idea that the thread runs independently and then destroys itself when finished.

    The following snipped should give you the idea:

    int main(void)
    {
        Board_init();
        ti_ndk_config_Global_startupFxn();
        
        /* Calls creating other threads, mailboxes, and semaphores */
        
        // Create timer for event handling
        // CONFIG_TIMER_0 has been created in syscfg
        Timer_init();
        Timer_Handle timer0;
        Timer_Params timerParams;
        Timer_Params_init(&timerParams);
        timerParams.period = 30000000; // call each 30 seconds as 60 are too much for the uint32_t
        timerParams.periodUnits = Timer_PERIOD_US;
        timerParams.timerMode = Timer_CONTINUOUS_CALLBACK;
        timerParams.timerCallback = (Timer_CallBackFxn) timer_init;
        timer0 = Timer_open(CONFIG_TIMER_0, &timerParams);
        Timer_start(timer0);
        
        BIOS_start();
    
        return (0);
    }
    
    bool tcount = true;
    
    void timer_init(UArg arg)
    {
        // Skip every 2nd call (30->60 secs)
        if (tcount)
        {
            tcount = false;
            Task_Params taskParams;
    
            Task_Params_init(&taskParams);
            taskParams.priority = TASK_PRIO_MEDIUM;
            taskParams.stackSize = THREADSTACKSIZE;
            Task_create(timer_run, &taskParams, NULL);
        }
        else
        {
            tcount = true;
        }
    }
    
    void timer_run(UArg arg0, UArg arg1)
    {
        struct timespec tm;
        struct tm *now;
    
        // Get the current time as a time_t value
        clock_gettime(CLOCK_REALTIME, &tm); // CRASHES HERE: Hwi_disable(); -> ti_sysbios_family_arm_m3_Hwi_excHandlerAsm__I
        now = localtime(&tm.tv_sec);
        
        // Rule processing code
        
        Task_delete(NULL);
    }

    Any idea what I am doing wrong in the above code or what else may make the Hwi_disable call fail just and only in that function?

    Regards
    Peter

  • Hi Peter,

      What type of exception are you getting? What does the fault status register produce?

  • Hi,

      All I can tell is that the processor encountered a Imprecise Bus fault. Normally, this is when the processor tried to write to an protected address or an invalid address (e.g an unimplemented address). Reads are precise and therefore you can use the fault address register to know what address caused the fault. Writes if at fault are imprecise because of the internal write buffering. 

    Todd Mullanix presented some techniques to debug exception in this document. https://www.ti.com/content/dam/videos/external-videos/1/3816841626001/4910324181001.mp4/subassets/debugging-common-application-issues-ti-rtos-presentation-lab.pdf

    Here is another app note that provides some techniques to isolate the fault source. 

    https://www.ti.com/lit/pdf/spma043

  • OK, I got it: it actually was a Display_printf line in the timer-callback function and the system crashed at the Hwi_disable of the clock_gettime only by accident because at that moment ti.sysbios.knl.Tak.IdleTask went into the above exception. Removed the Display_printf line from the timer callback and everything works fine. I did not investigate any further why I cannot use that command in a timer callback but as it is working now, I will leave it there.

  • Glad that your problem is resolved. Good that you find the root cause as fat irst I didn't see Display_printf in your code snippet and even if I did, I may not have related Display_printf with your crash. However, if you were to follow the app note I referenced, you should be able to finally narrow down to Display_printf.