RT-Thread software timer (study notes)

This article refers to [Wildfire EmbedFire] "RT-Thread Kernel Implementation and Application Development - Based on STM32", which is only used as a personal study note. For more detailed content and steps, please check the original text (you can download it from the Wildfire Data Download Center)

Basic Concept of Timer

A timer refers to starting from a specified time, after a specified time, and then triggering a timeout event. Users can customize the period and frequency of the timer. Similar to the alarm clock in life, we can set when the alarm clock rings every day, and also set the number of times of ringing, whether it rings once or every day.

Timers are divided into hardware timers and software timers:

hardware timers are timing functions provided by the chip itself. Generally, the input clock is provided to the chip by an external crystal oscillator, and the chip provides a set of configuration registers to the software module to accept control input. When the set time value is reached, the chip interrupt controller generates a clock interrupt. The precision of hardware timers is generally very high, which can reach the nanosecond level, and is interrupt-triggered.

Software timer, software timer is a type of system interface provided by the operating system. It is built on the basis of hardware timers, enabling the system to provide timer services that are not limited by hardware timer resources. Timers are similar.

The RT-Thread operating system provides software timer functions. The use of software timers is equivalent to expanding the number of timers, allowing more timing services to be created.

--original

Application scenarios of timers

Due to the limited number of hardware timers of microprocessors or microcontrollers, when users need more timers, they need to use software timers to complete.

However, software timers are only suitable for threads that do not require high time accuracy, because compared with hardware timers, software timers have very low accuracy, and software timers are easily interrupted by other threads (software timers are a thread , the priority defaults to 4).

The precision of the timer

In the operating system, usually the software timer takes the system tick cycle as the timing unit. The system beat is the heartbeat beat of the system, indicating the frequency of the system clock, which is similar to the human heartbeat, how many beats can be beat in 1s, the system beat is configured as RT_TICK_PER_SECOND, this macro is defined in rtconfig.h, the default is 1000. Then the clock cycle of the system is 1ms (1s beats 1000 times, each time is 1ms). The timing value of the software timer must be an integer multiple of the beat period. For example, if the beat period is 10ms, the timing value of the upper-layer software timer can only be 10ms, 20ms, 100ms, etc., but not 15ms. Since the tick defines the accuracy that the timers in the system can distinguish, the system can set an appropriate value according to the actual system CPU processing capability and real-time requirements. The smaller the value of the system tick period, the higher the accuracy, but the higher the system overhead. Larger, because the more times the system enters the clock interrupt in 1 second.

--original

How the timer works

When the user creates a software timer, the system will determine the wake-up time timeout of the timer according to the rt_tick time and the timing set by the user, and hang the timer control block into the software timer list rt_soft_timer_list.

rt_tick is a 32-bit unsigned variable used to record the current running time of the system. Every time a clock beat passes, rt_tick is incremented by 1.

rt_soft_timer_list stores timer tasks, which store all activated timers in ascending order of time.

Each time a timer is added, its timeout function wake-up time timeout is equal to the current system time rt_tick + timing time time.

timer control block

struct rt_timer
{
    
    
    struct rt_object parent;                            /**< 继承自rt_object */

    rt_list_t        row[RT_TIMER_SKIP_LIST_LEVEL];     /**< 定时器列表算法用到的队列 */

    void (*timeout_func)(void *parameter);              /**< 定时器超时调用的函数 */
    void            *parameter;                         /**< 超时函数用到的入口参数 */

    rt_tick_t        init_tick;                         /**< 定时器初始超时节拍数 */
    rt_tick_t        timeout_tick;                      /**< 定时器实际超时时的节拍数 */
};

timer timeout function

The timer timeout function is a function that the timer will automatically run when the count value reaches the set value. This function needs to be defined by itself. There are two situations in the timer timeout function:

  1. The timeout function is executed in the (system clock) interrupt context (hardware timer), and RT_TIMER_FLAG_HARD_TIMER needs to be specified in the timer control block;
  2. The timeout function runs in the context of the thread and needs to specify RT_TIMER_FLAG_SOFT_TIMER in the timer control block.

Timer function interface

Create timer rt_timer_create

rt_timer_t rt_timer_create(const char* name,
void (*timeout)(void* parameter), void* parameter,
rt_tick_t time, rt_uint8_t flag);

After calling this function interface, the kernel first allocates a timer control block from the dynamic memory heap, and then performs basic initialization of the control block.
When the specified flag is RT_IMER_FLAG_HARD_TIMER, if the timer times out, the timer's callback function will be called in the context of the service routine of the clock interrupt; when the specified flag is RT_TIMER_FLAG_SOFT_TIMER, if the timer times out, the timer's callback function will be called Called in the context of the system clock timer thread.

parameter describe
name the name of the timer
timeout Timer supermarket function pointer
parameter Timer timeout function entry parameters
time Timeout time, the unit is system beat
flag parameter options

delete timer rt_timer_delete

rt_err_t rt_timer_delete(rt_timer_t timer);

After calling this function interface, the system will delete the timer from the rt_timer_list linked list, and then release the memory occupied by the corresponding timer control block.

parameter describe
timer timer handle

Initialize the timer rt_timer_init

void rt_timer_init(rt_timer_t timer,
const char* name, void (*timeout)(void* parameter), void* parameter,
rt_tick_t time, rt_uint8_t flag);

When using this function interface, the corresponding timer control block will be initialized, the corresponding timer name, timer timeout function, etc. will be initialized.
When the specified flag is RT_IMER_FLAG_HARD_TIMER, if the timer times out, the timer's callback function will be called in the context of the service routine of the clock interrupt; when the specified flag is RT_TIMER_FLAG_SOFT_TIMER, if the timer times out, the timer's callback function will be called Called in the context of the system clock timer thread.

parameter describe
timer timer handle
name the name of the timer
timeout Timer supermarket function pointer
parameter Timer timeout function entry parameters
time Timeout time, the unit is system beat
flag parameter options

Start timer rt_timer_start

rt_err_t rt_timer_start(rt_timer_t timer);

After calling the timer start function interface, the state of the timer will be changed to the active state (RT_TIMER_FLAG_ACTIVATED) and inserted into the rt_timer_list queue linked list in the order of timeout.

parameter describe
timer timer handle

Stop timer rt_timer_stop

rt_err_t rt_timer_stop(rt_timer_t timer);

After calling the timer stop function interface, the timer state will be changed to the stop state, and it will be separated from the rt_timer_list list and will not participate in the timer timeout check. When a (periodic) timer expires, this function interface can also be called to stop the (periodic) timer itself.

parameter describe
timer timer handle

Control timer rt_timer_control

rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);

The control timer function interface can view or change the timer settings according to the command type parameter. Currently supports four command interfaces, namely, set timing time, view timing time, set single trigger, and set cycle trigger;

parameter describe
timer timer handle
cmd Commands to control the timer
arg Control command parameters corresponding to cmd

timer experiment

The experiment is relatively simple, define two timers, use the single timing mode and the periodic timing mode respectively.

#include "board.h"
#include "rtthread.h"


// 定义软件定时器控制块
static rt_timer_t tmr1 = RT_NULL;
static rt_timer_t tmr2 = RT_NULL;

// 可能用到的全局变量
static rt_uint32_t TmrCb_Cnt1 = 0;
static rt_uint32_t TmrCb_Cnt2 = 0;



/******************************************************************************
* @ 函数名  : timer1_callback
* @ 功  能  : 定时器1回调函数
* @ 参  数  : parameter 外部传入的参数
* @ 返回值  : 无
******************************************************************************/
static void timer1_callback(void *parameter)
{
    
    
	rt_uint32_t tick_num1 = 0;
	
	TmrCb_Cnt1++;
	
	tick_num1 = (rt_uint32_t)rt_tick_get();   // 获取滴答定时器的计数值
	
	rt_kprintf("timer1_callback 函数被执行%d次\n", TmrCb_Cnt1);
	rt_kprintf("滴答定时器的数值=%d\n", tick_num1);
}

/******************************************************************************
* @ 函数名  : timer2_callback
* @ 功  能  : 定时器2回调函数
* @ 参  数  : parameter 外部传入的参数
* @ 返回值  : 无
******************************************************************************/
static void timer2_callback(void *parameter)
{
    
    
		rt_uint32_t tick_num2 = 0;
	
	TmrCb_Cnt2++;
	
	tick_num2 = (rt_uint32_t)rt_tick_get();   // 获取滴答定时器的计数值
	
	rt_kprintf("timer2_callback 函数被执行%d次\n", TmrCb_Cnt2);
	rt_kprintf("滴答定时器的数值=%d\n", tick_num2);
}

int main(void)
{
    
    
	// 硬件初始化和RTT的初始化已经在component.c中的rtthread_startup()完成

	// 创建一个软件定时器
	tmr1 =  rt_timer_create("tmr1",                 // 软件定时器名称       
						timer1_callback,            // 软件定时器超时函数
						RT_NULL,                    // 超时函数参数
						3000,                       // 超时时间
						RT_TIMER_FLAG_ONE_SHOT |   
						RT_TIMER_FLAG_SOFT_TIMER);  // 软件定时器模式,一次模式
					
	
	// 启动定时器
	if(tmr1 != RT_NULL)
		rt_timer_start(tmr1);
							
	// 创建一个软件定时器
	tmr2 =  rt_timer_create("tmr2",                 // 软件定时器名称       
						timer2_callback,            // 软件定时器超时函数
						RT_NULL,                    // 超时函数参数
						1000,                       // 超时时间
						RT_TIMER_FLAG_PERIODIC |   
						RT_TIMER_FLAG_SOFT_TIMER);  // 软件定时器模式,周期模式
					
	
	// 启动定时器
	if(tmr2 != RT_NULL)
		rt_timer_start(tmr2);
}

experimental phenomenon

The timer 1 timeout function is executed only once, while the timer 2 timeout function runs periodically.

insert image description here

Guess you like

Origin blog.csdn.net/weixin_43772810/article/details/124191497