设为首页 加入收藏

TOP

Zephyr学习(四)系统时钟(一)
2019-09-01 23:08:47 】 浏览:91
Tags:Zephyr 学习 系统 时钟

每一个支持多进程(线程)的系统都会有一个滴答时钟(系统时钟),这个时钟就好比系统的“心脏”,线程的休眠(延时)和时间片轮转调度都需要用到它。

Cortex-M系列的内核都有一个systick时钟,这个时钟就是设计用来支持操作系统的,是一个24位的自动重装载向下计数器,中断入口就位于中断向量表里面,定义在zephyr-zephyr-v1.13.0\arch\arm\core\cortex_m\vector_table.S:

1 SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
2 
3     /*
4      * setting the _very_ early boot on the main stack allows to use memset
5      * on the interrupt stack when CONFIG_INIT_STACKS is enabled before
6      * switching to the interrupt stack for the rest of the early boot
7      */
8     .word _main_stack + CONFIG_MAIN_STACK_SIZE
9 
10    .word __reset
11    .word __nmi
12
13    .word __hard_fault
14    .word __mpu_fault
15    .word __bus_fault
16    .word __usage_fault
17    .word __reserved
18    .word __reserved
19    .word __reserved
20    .word __reserved
21    .word __svc
22    .word __debug_monitor
23
24    .word __reserved
25    .word __pendsv
26#if defined(CONFIG_CORTEX_M_SYSTICK)
27    .word _timer_int_handler
28#else
29    .word __reserved
30#endif

第27行,_timer_int_handler()就是systick时钟的中断入口函数。

那么问题来了,前面的启动过程随笔里并没有分析到systick时钟是何时被初始化的,事实上systick也是通过设备宏定义的方式进行初始化的,定义在zephyr-zephyr-v1.13.0\drivers\timer\sys_clock_init.c:

SYS_DEVICE_DEFINE("sys_clock", _sys_clock_driver_init, sys_clock_device_ctrl,
        PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);

可知,系统时钟属于PRE_KERNEL_2类设备,同一类设备也是有分优先级的,优先级高的先初始化,初始化函数为_sys_clock_driver_init(),定义在zephyr-zephyr-v1.13.0\drivers\timer\cortex_m_systick.c:

1 int _sys_clock_driver_init(struct device *device)
2 {
3     /* enable counter, interrupt and set clock src to system clock */
4     u32_t ctrl = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk |
5             SysTick_CTRL_CLKSOURCE_Msk;
6 
7     ARG_UNUSED(device);
8 
9     /*
10     * Determine the reload value to achieve the configured tick rate.
11     */
12
13    /* systick supports 24-bit H/W counter */
14    __ASSERT(sys_clock_hw_cycles_per_tick <= (1 << 24),
15         "sys_clock_hw_cycles_per_tick too large");
16    sysTickReloadSet(sys_clock_hw_cycles_per_tick - 1);
17
18    NVIC_SetPriority(SysTick_IRQn, _IRQ_PRIO_OFFSET);
19
20    SysTick->CTRL = ctrl;
21
22    SysTick->VAL = 0; /* triggers immediate reload of count */
23
24    return 0;
25}

系统时钟不一定要使用systick,像Nordic的SOC用的是硬件RTC作为系统时钟的,只是不过systick是一个通用的时钟。

第16行,参数sys_clock_hw_cycles_per_tick的含义是多少个systick时钟计数产生一个中断,这里CPU时钟为72MHz(systick时钟源来自CPU),系统时钟中断周期为10ms(100Hz,1秒产生100个中断),所以sys_clock_hw_cycles_per_tick = 72000000 / 100 = 720000。sysTickReloadSet()函数定义在zephyr-zephyr-v1.13.0\drivers\timer\cortex_m_systick.c:

1  static ALWAYS_INLINE void sysTickReloadSet(
2      u32_t count /* count from which timer is to count down */
3      )
4  {
5      /*
6       * Write the reload value and clear the current value in preparation
7       * for enabling the timer.
8       * The countflag in the control/status register is also cleared by
9       * this operation.
10      */
11     SysTick->LOAD = count;
12     SysTick->VAL = 0; /* also clears the countflag */
13 }

第11行,设置重装载寄存器。

第12行,将计数值置0,在使能systick后就会马上触发中断。

回到_sys_clock_driver_init()函数,第18行,设置systick的中断优先级,这里_IRQ_PRIO_OFFSET的值为1,因此systick的中断优先级就为1。

第20行,使能systick。

第22行,马上触发systick中断,并自动重装计数值。

接下来看systick中断执行函数_timer_int_handler(),定义在zephyr-zephyr-v1.13.0\drivers\timer\cortex_m_systick.c:

1  void _timer_int_han
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇per-CPU变量 下一篇网络中的NAT模式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目