RT-Thread 源码阅读笔记之hook function call macro

RT-Thread 操作系统

hook function call macro

The hook function call macro 可能是指在某些编程语言中用于插入或修改函数调用行为的宏。这种宏通常用于调试、性能监控、日志记录或其他需要在函数执行前后进行额外操作的场景。例如:

#define HOOK_CALL(func) \
    do { \
        if (hook_##func != NULL) { \
            hook_##func(); \
        } \
    } while (0)

/* 使用时 */
void foo() {
    do_something();

    HOOK_CALL(foo);

    do_other_things();
}

在rtt中,对hook的宏定义是这样的:

/**
 * The hook function call macro
 */
#define _RT_OBJECT_HOOK_CALL(func, argv) __ON_HOOK_ARGS(func, argv)
#define RT_OBJECT_HOOK_CALL(func, argv)  _RT_OBJECT_HOOK_CALL(func, argv)

    #ifdef RT_HOOK_USING_FUNC_PTR
        #define __ON_HOOK_ARGS(__hook, argv)        do {if ((__hook) != RT_NULL) __hook argv; } while (0)
    #else
        #define __ON_HOOK_ARGS(__hook, argv)
    #endif /* RT_HOOK_USING_FUNC_PTR */

/* 在使用时 (src/clock.c)*/
static void (*rt_tick_hook)(void);
/* This function will set a hook function, which will be invoked when tick increase */
void rt_tick_sethook(void (*hook)(void))
{
    rt_tick_hook = hook;
}
void rt_tick_increase(void)
{
    RT_ASSERT(rt_interrupt_get_nest() > 0);

    RT_OBJECT_HOOK_CALL(rt_tick_hook, ());
    /* tracing cpu usage */
    _update_process_times(1);
   // any code ......
}

在上面的例子里,注册了一个时间片增长的钩子函数 rt_tick_hook,并且在 rt_tick_increase() 运行时被调用,rt_tick_increase() 给操作系统提供时钟,stm32一般在滴答定时器中被调用,所以每次进入滴答定时器中断,都会触发钩子函数rt_tick_hook,简单来说,就是可以跟随时间片增长函数进行周期执行。
在rtt的历程中,我找到了相关的运用:

#define PWM_CYCLE_MAX   255
static struct rt_device_pwm *pwm_dev;    /* rtt pwm设备 */
static void pwm_tick_hook(void)
{
    uint32_t pulse;
    if (pwm_dev)
    {
        /* PWM.CH3 duty cycle : 0%->100% for every ~2.5 seconds */
        pulse = (rt_tick_get() >> 1) % (PWM_CYCLE_MAX + 1);
        pulse = (pwm_period * pulse + PWM_CYCLE_MAX/2) / PWM_CYCLE_MAX;
        rt_pwm_set_pulse(pwm_dev, 3, pulse);  /* rtt pwm设备的通道3输出占空比为pulse的脉冲 */
    }
}

这是一段测试pwm设备的测试程序,意思是在2.5秒内将PWM通道3的占空比从0%线性增加到100%,然后再从100%线性减少到0%,循环反复。至于这个2.5s,就是通过rt_tick_increase()的钩子函数rt_tick_hook来实现周期调用,从而实现2.5s的周期。

总结

在嵌入式实时操作系统(RTOS)中,钩子(hook)函数是一种常见的设计模式,它允许用户在操作系统的特定事件或动作发生时插入自定义的代码。这种机制在RTT中得到了广泛应用,特别是在时钟管理方面。rt_tick_increase()是RTT内核中的一个关键函数,它负责增加系统的滴答计数,通常每秒钟调用多次。这个函数在系统计时、任务切换等方面起着核心作用。
由于clock.c文件属于操作系统内核的一部分,直接修改内核源码是不推荐的,因为这可能会导致系统不稳定,而且对内核的修改在系统升级时可能会丢失。因此,RTT提供了一种钩子机制,允许用户在不改动内核代码的情况下,注册自己的函数来扩展内核功能。
例如,用户可能需要周期性地执行某些操作,比如PWM(脉宽调制)信号的测试。在这种情况下,用户可以注册一个钩子函数,这个钩子函数会在每次rt_tick_increase()被调用时执行。这样,用户就可以在不直接修改rt_tick_increase()的情况下,实现周期性任务的需求。

通过使用钩子函数,RTT提供了一种灵活且安全的机制,使用户能够在保留内核稳定性和可维护性的同时,实现特定的功能扩展。这种设计既保护了内核的完整性,又满足了用户的定制化需求,是一种理想的解决方案。

--- 2025/1/3

文章作者: 戎劲羽
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 羽老板的心事
rt-thread C语言 rt-thread 学习
喜欢就支持一下吧