[文章]鸿蒙Harmony系统时钟源码解析

阅读量0
0
0
一.系统时钟初始化1.main函数的各种调用,验证参数
kernelliteos_aplatformmain.c->main()
        kernelliteos_akernelcommonlos_config.c->OsMain()
                kernelliteos_aarcharmarmsrclos_hw_tick.c->OsTickInit()
  1. <span role="presentation"><span class="cm-variable">systemClock</span><span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-comment">//vendor里设置的是50000000</span></span>
  2. <span role="presentation"><span class="cm-variable">tickPerSecond</span><span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-comment">//鸿蒙默认设置的是100</span></span>
  3. <span role="presentation"><span class="cm-variable">LITE_OS_SEC_TEXT_INIT</span> <span class="cm-variable">UINT32</span> <span class="cm-def">OsTickInit</span>(<span class="cm-variable">UINT32</span> <span class="cm-variable">systemClock</span>, <span class="cm-variable">UINT32</span> <span class="cm-variable">tickPerSecond</span>)</span>
  4. <span role="presentation">{    <span class="cm-comment">//只是验证了下传入的这两个参数,并未使用</span></span>
  5. <span role="presentation">    <span class="cm-variable">HalClockInit</span>();</span>
  6. <span role="presentation">    <span class="cm-keyword">return</span> <span class="cm-variable">LOS_OK</span>;</span>
  7. <span role="presentation">}</span>
复制代码
2.先获取当前时钟频率,注册中断
kernelliteos_aplatformhwarmtimerarm_genericarm_generic_timer.c
  1. <span role="presentation"><span class="cm-variable">OS_TICK_INT_NUM</span><span class="cm-comment">//中断号,在vendor******boardincludeasmhal_platform_ints.h下定义,查手册确定</span></span>
  2. <span role="presentation"><span class="cm-variable">MIN_INTERRUPT_PRIORITY</span><span class="cm-comment">//优先级</span></span>
  3. <span role="presentation"><span class="cm-variable">OsTickEntry</span><span class="cm-comment">//中断函数</span></span>
  4. <span role="presentation"><span class="cm-variable">LITE_OS_SEC_TEXT_INIT</span> <span class="cm-variable">VOID</span> <span class="cm-def">HalClockInit</span>(<span class="cm-variable">VOID</span>)</span>
  5. <span role="presentation">{   ...</span>
  6. <span role="presentation">    <span class="cm-variable">g_sysClock</span> <span class="cm-operator">=</span> <span class="cm-variable">HalClockFreqRead</span>(); <span class="cm-comment">//先获取当前时钟频率</span></span>
  7. <span role="presentation">    </span>
  8. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-comment">//调用LOS_HwiCreate函数新建中断,系统中断由它注册</span></span>
  9. <span role="presentation">    <span class="cm-variable">ret</span> <span class="cm-operator">=</span> <span class="cm-variable">LOS_HwiCreate</span>(<span class="cm-variable">OS_TICK_INT_NUM</span>, <span class="cm-variable">MIN_INTERRUPT_PRIORITY</span>, <span class="cm-number">0</span>, <span class="cm-variable">OsTickEntry</span>, <span class="cm-number">0</span>);<span class="cm-comment">//参数1:中断号、参数4:执行函数</span></span>
  10. <span role="presentation">    <span class="cm-comment">//这个函数就不深入了,大体就是将中断号好和对应的执行函数放到一个数组</span></span>
  11. <span role="presentation">    <span class="cm-comment">//比如这里就是,当发生OS_TICK_INT_NUM这个中断时,执行OsTickEntry()函数</span></span>
  12. <span role="presentation">    ...</span>
  13. <span role="presentation">}</span>
复制代码
二.时钟中断的执行函数OsTickEntry()
kernelliteos_aplatformhwarmtimerarm_genericarm_generic_timer.c
不过此时这是注册了这个函数,时钟并未启动,得执行了(三.启动时钟)之后才会调用这个函数
  1. <span role="presentation"><span class="cm-variable">LITE_OS_SEC_TEXT</span> <span class="cm-variable">VOID</span> <span class="cm-def">OsTickEntry</span>(<span class="cm-variable">VOID</span>)</span>
  2. <span role="presentation">{</span>
  3. <span role="presentation">    <span class="cm-variable">TimerCtlWrite</span>(<span class="cm-number">0</span>);</span>
  4. <span role="presentation">    <span class="cm-variable">OsTickHandler</span>();</span>
  5. <span role="presentation">    <span class="cm-variable">TimerCvalWrite</span>(<span class="cm-variable">TimerCvalRead</span>() <span class="cm-operator">+</span> <span class="cm-variable">OS_CYCLE_PER_TICK</span>);</span>
  6. <span role="presentation">    <span class="cm-variable">TimerCtlWrite</span>(<span class="cm-number">1</span>);</span>
  7. <span role="presentation">    <span class="cm-comment">//使用最后一个cval生成下一个tick的时间是绝对和准确的。不要使用tval来驱动一般时间,在这种情况下tick会变慢。</span></span>
  8. <span role="presentation">}</span>
复制代码
三.启动时钟
main() => OsStart(VOID) => OsTickStart() => HalClockStart(VOID)
kernelliteos_aplatformhwarmtimerarm_genericarm_generic_timer.c => HalClockStart(VOID)
  1. <span role="presentation"><span class="cm-comment">//树莓派2b没有GIC所以这个函数要爆改</span></span>
  2. <span role="presentation"><span class="cm-variable">LITE_OS_SEC_TEXT_INIT</span> <span class="cm-variable">VOID</span> <span class="cm-def">HalClockStart</span>(<span class="cm-variable">VOID</span>)</span>
  3. <span role="presentation">{</span>
  4. <span role="presentation">    <span class="cm-variable">HalIrqUnmask</span>(<span class="cm-variable">OS_TICK_INT_NUM</span>);  <span class="cm-comment">//wendor里定义的 OS_TICK_INT_NUM = 29</span></span>
  5. <span role="presentation">    <span class="cm-variable">TimerCtlWrite</span>(<span class="cm-number">0</span>);</span>
  6. <span role="presentation">    <span class="cm-variable">TimerTvalWrite</span>(<span class="cm-variable">OS_CYCLE_PER_TICK</span>);</span>
  7. <span role="presentation">    <span class="cm-variable">TimerCtlWrite</span>(<span class="cm-number">1</span>);</span>
  8. <span role="presentation">}</span>
复制代码
1. HalIrqUnmask; //接收中断(通过设置寄存器,允许CPU响应该中断)
  1. <span role="presentation">HalIrqUnmask(OS_TICK_INT_NUM);</span>
  2. <span role="presentation">HalIrqUnmask(29);</span>
  3. <span role="presentation">GIC_REG_32(GICD_ISENABLER(29 >> 5)) = 1U << (29 % 32);</span>
  4. <span role="presentation"><span cm-text="">​</span></span>
  5. <span role="presentation">(GICD_ISENABLER(29 >> 5))拆开</span>
  6. <span role="presentation">GIC_REG_32(GICD_OFFSET + 0x100 + (29 >> 5) * 4) = 1U << (29 % 32);/* 中断使能 Registers */</span>
  7. <span role="presentation"><span cm-text="">​</span></span>
  8. <span role="presentation">GIC_REG_32拆开,(29 % 32)=1D</span>
  9. <span role="presentation">GIC_BASE_ADDR + (GICD_OFFSET + 0x100 + (29 >> 5) * 4) = 1U << (29 % 32)</span>
  10. <span role="presentation"><span cm-text="">​</span></span>
  11. <span role="presentation">#define GIC_BASE_ADDR             IO_DEVICE_ADDR(0x3F00A100)</span>
  12. <span role="presentation">#define GICD_OFFSET               0x1000     /* interrupt distributor offset */</span>
复制代码
2.TimerCtlWrite(0); //关闭Timer
  1. <p cid="n55" mdtype="paragraph" class="md-end-block md-p">WRITE_TIMER_REG32(TIMER_REG_CTL, 0);</p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n57" mdtype="fences"><span role="presentation">ARM_SYSREG_WRITE(TIMER_REG_CTL, 0)</span>
  2. <span role="presentation">ARM_SYSREG_WRITE(TIMER_REG(_CTL), 0)</span>
  3. <span role="presentation">ARM_SYSREG_WRITE(CP15_REG(c14, 0, c2, 1)), 0)</span>
  4. <span role="presentation">"mcr " (CP15_REG(c14, 0, c2, 1) :: "r" (val)</span>
  5. <span role="presentation">反汇编</span>
  6. <span role="presentation">r8 0</span>
  7. <span role="presentation">mcr<span class="cm-tab" role="presentation" cm-text="        "> </span>p15, #0, r8, c14, c2, #1<span class="cm-tab" role="presentation" cm-text="        ">    </span>CNTP_CTL,PL1物理定时器控制寄存器</span></pre>
复制代码
3.TimerTvalWrite(OS_CYCLE_PER_TICK); //设置Tval
  1. <span role="presentation">反汇编</span>
  2. <span role="presentation">r0 192000</span>
  3. <span role="presentation">mcr<span class="cm-tab" role="presentation" cm-text="        "> </span>p15, #0, r0, c14, c2, #0<span class="cm-tab" role="presentation" cm-text="        ">    </span>CNTP_TVAL,PL1物理时间值寄存器</span>
复制代码
4.TimerCtlWrite(1);        //再开启Timer
  1. <span role="presentation">反汇编</span>
  2. <span role="presentation">r5 1</span>
  3. <span role="presentation">mcr<span class="cm-tab" role="presentation" cm-text="        "> </span>p15, #0, r5, c14, c2, #1<span class="cm-tab" role="presentation" cm-text="        ">    </span>CNTP_CTL,PL1物理定时器控制寄存器</span>
复制代码
代码移植
Z:brightharmony-100askkernelliteos_aplatformhwarminterruptgicgic_v2.c
  1. <span role="presentation"><span class="cm-variable">VOID</span> <span class="cm-def">HalIrqUnmask</span>(<span class="cm-variable">UINT32</span> <span class="cm-variable">vector</span>)</span>
  2. <span role="presentation">{</span>
  3. <span role="presentation">    <span class="cm-keyword">if</span> ((<span class="cm-variable">vector</span> <span class="cm-operator">></span> <span class="cm-variable">OS_USER_HWI_MAX</span>) <span class="cm-operator">||</span> (<span class="cm-variable">vector</span> <span class="cm-operator"><</span> <span class="cm-variable">OS_USER_HWI_MIN</span>)) {</span>
  4. <span role="presentation">        <span class="cm-keyword">return</span>;</span>
  5. <span role="presentation">    }</span>
  6. <span role="presentation">    <span class="cm-comment">//GIC_REG_32(GICD_ISENABLER(vector >> 5)) = 1U << (vector % 32);  //替换</span></span>
  7. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-operator">*</span>(<span class="cm-keyword">volatile</span> <span class="cm-variable">UINT32</span> <span class="cm-operator">*</span>)((<span class="cm-variable">UINTPTR</span>)<span class="cm-variable">IO_DEVICE_ADDR</span>(<span class="cm-number">0x3F00B218</span>)) <span class="cm-operator">=</span> <span class="cm-number">1</span>; <span class="cm-comment">//使能ARM Timer IRQ<span class="cm-tab" role="presentation" cm-text="        ">    </span></span></span>
  8. <span role="presentation"><span cm-text="">​</span></span>
  9. <span role="presentation">}</span>
复制代码
Z:brightharmony-100askkernelliteos_aplatformhwarmtimerarm_genericarm_generic_timer.c
  1. <span role="presentation"><span class="cm-variable">STATIC_INLINE</span> <span class="cm-variable">VOID</span> <span class="cm-def">TimerCtlWrite</span>(<span class="cm-variable">UINT32</span> <span class="cm-variable">cntpCtl</span>)</span>
  2. <span role="presentation">{</span>
  3. <span role="presentation">    <span class="cm-comment">//WRITE_TIMER_REG32(TIMER_REG_CTL, cntpCtl);//替换</span></span>
  4. <span role="presentation">    <span class="cm-keyword">if</span>(<span class="cm-variable">cntpCtl</span> <span class="cm-operator">==</span> <span class="cm-number">0</span>){</span>
  5. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-operator">*</span>(<span class="cm-keyword">volatile</span> <span class="cm-variable">UINT32</span> <span class="cm-operator">*</span>)((<span class="cm-variable">UINTPTR</span>)<span class="cm-variable">IO_DEVICE_ADDR</span>(<span class="cm-number">0x3F00B408</span>)) <span class="cm-operator">=</span> <span class="cm-number">0x003E0000</span>;</span>
  6. <span role="presentation">    <span class="cm-tab" role="presentation" cm-text="        ">    </span>}</span>
  7. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-keyword">else</span></span>
  8. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  9. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-operator">*</span>(<span class="cm-keyword">volatile</span> <span class="cm-variable">UINT32</span> <span class="cm-operator">*</span>)((<span class="cm-variable">UINTPTR</span>)<span class="cm-variable">IO_DEVICE_ADDR</span>(<span class="cm-number">0x3F00B408</span>)) <span class="cm-operator">=</span> <span class="cm-number">0x003E00A2</span>;</span>
  10. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>}</span>
  11. <span role="presentation">}</span>
复制代码
Z:brightharmony-100askkernelliteos_aplatformhwarmtimerarm_genericarm_generic_timer.c
  1. <span role="presentation"><span class="cm-variable">STATIC_INLINE</span> <span class="cm-variable">VOID</span> <span class="cm-def">TimerTvalWrite</span>(<span class="cm-variable">UINT32</span> <span class="cm-variable">tval</span>)</span>
  2. <span role="presentation">{</span>
  3. <span role="presentation">    <span class="cm-comment">//WRITE_TIMER_REG32(TIMER_REG_TVAL, tval);//替换</span></span>
  4. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-operator">*</span>(<span class="cm-keyword">volatile</span> <span class="cm-variable">UINT32</span> <span class="cm-operator">*</span>)((<span class="cm-variable">UINTPTR</span>)<span class="cm-variable">IO_DEVICE_ADDR</span>(<span class="cm-number">0x3F00B400</span>)) <span class="cm-operator">=</span> <span class="cm-variable">tval</span>;  <span class="cm-comment">//设置倒计时时间,鸿蒙是10ms<span class="cm-tab" role="presentation" cm-text="        ">    </span></span></span>
  5. <span role="presentation">}</span>
复制代码



回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友