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.

RTOS/CC1310: HWI Timer Being Pre-empted by SysClock?

Part Number: CC1310
Other Parts Discussed in Thread: SYSBIOS, CC3200

Tool/software: TI-RTOS

Hi,

I'm a newbie to TI-RTOS and I'm having trouble getting my blinky to work on my CC1310 Launchpad.

I think I am missing something about the periodicity or something is pre-empting my HWI.

-----

app.cfg

***
(Other settings excluded, I am using a clean TI .cfg from a template)

var Clock = xdc.useModule('ti.sysbios.knl.Clock');
Clock.tickPeriod = 10;
Clock.tickMode = Clock.TickMode_PERIODIC;

var Timer = xdc.useModule('ti.sysbios.hal.Timer');

*****************

Application:


/* XDC Module Headers */

#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
//#include <xdc/runtime/Types.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>

/* BIOS Module Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/hal/Timer.h>
//#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Queue.h>

/* Example/Board Header files */
#include "Board.h"

/* NOTE: See tistdtypes.h, for data types */


Timer_Handle timerHandle;

/* Create Timer Parameters object */
Timer_Params timerParams;

Void tickFxn(UArg arg0)
{
static Uint16 cTimerInterrupts;

cTimerInterrupts++;

if(cTimerInterrupts == 100)
{
/* Turn on user LED */
GPIO_toggle(Board_GPIO_LED0);
GPIO_toggle(Board_GPIO_LED1);
cTimerInterrupts = 0;
}
}

/*
* ======== main ========
*/
int main()
{
/* Set Error Blocks */
Error_Block eb;

/* Initialize Error Block */
Error_init(&eb);

/* Initialize Board */
Board_initGeneral();

/* Initialize GPIO */
GPIO_init();

/* Configure the LED pin */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

/* Initialize Timer */
Timer_Params_init(&timerParams);
timerParams.period = 5000; /* 5ms seconds timer (1 = 1us) */
timerParams.periodType = Timer_PeriodType_MICROSECS;
timerHandle = Timer_create(Timer_ANY, tickFxn, &timerParams, &eb);
if (timerHandle == NULL)
{
System_abort("Timer create failed");
}

/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);

BIOS_start(); /* does not return */
}

*************************

-------------------------------------

When I debug this function using breakpoints, I see the LEDs toggling correctly off of cTimerInterrupts.

When I run the function I don't see the LEDs toggling.

Here is my understanding of what I have set up.

In app.cfg, I have the Clock tick period set to 10us.  That is actually an HWI that is hard posting.  You should use that clock tick to trigger SWIs?

Regardless of the clock period, I have set another HWI that is set to go off every 5ms.  With my LED timer variable, I should see the LED toggles every 500ms?

A few question:

1)In general practice should I be using the Clock module and SWIs like in the SYS_BIOS example to toggle an LED like this?  Is the periodicity actual 10us?

2)What is going on with the Timer tickFxn task (ISR?)?  Why do not I see the led blinking every 500ms?  Am I incorrect about the period of the timer I setup in main?  Is this HWI getting pre-empted with the 10us Clock module running?

I think the context here isn't so much to get the LED blinking, but my concern is more like when we have HWIs (GPIO callbacks on button presses, or incoming driver inputs that need an HWI to service them) how do I make sure I'm not goofing up the priority.  (For this example, I would probably blink the LED based on the SYS/BIOS clock examples type approach if this was the whole application).

Thanks,

  • I wired up a blinking LED using a Clock Object. I see the default clock timing seems to be TickMode_Dynamic, and the tick period is actually 1000us by default.

    So what am I doing wrong with my HWI Timer object? When I add back in the Timer code, and have it try to blink LED1 seperate from the Clock everything stops working.  Something is not happy here.

    I've got GPIO callbacks working on an input button (plus a oneshot timer to debounce it!), but I can't get the HWI Timer to work like I am expecting.

    Also, when I change the TickMode to PERIODIC, the clock task isn't triggered...  Is there a bunch of RTOS stuff on the CC1310 that depends on TickMode_Dynamic?


    So, here is what a 500ms blinking LED looks like:

    ***
    *WHATEVER ELSE IN MAIN*

    /* Set Clock Parameters */
    Clock_Params_init(&clkParams);
    //Default clock is 1000us, so 500ms = 500,000
    clkParams.period = 500000/Clock_tickPeriod;
    clkParams.startFlag = TRUE;

    /* Construct a periodic Clock Instance */
    Clock_construct(&clk0Struct, (Clock_FuncPtr)clk0Fxn, 5000/Clock_tickPeriod, &clkParams);

    BIOS_start(); /* does not return */
    }

    /*
    * ======== clk0Fxn =======
    */
    Void clk0Fxn(UArg arg0)
    {
    /* Turn on user LED */
    GPIO_toggle(Board_GPIO_LED0);
    GPIO_toggle(Board_GPIO_LED1);
    }

  • Hi Tim,

    Lets see if I can put some answers to all your questions!

    First of all,from where did you pick up the app.cfg example? Out default .cfg files that we ship with the example is setup to have a 10 us tick resolution. If you are seeing a tick period of 1000us, can you check what the Clock module is setup to using ROV (Tools->Runtime object viewer->Clock (module), required using CCS).

    I have tried to run your initial example code and it worked out just fine for me with blinking LEDs at 500ms with or without breakpoint. I would guess the only difference here is our .cfg files, where I simply added the hal.Timer module and also set Clock.tickMode = Clock.TickMode_PERIODIC;

    The general practice to implement this on the CC13XX and CC26XX would be using the Clock module like you do in the second post. 
    The Timer/Clock situation for TI-RTOS on these devices is a bit confusing, basically the main Timer only support one instance, which is used for the RTOS system tick. This timer is using the RTC hardware and also sources all Clock instances. This means you can only have one of these Timer instances, but multiple Clock instances on top of it (you could do some HWI hooks into this Timer if you really need to, see the API documentation below). 

    dev.ti.com/.../Timer.html

    There is another Timer implementation that maps to the SysTick hardware, which is the one you are using. This works, but the timer will stop when the system clock shuts down (low-power modes).

    dev.ti.com/.../Timer.html

    Point being, you are better of using the Clock module as this is always running as it is built on top of the RTC.

  • APP. CFG LINK:app.cfg

    ----------------------------------------------

    Hi M-W,

    My app.cgf is just a renamed stock .cfg from the empty sysbios project.

    I added it here, do you agree that the Clock settings in app.cfg, should be 10 us?  And that var Timer = xdc.useModule('ti.sysbios.hal.Timer'), is the correct timer to use in conjunction?  

    Thanks, I will dive through this. I saw somewhere in the documentation (or it may have been an IDE pop-up when you hover over some functionality), that said the minimum tick_period on the CC1310 was 1000us?

    In my app.cfg, the tick_period is set to 10 and the period_tick is not set, so I am assuming it defaults to the dynamic mode. I interpreted that to me the tick_period was in fact 10us. (10 = 10us in the .cfg, seems easy enough). But I'm not seeing that timing with the clock module.

    But, in my clock example, (clkParams.period = 500000/Clock_tickPeriod;), the LED is definently blinking at 500ms (measured it with a scope). I originally used 10us as the timing -- which is why I am wondering about this now.

    ---
    I know some about Cortex M's but am no master (8 bit background, bare-metal).

    I'm kind of trying to naildown some of the specifics. The clock functionality is very intuitive overall. I can see how you can build a threaded application quite quickly.

    That's very clever to use the RTC. Some folks clearly spent some time to implement that along with the dynamic tick algorithm.

    ---

    I just started playing with the ROV. I'll chase this for a bit, let me know if I am crazy on the clock_tick timing for the CC1310.

    The long and short, is that we have an interrupt where we need an HWI at 300us that pre-empts any SWI or TASKS.

    So I want to nail down the timing here.

  • Okay here is a clue of something not working right.  What could this be?

    On my CC1310 Launchpad, I explicitly set the TimerParams for periodType MICROSECONDS and a period of 50000.

    When I am in ROV, I attached a screenshot of that Timer object.  It has what looks like a 24MHz period, and is clocked off of counts (system cycles, I am guessing)...

    Did I goof something up here?  It's taking the tickFXN parameter.

    ----

  • Hi Tim,

    I need to have a deeper look into this hal.Timer, seems to me it is behaving strange (or at least the Friday nerves are getting the best of me).

    The Clock tick period should be 10 us from what you are setting up in the .cfg file. When you say you are not seeing this timing, what do you mean? I understand that you see the correct period when setting the clkParams.period to 500000/Clock_tickPeriod (this would be the safest way to do this as you don't have to change all your code if changing the period in the .cfg file), have you check the value of Clock_tickPeriod?

    There is some other SimpleLink platforms such as the MSP and CC3200 that have a default period of 1000us, so there could be some references around TI-RTOS with this value (regarding the pop-up). For CC13XX and CC26XX, the default are typically 10us, however, it depends on what you set in the .cfg file as you have already figured out.

    If you really need a 300us HWI interrupt, I recommend you look at the other timer module based on the RTC and read the API documentation there. It describes how you can use the two remaining RTC channels to add another custom RTC timer interrupt (requires some additions to the .cfg file as). This method also allows you to use low-power modes (as the SysTick timer needs the system to be active to function).

     

  • Hi M-W,

    Sorry, I'm muddling through this stuff for the first time. I don't have a history with TI MCUs or the SDKs, so I totally understand what you are saying. The general documents generally tell you about the products, but there are always these little details.

    The design intent is for you open the examples, wire up your application as quickly as possible, and ship a working product! ;)

    This HWI really is an odd one because it seems so fundamental to any embedded system.  I'm just trying to nail down the order of operations of the CC1310 (those TI Workshop videos!).
    ---

    I came across this very good post from 2016 discussing the RTC clock, and some details on the dynamic_tick.

    e2e.ti.com/.../1769815

    Whoever ScottG is/was at TI, seemed to infer that the radio stack was designed to run on the CC1310 RTC at 10us. I also read that the SOC hard operates at 48MHz (non-adjustable), and that's from the guy who runs the support group for CC1310. So I am taking those as a given.

    What is really good from that post is that it indicates that these system ticks are coming from the clock (I originally thought we were using a Timer object and issuing a HWI, so you would be messing with timing in the SWI context of other tasks. I am thinking that perhaps everything is executed in the SWI on the CC1310 -- as debugging some RTOS calls also can't be done, something about "missing the symbols" or something from another forum post I put up -- I can't really confirm).

    When I modify my .cfg away from dynamic_tick, or try to change the period (without modifying the idle task). Let's just say bad stuff happens. The system appears to just lock and non-function. That is just like blinking LEDs locking, not like some esoteric radio issue.

    I'm starting to think the way the SOC is wired with the RTOS is to leave that value alone.... I'd have to investigate further because there is some notation that the power management task relies on 10us timing, and if you disabled it in the idle task, maybe it would work. The RF core may be using the 10us timing with other clock objects in the RTOS.

    Is it possible the CC1310 actually does not have free timers for the Timer object? I have read somewhere about a SensorTag processor running at 24MHz, perhaps this is what the Timer object is setting itself against...?  I'm not sure where else 24MHz is coming from.

    ---

    For my clock example, I need to recalculate all the values to make sure. It's very easy to be off by a factor of 10.

    Since for certain we have a 10us period occurring. I would say there is just a simply syntax / typo / calculation issue somewhere. I'm not worried.

    Why the system locks out when I adjust to systick_periodic?  That is maybe more concerning, but I'm coming around to dynamic just being a necessity for the power management and radio. 

    If you actually have 10us of response time,  that's pretty darn fast for any application I could dream of using the CC1310 for.

    ---

    Could you check a bit more on the Timer object / HWI situation with the CC1310? Like my design concern would be, "well what about the callback functions for the peripherals? Are those in the HWI context or SWI context?".

    Thus far I haven't gotten anything going in the HWI context. I have a theory the peripheral callbacks are in the SWI context on the CC1310, because of the very unique RTC clock being used for the 10us period.

  • Hi Tim,

    No worries, I'm happy to try answering your questions, things tend to be a bit trickier to understand when starting with TI-RTOS, the system clock is one of these things.

    The TI-RTOS uses the Clock module to create the system tick, and the Clock module itself uses the sysbios.family.arm,cc26xx.Timer (lets call it the RTC Timer) module.
    The Clock module runs all interrupts in Swi context and are set to the highest Swi priority per default. The Timer however calls it's functions in Hwi context, this is why you can hook into the RTC channel 1-2 to create a Hwi Timer if you need one, channel 0 is reserved for the Clock module.

    Then we have the confusion of the two Timers. The RTC Timer only support one instance so there is no "free" objects for this timer when running TI-RTOS. The hal.Timer that uses the SysTick module does however support multiple instances, but this timer is only functional when the device is active (system clock is running). The limitation to the later makes the Clock module a better choice (even if run in Swi) as this enables low-power modes to be used.

    I tried your basic LED example with periodic mode on the Clock without any problem, changing from dynamic to periodic should typically not break the code but instead generate additional overhead due to unnecessary interrupts. Could you share the exact code you are running when setting periodic mode?

    Regarding the Hwi or Swi context part, generally all callback functions are performed in Swi context when using our peripheral drivers. The peripheral Hwi is typically used inside the drivers and when it is time for the callback this is done by posting a separate Swi. There exist some special cases where a callback can be posted in either Task or Hwi context as well, in this case it is documented in that specific driver.

    If you are able to get the hal.Timer to work you should have a Hwi callback working (I'm running your earlier example just fine).

    A note on debugging TI-RTOS, missing symbols are typical if the ROM code are used. Disabling ROM usage for TI-RTOS in the .cfg file should make it easier to debug.

    Furthermore, I had another look on my hal.Timer code and it works as intended, turns out the Friday nerves got to me.
  • CC1310_RTOS.zip

    Hi M-W,

    Everything you explained I totally understand.  That was my understanding as well.  

    I went back to an earlier version of this demo code just with the clock example.  

    In app.cgf, line 56, if I don't comment out, Clock.tickMode = Clock.TickMode_PERIODIC, than the system locks up and doesn't blink an LED.

    Can you sanity confirm the attached project builds and runs with periodic_tick enabled, as in app.cfg?

    I'm coming around to the possibility I damaged my example boards in some way, perhaps. (Seems I damaged the RF front end on one sample board (the RF core doesn't work anymore), I forgot to put an LDO in front of a 3.7V LiPo to the external power pins -- it's possible the SOC got zapped with 4.2V from LiPo...  The other board seems to work okay though, the TX output looks fine on the spectrum analyzer.  But it still locks.)

    I ordered two more Launchpads from DigiKey just to confirm if there is a HW issue (I'm also seeing flakiness with RF Studio and our own RF demos, like 15 ft of range issues -- maybe these boards are just bad, I don't think I'm jacking up the code).

    --

    That's very helpful with the peripheral drivers.  I keep hearing "use the clock object" from TI employees, so I take it they probably apply that to the peripherals as well in terms of end users!  I am probably thinking that the RTOS design intent is for users to use tasks and semaphores, so you don't trip up the SWIs?  HWIs use with abundant caution, they are "reserved" for the highest level stuff in the RTOS and hardware -- ie. you could break things in the RTOS?

  • Hi Tim,

    I have looked on your project and what is causing the crash when setting the Clock period is that you are including the ROM BIOS. If you are to use the BIOS is ROM you should leave the Clock setting untouched. In general, I would advice to leave this as dynamic in any case to avoid unnecessary interrupts and overhead.

    If you comment out the ROM part of the app.cfg, your program will run with Clock.TickMode_PERIODIC set, however, you will not see the clock period you expect if you set the Clokc.tickPeriod to low. This because the RTC timer will go into generating a period interrupt at a a 4 tick interval if the interval is to small (and periodic).

    An example:. This means that if you set the tickPeriod to 10 us and Clock object period to be 5000, you will have a ~610ms period. This plays well with the fact that a RTC tick is ~30.5 us: 610 ms/5000 period = 0.122 / 4 tick per interrupt = 30.5 us

    If you in this case would adjust the tickPeriod to a higher number (say 1000us), then you would get the expected result: a 500 Clock object period is 500 m.

    Hope this is helps to clarify everything regarding the Clock module.

    Using semaphores/events/etc together with Task is a good approach to not trip up the Hwi/Swis (as you say).There are typically no need for users to look into the Hwis unless they are writing there own driver for any of the peripherals.

    If this is the case for some reason, you should use the TI-RTOS Hwi module to register the Hwi to the peripheral. As long as the Hwi routine is not doing anything that would cause a look in the system (any kind of blocking calls such as pend APIs) the RTOS should be all happy and healthy.

  • BEAUTIFUL.  Okay that explains the behavior.  Thanks, I would NEVER have divined that as the cause.  RTOS in ROM, lesson learned....

    I hear you on the HWIs!

    Alright -- hopefully smooth sailing to code out this application.

  • Good luck with the sailing ;)

    Using the ROM BIOS saves quite a bit of Flash for those applications where the fit is tight. If you are OK with the example configurations you should be just fine. Typically the build tools would throw an error if trying to change the configuration in such a way that the ROM would not support it (in other word I would have expected a compilation error if it was not supported).

    I will have to look into if we are missing an check here for the case when TI-RTOS is build with ROM.