Clocks

Clock instances are functions that can be scheduled to run after a certain number of system ticks. Clock instances are either one-shot or periodic. These instances start immediately upon creation, are configured to start after a delay, and can be stopped at any time. All clock instances are executed when they expire in the context of a Swi. The following example shows the minimum resolution is the TI-RTOS clock tick period set in the TI-RTOS configuration file (.cfg).

Note

The default TI-RTOS kernel tick period is 1 millisecond. For CC13x2 or CC26x2 devices, this is reconfigured in the TI-RTOS configuration file (.cfg):

Clock.tickPeriod = 10;

Each system tick, which is derived from the real-time clock RTC, launches a Clock object that compares the running tick count with the period of each clock to determine if the associated function should run. For higher-resolution timers, TI recommends using a 16-bit hardware timer channel or the sensor controller. See the Clock module in the package ti.sysbios.knl section of the TI-RTOS Kernel User Guide for more information on these functions.

Functional Example

@startuml
hide footbox

participant Application as A
box "Swi context"
    participant "Clock Object" as B
end box

activate A
group Initialize Clock object
    autonumber
    A -> B : Clock_construct()
    autonumber stop
    A <-- B
end

...

group Start Clock object
    A -> B : Clock_start()

    B --> A
    note left: Event_pend(event,...)

    deactivate A
end

...

group Clock function triggers after expiration
    autonumber resume
    rnote over B
        The Clock object invokes supplied function pointer.
        This function only posts a signal such as an Event
    end note
    B -> B : Application_clockHandler();
    activate B
    autonumber stop
    B -> : Event_post(event, APP_PERIODIC_EVT);
    A <--
    deactivate B
end

group Process period function and restart Clock object
    -> A : Unblocked due to posted APP_PERIODIC_EVT.
    activate A
    rnote over A
        Given that an event was posted, we can process the
        periodic function from a Task context.
    end note
    autonumber resume
    A -> A : Application_performPeriodicTask()
    activate A

    rnote over A
        Restart the clock after the periodic process
    end note
    deactivate A
    autonumber stop
    A -> B : Clock_start();
    B --> A

    deactivate A
    note left: Event_pend(event,...)
end

rnote over A, B
    The Clock object will trigger after
    expiration and the cycle will repeat itself.
end note

...

@enduml

Figure 22. Triggering Clock objects

Step 1 in Triggering Clock objects constructs the Clock object using the Clock_construct API. When the application desires, it will then start the Clock object via the Clock_start() API.

Listing 14. Constructing periodicClock Clock object
// Clock instances for internal periodic events.
static Clock_Struct periodicClock;

// Create one-shot clocks for internal periodic events.
Clock_construct(&periodicClock, Application_clockHandler,
    APP_PERIODIC_EVT_PERIOD, 0, false, APP_PERIODIC_EVT);

Step 2 in Triggering Clock objects, after the Clock object’s timer expired, it will execute Application_clockHandler() within a Swi context. As this call cannot be blocked and blocks all Tasks, it is kept short by invoking an Event_post(APP_PERIODIC_EVT) for post processing in the application task.

Listing 15. Defining Application_clockHandler()
static void Application_clockHandler(UArg arg)
{
    /* arg is passed in from Clock_construct() */
    Event_post(events, arg);
}

Attention

Clock functions must not call blocking kernel APIs or TI-RTOS driver APIs! Executing long routines will impact real-time constraints placed in high priority tasks allocated for wireless protocol stacks!

Step 3 in Triggering Clock objects, the application task is unblocked due the Event_post(APP_PERIODIC_EVT), where it proceeds to invoke the Application_performPeriodicTask() function. Afterwards, to restart the periodic execution of this function, it will restart the periodicClock Clock object.

Listing 16. Servicing the APP_PERIODIC_EVT event
if (events & APP_PERIODIC_EVT)
{
  // Perform periodic application task
  Application_performPeriodicTask();

  Clock_Handle hClock = Clock_handle(&periodicClock);
  Clock_start(hClock);
}