Chapter 5th Time Service
5.1 Time Service OverviewIn Sys/bios and Xdctools, there are several modules involved in clocking and clocking-related services:
Ti.sysbios.knl.Clock module:Responsible for periodic system ticks that the kernel uses to hold the time track. All Sys/bios APIs Expect a timeout parameter to interrupt timeout set by time ticks. The clock module is used to dispatch functions that are run internally as specified in the clock ticks. By default, the clock module uses the hardware abstraction layer. The timer module gets the hardware-based tick. In addition, the clock module can be configured to use the tick source provided by the application, as described in section 5.2 (Clock module replaces CLK and PRD in earlier Dsp/bios versions).
Ti.sysbios.hal.Timer module:Provides a standard interface for using timer peripherals. It hides the specific characteristics of all targets/devices of the timer peripherals. The target/device specific properties of the timer are supported by the Ti.sysbios.family.xxx.Timer module (for example, Ti.sysbios.family.c64.Timer). You can use a timer module to invoke a TICKFXN when the timer expires. See sections 5.3 and 8.3 for more details.
The ti.sysbios.hal.Seconds module:Provides a means to maintain the current time and date, defined as the number of seconds since 1970 (Unix ERA). This module generates a custom time () function to invoke the Seconds_get () and overrides the C standard library () function. See section 5.4.
Xdc.runtime.Timestamp module:Provides a simple timestamp service for baseline code and for adding timestamp logs. This module uses the timestampprovider of a specific target/device in Sys/bios to control the implementation of the timestamp, as described in section 5.5. See video introducing Timers and clocks for an overview.
5.2 ClockThe Ti.sysbios.knl.Clock module is responsible for the periodic system tick that the kernel uses to hold the time track. All Sys/bios APIs Expect a timeout parameter to interrupt timeout set by time ticks.
The clock module uses the timer created by the Ti.sysbios.hal.Timer module by default to generate the system tick---based on the period called Clock_tick (). For more information on the timer module, refer to Section 5.3.
The clock module can be configured to not use a timer, and the following two static declarations can:
Ti.sysbios.knl.Clock.tickSource = Clock.ticksource_user Or Ti.sysbios.knl.Clock.tickSource = Clock.ticksource_null |
The period of the system tick is set by the configuration parameter clock.tickperiod, in microseconds.
The Clock_tick () and tick cycles are used in the following ways:
if Ticksource is Clock.ticksource_timer(default), the clock uses Ti.sysbios.hal.Timer to create a timer to produce a system tick, which is generated based on the period of the called Clock_tick (). The clock uses Clock.tickperiod to create timers. The Clock.timerid can be changed, which allows the clock to use different timers.
if Ticksource is Clock.ticksource_user, your app must call Clock_tick () from the user interrupt and set Tickperiod to the approximate frequency of user interrupts in microseconds.
if Ticksource is Clock.ticksource_null, you cannot invoke any Sys/bios APIs with a timeout value, and you cannot invoke any clock APIs. You can still use the task module, but you cannot invoke APIs that require a timeout, such as Task_sleep (). The Clock.tickperiod value in this configuration is not valid.
Clock_getticks () The number of times the clock ticks has occurred since startup. This value will change back to 0 when it reaches the maximum value that 32bit can store.
The clock module provides APIs for starting, stopping, and reconfiguring ticks. These APIs allow you to change the frequency at run time. The three APIs are non-reentrant, so there is no need for gates to protect them.
clock_tickstop ()The clock tick is generated by calling the Timer_stop () stop timer.
Clock_tickreconfig ()Calls the Timer_setperiodmicroseconds () reconfiguration timer internally. If the timer cannot support Clock.tickperiod at the current CPU frequency, then Clock_tickreconfig () fails. Clock_tickstart () Restarts the timer by calling Timer_start () to generate the clock tick. The clock module allows you to create an instance of the clock object, when the timeout value specified in clock ticks expires and the associated function runs.
All clock functions run in the context of the SWI. That is, the clock module automatically creates a SWI and runs the clock function within the SWI. You can change the priority of the SWI used by the clock by configuring Clock.swipriority.
You can use Clock_create () to dynamically create a clock instance. The clock instance can be either a single trigger or a continuous trigger. You can start a clock instance by calling Clock_start () after the clock is created or started. This is controlled by the configuration parameter Startflag. Clock_create () can only be called in the context of a task or main () function.
Clock_create () requires a function and a non-0 timeout value as a parameter. When timeout expires, the function is called. The timeout value is used to calculate the first expiration time. For a single-shot clock instance, the timeout value is used to calculate a single expiry time of period of 0. For a recurring clock instance, the timeout value is used to calculate the first expiration time, and the period value (part of the parameter) is used after the first trigger. Clock instances (single and recurring clocks) can be started and restarted by calling Clock_start () and Clock_stop (). Note When Clock_tickstop () stops the timer used to generate the clock tick, clock_stop () stops only one instance of the clock object. When you call Clock_start (), the expiration value is recalculated. APIs that start and stop clock instances---clock_start () and Clock_stop () can be called in any context other than the start of the program before Main ().
The Clock module provides clock_setperiod (), Clock_settimeout (), and Clock_setfunc () APIs to change the clock instance properties after a stop.
Run-time instance: This C instance demonstrates how to create a clock instance. This instance is created dynamically (run repeatedly) and starts automatically. It runs the MyHandler function once every 5 ticks. A user parameter (UARG) is passed to the function.
Clock_params Clockparams; Clock_handle Myclock; Error_block EB; Error_init (&EB); Clock_params_init (&clockparams); Clockparams.period = 5; Clockparams.startflag = TRUE; Clockparams.arg = (uarg) 0x5555; Myclock = Clock_create (MyHandler1, 5, &clockparams, &eb); if (Myclock = = NULL) { System_abort ("Clock create failed"); } |
Configuration instance: This example creates a clock instance from the configuration script, with the same properties as the previous example.
var Clock = xdc.usemodule (' Ti.sysbios.knl.Clock '); var clockparams = new Clock.params (); Clockparams.period = 5; Clockparams.startflag = true; Clockparams.arg = (uarg) 0x5555; Program.global.clockInst1 = Clock.create ("&myhandler1", 5, Clockparams); |
Run-time instance: this instance uses some clock APIs to print how long a task sleeps.
UInt32 time1, time2; . . . system_printf ("Task going to sleep for ten ticks ... \ n"); time1 = Clock_getticks (); Task_sleep (10); Time2 = Clock_getticks (); System_printf ("... awake! Delta time is:%lu\n ", (ULong) (time2-time1)); |
Runtime instance: This C instance uses some clock APIs to reduce the frequency of the clock module.
Bios_getcpufreq (&cpufreq); Cpufreq.lo = CPUFREQ.LO/2; Bios_setcpufreq (&cpufreq); Key = Hwi_disable (); Clock_tickstop (); Clock_tickreconfig (); Clock_tickstart (); Hwi_restore (key); |
the following non-translated content:
Clocks are often used, here are a few examples, familiar with the use of clocks.
Example 1:Before the LED has done a marquee, using Cpudelay () to control the time, it was also mentioned that this method is not suitable for practical development. Well, it's a normal way to use a clock to implement a marquee today. The code is as follows:
#include <xdc/std.h> #include <xdc/runtime/System.h> #include <xdc/runtime/Error.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Clock.h> #include <ti/sysbios/knl/Task.h> #include <ti/drivers/PIN.h> #include "Board.h" /* Pin driver handle */ Static Pin_handle Ledpinhandle; Static Pin_state ledpinstate; Pin_config ledpintable[] = { board_led1 | Pin_gpio_output_en | Pin_gpio_high | Pin_drvstr_max, Board_led2 | Pin_gpio_output_en | Pin_drvstr_max, Board_led3 | Pin_gpio_output_en | Pin_drvstr_max, Board_led4 | Pin_gpio_output_en | Pin_drvstr_max, Pin_terminate }; Void clkfxn (Uarg arg0) { static uint8_t i = 0; Pin_setoutputvalue (Ledpinhandle, Ledpintable[i] & 0xFF, 0); i = (i + 1)% 4; Pin_setoutputvalue (Ledpinhandle, Ledpintable[i] & 0xFF, 1); } int main (void) { Clock_params Clockparams; Board_initgeneral (); /* Open LED pins */ Ledpinhandle = Pin_open (&ledpinstate, ledpintable); if (!ledpinhandle) { System_abort ("Error Initializing Board LED pins\n"); } Clock_handle Myclock; Error_block EB; Error_init (&EB); Clock_params_init (&clockparams); Clockparams.period = 10000; Clockparams.startflag = TRUE; Myclock = Clock_create (CLKFXN, 5, &clockparams, &eb); if (Myclock = = NULL) { System_abort ("Clock create failed"); } Bios_start (); return (0); } |
Example 2:CC2650 comes with a clock instance that can be downloaded from the "View" and "Resource Explorer" menu in CCS. The code is as follows:
#include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Clock.h> #include "Board.h" Void clk0fxn (Uarg arg0); Void clk1fxn (Uarg arg0); Clock_struct clk0struct, clk1struct; Clock_handle Clk2handle; Int Main () { /* Construct BIOS Objects */ Clock_params Clkparams; /* CALL Board init functions */ Board_initgeneral (); Clock_params_init (&clkparams); Clkparams.period = 5000/clock_tickperiod; Setting this flag indicates that Clk0 is automatically started Clkparams.startflag = TRUE; /* Create a multi-cycle clock */ Clock_construct (&clk0struct, (clock_funcptr) CLK0FXN, 5000/clock_tickperiod, &clkparams); Clkparams.period = 0; Setting this flag indicates that CLK1 is started manually Clkparams.startflag = FALSE; /* Create a single-cycle clock */ Clock_construct (&clk1struct, (clock_funcptr) CLK1FXN, 11000/clock_tickperiod, &clkparams); Clk2handle = Clock_handle (&clk1struct); Manually Start CLK1 Clock_start (Clk2handle); Bios_start (); /* Does not return */ return (0); } Void clk0fxn (Uarg arg0) { UInt32 time; Time = Clock_getticks (); system_printf ("System time in clk0fxn =%lu\n", (ULong) time); } Void clk1fxn (Uarg arg0) { UInt32 time; Time = Clock_getticks (); system_printf ("System time in clk1fxn =%lu\n", (ULong) time); system_printf ("Calling Bios_exit () from clk1fxn\n"); Bios_exit (0); } |
The results of the operation are as follows:
System time in CLK0FXN = 506 System time in CLK0FXN = 1010 System time in clk1fxn = 1104 Calling Bios_exit () from CLK1FXN |
This example demonstrates how to create a single-cycle clock and a multi-cycle clock at run time. It is created using the Clock_construct () function, and differs from the first instance. Also, this example demonstrates how to manually start a clock, or it is very instructive. You may also like: