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.

MCU-PLUS-SDK-AM243X: usage of 1ms-module of the Am243X timer-module

Part Number: MCU-PLUS-SDK-AM243X
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello,

In advance: we do not use SysCfg. We have our own driver-wrapper and we directly use the TimerP-API for that and set the clock-source to the timer-clocksrcMux-address directly.
This will be used for our internal time as well the same way SysCfg would do that. 

currently I am trying to utilize the TimerP to get a 1 ms-tick.

With the standard-setting of a clock-source MCU_HF0SC0 we have 25 MHz. if we now input to timerP to have a 1 ms intervall with this clock-rate it isn't really 1 ms at all. We also tried to use the 1-ms-tick-module which is advertised in the TRM. it simply states "Generates a 1-ms tick clock when functional clock is 32.768 kHz". SysCfg does not set the clock to 32.768 Hz, but to 32000 Hz, when the MCU_HFOSC0_CLKOUT_32K gets selected.

We utilized HWTimer 5 for that.

To verify the 1 ms-tick of the timer I just did some manual noting. We output the system-timestamp via the console from a task that sleeps for 5 seconds. It just reads the HWTimer-value. In my understanding any sw shouldn't impact the HW-Timer since it's free-running, generating an interrupt in 1 ms intervall.

the timestamp-variable which gets updated with every interrupt is an 64-bit integer, a unix timestamp in ms-resolution.

So here are the measurings I made:

As you can see in a short amount of time the general time and the time in the device deviate much in the seconds range already! This is not useable for us. We need a way more exact 1ms-tick. 

Also to me it seems the TimerP does not support the 1 ms-tick-module of the Sitara-timers, since the TRM states much more configuration than I can see in the TimerP-implementation.

If we check the registers:

And check the settings of them from the TRM:

They are not the same.

So will this functionality be implemented? This is really really important for us and our devices. We need an exact timestamp, even solely for security reasons. We additionally have an NTP-synchronisation but those drift-times are way too big!

Additions: I also saw the clocktree-tool for Am64 does not support all possible clock-inputs for the timer-module:

Best regards

Felix

  • Hello Felix,

    I am going to raise this exception and request to the dev team. I will check as to when a timer example can be put out as a part of MCU PLUS SDK Examples.

    But before I do this, can you give me a sample code to test this out?

    Regards,

    Vaibhav

  • Hey Vaibhav,

    sorry for the delay. So unfortunately we are not using the SDK in a raw way and we have your own HAL and driver-encapsulation and we also do not use SysConfig but a modified SDK-API which takes the configs directly instead of an array-index.

    Also we have a whole framework, so it's not easy to share an example.

    But in fact it's just a HW-timer created via TimerP set to 1 ms-intervall with its callback incremented a 64-bit-variable and another task which prints out the value formatted and converted into the iso-data representation every 5 seconds via the CCS-console.

    after thinking through it multiple times, I have a bad guess: could it be that the console-log blocks ALL interrupts inside the Sitara? Because we know the Console-log can slow down things dramatically but we normaly thought that only the freeRTOS is affected. If it also blocks all interrupts while printing, this could even be the reason why the timer-value is not increased an thus I would need to log it only in memory.

    Is this valid? because then it's not a problem of the timers.

    Anyway the 1ms-tick-module does not seem to be working properly with the current TimerP-Implementation, according to the TRM.

    best regards

    Felix

  • Hello Felix, 

    I got your point of you using a different approach for development.

    If not an example, can you share a pseudocode in plain english, preferably in points.

    I can read through the points and ask follow up questions/reproduce this issue.

    Regards,

    Vaibhav

  • Hey Vaibhav, sorry for the late reply.

    but of course I can try to write it down in pseude-code but a bit more complex, since we do initialize all without SysCfg:

    - HW timer 5 is used, baseAddr is 0x02450000, we set clkSrcMuxAddr to 0x430081C4, irqNumber is 157, clockSrc_is MCU_HF0SC0 (0)

    -

        SOC_controlModuleUnlockMMR(SOC_DOMAIN_ID_MAIN, 2);
        *(volatile uint32_t*)AddrTranslateP_getLocalAddr(clockSrcMuxAddr) = static_cast<uint8_t>(clockSrc_);
        SOC_controlModuleLockMMR(SOC_DOMAIN_ID_MAIN, 2);

    - TimerP is created:

        TimerP_Params_init(&timerParams);
        timerParams.inputPreScaler = 1;
        timerParams.inputClkHz     = 25000000;
        timerParams.periodInNsec   = 1000000;
        timerParams.oneshotMode    = 0;
        timerParams.enableOverflowInt = 1;
        timerParams.enableDmaTrigger  = 0;
        TimerP_setup(hwTimerBaseAddr_, &timerParams);
    
        HwiP_Params timerHwiParams;
        HwiP_Params_init(&timerHwiParams);
        timerHwiParams.intNum = irqNumber_;
        timerHwiParams.callback = &timerCbStatic; // this callback is routed later to a callback registered at a later stage
        timerHwiParams.args = this;
        timerHwiParams.isPulse = 0;
        timerHwiParams.priority = interruptPriority_;
        HwiP_construct(&hwiObject_, &timerHwiParams);

    - timeHandler:

    class TimeHandler
    {
        TimeHandler(HWTimer* timer) : timer_(timer)
        {
            timer_->registerCallback(timerCB) // registers callback for the timer
        }
        
        void timerCB()
        {
            timeInMs_++;
        }
        
        int64_t get()
        {
            return timeInMs_;
        }
        
        Timer timer_;
        int64_t timeInMs_;
    }

    - logging-task:

    taskLoop()
    {
        sleepMs(5000) // sleep 5 seconds
        time = systemtime->get()
        convertedIsoTime = convertToIso(time)
        DebugP_log("%i-%i-%iT%i:%i:%i.%iZ", convertedIsoTime.year, 
        convertedIsoTime.month, convertedIsoTime.day, convertedIsoTime.hour, 
        convertedIsoTime.minute, convertedIsoTime.second, convertedIsoTime.millisecond)
    }

    I hope this shows the flow.

    So not sure if the DebugP_Log and thus it's inside called puts-function can cause a lockup of the HW-interrupts and thus never incrementing the variable when printing.

    For the 1ms-tick-module of the Timer I would set the timerParams.inputClkHz to 32000 (as SysCfg) or the 32768 (as suggested in the TRM) and the clockSrc would be 1. But the code in TimerP doesn't seem to differentiate here to enable the 1 ms-module.

  • after thinking through it multiple times, I have a bad guess: could it be that the console-log blocks ALL interrupts inside the Sitara? Because we know the Console-log can slow down things dramatically but we normaly thought that only the freeRTOS is affected.

    When you refer to the "console-log" are you referring to the Console view in CCS? Can you detail what you mean it slowing things down and its relation with freeRTOS? 

    Also what transport is DebugP_Log using to output messages? Is it C/IO over JTAG or something else?

    Sorry for the basic questions as my expertise is on the tools and not the device/SDK.

  • Hey Ki, sorry for the late reply.

    Yes I mean the CIO-console via JTAG, this is also used in our case for the DebugP_log-output.

    we noticed that when using the console-log it seemed like all freeRTOS-tasks have stopped working (which could also be because of blocked interrupts). In general you can say that the time of issuing a log in the device until it is printed in the console is delaying everything in the system.

    But I didn't hink of it blocking all interrupts, because normaly the debug configuration suggests this is configurable. e.g. you can lock interrupts when assembly-debug-stepping etc.

  • Standard C I/O over JTAG can certainly add overheard in both performance and code size. Note that C I/O also relies on breakpoints (which is used under the hood) to send the data over JTAG. This can certainly have considerable real-time impact.

  • ok I see, so a memory-logging would be way more reliable here.

    But to understand it a bit better. We have those options for the Debug configuration:

    now the checkbox at the top for CIO says that this requires setting a breakpoint, as you also mentioned. Now there is this "disable interrupts" and the checkbox for "when source stepping" is also activated in this example. Now do they effect each other? like is the breakpoint "seen" as source stepping and thus disabling all interrupts? Or is it even an assembly stepping and can I even deactivate the disabling of interrupts and then it should not be a problem?

  • ok I see, so a memory-logging would be way more reliable here.

    Yes. Another option is to redirect C I/O to a different transport as mentioned at the end of this article: https://dev.ti.com/tirex/explore/node?node=A__ADxuQu8gX3MLBUkurarz8A__ccs_devtools__FUz-xrs__LATEST (see the section "Using printf() to output to a user-defined device").

    Now do they effect each other? like is the breakpoint "seen" as source stepping and thus disabling all interrupts?

    "source stepping" in regards to that option typically only applies to when the target is executing an explicit source step operation. If a breakpoint is explicitly set somewhere and the target is run and the breakpoint is hit, that is not considered a source step. That is considered "running" and then a breakpoint is hit.

  • ok thanks Ki,

    just one more time to get this for my understanding: does this breakpoint mean that there is no more execution of any interrupts?

  • does this breakpoint mean that there is no more execution of any interrupts?

    If the "When running" option is disabled, then interrupts will be executed while the target is running until the breakpoint is triggered. Interrupts will not be serviced while halted at the breakpoint of course.