设为首页 加入收藏

TOP

Zephyr学习(四)系统时钟(二)
2019-09-01 23:08:47 】 浏览:94
Tags:Zephyr 学习 系统 时钟
dler(void *unused) 2 { 3 ARG_UNUSED(unused); 4 5 sys_trace_isr_enter(); 6 7 /* accumulate total counter value */ 8 clock_accumulated_count += sys_clock_hw_cycles_per_tick; 9 10 /* 11 * one more tick has occurred -- don't need to do anything special since 12 * timer is already configured to interrupt on the following tick 13 */ 14 _sys_clock_tick_announce(); 15 16 extern void _ExcExit(void); 17 _ExcExit(); 18 }

第8行,累加系统启动后经历了多少个时钟计数,注意这里不是累加系统ticks的个数,因为累加时钟计数会更加精确。

第14行,调用_sys_clock_tick_announce()函数,定义在zephyr-zephyr-v1.13.0\include\drivers\ system_timer.h:

#define _sys_clock_tick_announce() \
        _nano_sys_clock_tick_announce(_sys_idle_elapsed_ticks)

在没有使能TICKLESS_KERNEL配置的情况下参数_sys_idle_elapsed_ticks的值为1,实际上调用的是_nano_sys_clock_tick_announce()函数,定义在zephyr-zephyr-v1.13.0\kernel\ sys_clock.c:

1 void _nano_sys_clock_tick_announce(s32_t ticks)
2 {
3     unsigned int  key;
4 
5     K_DEBUG("ticks: %d\n", ticks);
6 
7     /* 64-bit value, ensure atomic access with irq lock */
8     key = irq_lock();
9     _sys_clock_tick_count += ticks;
10    irq_unlock(key);
11
12    handle_timeouts(ticks);
13
14    /* time slicing is basically handled like just yet another timeout */
15    handle_time_slicing(ticks);
16}

第9行,累加系统启动后所经历的ticks个数。

在分析第12行的handle_timeouts()函数之前,先说一下线程加入到超时队列的过程。线程通过调用k_sleep()等函数后,系统会将该线程加入到超时队列里,然后调度其他线程。k_sleep()对应的实现函数为_impl_k_sleep(),定义在zephyr-zephyr-v1.13.0\kernel\ sched.c:

1 void _impl_k_sleep(s32_t duration)
2 {
3     /* volatile to guarantee that irq_lock() is executed after ticks is
4      * populated
5      */
6     volatile s32_t ticks;
7     unsigned int key;
8 
9     __ASSERT(!_is_in_isr(), "");
10    __ASSERT(duration != K_FOREVER, "");
11
12    K_DEBUG("thread %p for %d ns\n", _current, duration);
13
14    /* wait of 0 ms is treated as a 'yield' */
15    if (duration == 0) {
16        k_yield();
17        return;
18    }
19
20    ticks = _TICK_ALIGN + _ms_to_ticks(duration);
21    key = irq_lock();
22
23    _remove_thread_from_ready_q(_current);
24    _add_thread_timeout(_current, NULL, ticks);
25
26    _Swap(key);
27}

第15行,如果传进来的时参数为0,则直接调用k_yield()函数,切换到其他线程,具体实现的话在下一篇随笔里再分析。

第20行,_TICK_ALIGN的值为1,即将睡眠时间以tick为单位补齐。

第23行,调用_remove_thread_from_ready_q()函数,定义在zephyr-zephyr-v1.13.0\kernel\ sched.c:

1  void _remove_thread_from_ready_q(struct k_thread *thread)
2  {
3      LOCKED(&sched_lock) {
4          if (_is_thread_queued(thread)) {
5              _priq_run_remove(&_kernel.ready_q.runq, thread);
6              _mark_thread_as_not_queued(thread);
7              update_cache(thread == _current);
8          }
9      }
10 }

第4行,线程能够运行,那它的状态必须是已经_THREAD_QUEUED了的。

第5行,将线程从运行队列移除,那么线程就不会参与线程调度了。

第6行,设置线程状态不为_THREAD_QUEUED。

第7行,调用update_cache()函数,在上一篇随笔已经分析过了,这里不再重复。

回到_impl_k_sleep()函数,第24行,调用_add_thread_timeout()函数,定义在zephyr-zephyr-v1.13.0\kernel\include\timeout_q.h:

1 static inline void _add_thread_timeout(struct k_thread *thread,
2                        _wait_q_t *wait_q,
3                        s32_t timeout_in_ticks)
4 {
5     _add_timeout(thread, &thread->base.timeout, wait_q, timeout_in_ticks);
6 }

实际上调用的是_add_timeout()函数,定义在zephyr-zephyr-v1.13.0\kernel\include\timeout_q.h:

1 static inline void _add_timeout(struct k_thread *thread,
2                 struct _timeout *timeout,
3                 _wait_q_t *wait_q,
4                 s32_t timeout_in_ticks)
5 {
首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇per-CPU变量 下一篇网络中的NAT模式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目