RT-Thread / rt-thread

RT-Thread is an open source IoT Real-Time Operating System (RTOS).
https://www.rt-thread.io
Apache License 2.0
10.49k stars 5.02k forks source link

rt_timer_check函数全程关中断有可能影响中断函数响应时间,其函数的关中断时间是否能优化? #7860

Open BreederBai opened 1 year ago

BreederBai commented 1 year ago

芯片:HC32F4A0 问题描述:定时器捕获时发现中断响应有时会延时20多us,单步调试发现是由于rt_timer_check函数长时间关中断造成的。 0通道:捕获信号;1通道:测试用的IO,在捕获中断(上升沿)函数中反转电平;2通道:rt_timer_check函数,在关中断和开中断时反转电平 image

测试二: 修改rt_timer_check函数(更改开关中断位置、更改反转电平位置)再次测试。 0通道:捕获信号;1通道:测试用的IO,在捕获中断(上升沿)函数中反转电平;2通道:rt_timer_check函数,在执行t->timeout_func(t->parameter);时反转电平

/**
 * @brief This function will check timer list, if a timeout event happens,
 *        the corresponding timeout function will be invoked.
 *
 * @note This function shall be invoked in operating system timer interrupt.
 */
void rt_timer_check(void)
{
    struct rt_timer *t;
    rt_tick_t current_tick;
    rt_base_t level;
    rt_list_t list;

    rt_list_init(&list);

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));

    current_tick = rt_tick_get();

    while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
    {
        /* disable interrupt */
        level = rt_hw_interrupt_disable();

        t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);

        /* enable interrupt */
        rt_hw_interrupt_enable(level);

        /*
         * It supposes that the new tick shall less than the half duration of
         * tick max.
         */
        if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
        {
            RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));

            /* remove timer from timer list firstly */
            _timer_remove(t);
            if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
            {
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
            }
            /* add timer to temporary list  */
            rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));

            GPIO_TogglePins(GPIO_PORT_D, GPIO_PIN_14);

            /* call timeout function */
            t->timeout_func(t->parameter);

            GPIO_TogglePins(GPIO_PORT_D, GPIO_PIN_14);

            /* re-get tick */
            current_tick = rt_tick_get();

            RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
            RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));

            /* Check whether the timer object is detached or started again */
            if (rt_list_isempty(&list))
            {
                continue;
            }
            rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
            if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
                (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
            {
                /* start it */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
                rt_timer_start(t);
            }
        }
        else break;
    }

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}

通过下图可以看出t->timeout_func(t->parameter);函数耗时1.37us~2.35us,且执行多个。更改后不再影响中断响应。修改后的代码只是为了验证题目所说的内容,在HC32F4A0上可以正常运行,但并没有严格测试是否会影响内核其他功能。 image

BernardXiong commented 1 year ago

所以这个也会和用户的timer定时器会执行什么超时函数相关

BreederBai commented 1 year ago

大部分执行的是_thread_timeout函数,调用rt_thread_mdelay函数,超时后是会执行_thread_timeout吗?

BreederBai commented 1 year ago

所以这个和用户的定时器计时器会执行什么相关的超时函数

熊大,这个问题即使和用户定时器执行的超时函数有关,似乎也不应该在关中断里执行用户的超时程序

Blues-Jiang commented 1 year ago

我也查到t->timeout_func(t->parameter);这个函数了,但是我最小系统,这里是哪个定时器的影响呢,我本身没开任何定时器啊。

Blues-Jiang commented 1 year ago

主定时器的话超时函数就是_thread_timeout,应该就是t->timeout_func(t->parameter);对应的函数,这个会运行8.6us大概(加上我控制io的时间),我是GD32, 然后rt_schedule会运行4us左右, rt_thread_sleep里也会运行将近9us,里面耗时的就是 err = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE);//4.6us

rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); rt_timer_start(&(thread->thread_timer));//4.7us

再往下我也找不到具体源头了,就我现在这个代码 加上io控制,已经几乎30+us不开中断了,每个时间段都有10us左右,打5折总delay也得15us

BreederBai commented 1 year ago

我也查到t->timeout_func(t->parameter);这个函数了,但是我最小系统,这里是哪个定时器的影响呢,我本身没开任何定时器啊。

有可能是线程的定时器吧

Blues-Jiang commented 1 year ago

我也查到t->timeout_func(t->parameter);这个函数了,但是我最小系统,这里是哪个定时器的影响呢,我本身没开任何定时器啊。

有可能是线程的定时器吧

应该是了,线程对应的定时器。这个东西是挺耗时间的