我是靠谱客的博主 甜甜柠檬,最近开发中收集的这篇文章主要介绍OpenHarmony(4) —— system counter,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

    进入多核时代后,ARM公司提供了timer的硬件设计,集成在了自己的多核结构中。例如:在Cortex A15 MPcore的硬件体系结构中有一个HW block叫做Generic Timer(该硬件取代了A9中的global timer、private timer的功能),为系统提供了计时以及触发timer event的功能。

    ARM generic timer的硬件block主要是SOC上的System counter(多个process共享,用来记录时间的流逝)以及附着在各个processor上的Timer(用于触发timer event)组成,其他的generic timer的硬件电路主要是用来进行交流generic time event的。例如各个processor中的timer和system counter外设进行交互,各个processor中的timer进行信息交互。System counter的功能很简单,就是计算输入时钟已经过了多少个clock,开始的时候是0,每一个clock,System counter会加一。System counter的counter value需要分发到各个timer中,也就是说,从各个timer的角度看,system counter value应该是一致的。Timer其实就是定时器,它可以定义一段指定的时间,当时间到了,就会assert一个外部的输出信号(可以输出到GIC,作为一个interrupt source)。

    除了基本的计时功能,system count还提供了event stream的功能。我们知道,ARMv7的处理器提供了wait for event的机制,该机制允许processor进入low power state并等待event的到来。这个event可能是来自另外的process的send event指令,也可能是外部HW block产生的event,比如来自system counter的wake-up event。

选自《Linux时间子系统之(十七):ARM generic timer驱动代码分析》

 

代码仓:https://codechina.csdn.net/fu851523125/rtos

main()

{

HalClockFreqWrite(OS_SYS_CLOCK);

。。。

OsMain() {

。。。

ret = OsTickInit(g_sysClock, LOSCFG_BASE_CORE_TICK_PER_SECOND) {

HalClockInit(){

    g_sysClock = HalClockFreqRead();
    ret = LOS_HwiCreate(OS_TICK_INT_NUM, MIN_INTERRUPT_PRIORITY, 0, OsTickEntry, 0);
    if (ret != LOS_OK) {
        PRINT_ERR("%s, %d create tick irq failed, ret:0x%xn", __FUNCTION__, __LINE__, ret);
    }

}

}

。。。

}

。。。


    OsStart() {

         OsTickStart() {

            HalClockStart() {

                HalIrqUnmask(OS_TICK_INT_NUM);

                /* triggle the first tick */
                TimerCtlWrite(0);
                TimerTvalWrite(OS_CYCLE_PER_TICK);
                TimerCtlWrite(1);

            }

         }

        。。。

    }

    while (1) {
        __asm volatile("wfi");
    }

}

 

    测试:

    ARCH_ClockStart() {

        /* set smp system counter freq */
        WRITE_TIMER_REG32(TIMER_REG_CNTFRQ, OS_SYS_CLOCK);

        WRITE_TIMER_REG32(TIMER_REG_CTL, 0);
        WRITE_TIMER_REG32(TIMER_REG_TVAL, 0);
        WRITE_TIMER_REG64(TIMER_REG_CVAL, 0);
        WRITE_TIMER_REG32(TIMER_REG_CTL, 1);

    }
    
    ret = RTOS_HAL_HwiCreate(OS_TICK_INT_NUM, OS_TickHandler, OS_NULL) {

        。。。

        ARCH_IrqUnmask(no);

        。。。

    }
    if (ret != OS_ERR_NOERR) {
        EPRINTK_ERR("create HWI os tick irq failed, ret:0x%08Xn", ret);
        RTOS_Hang();
    }

    eprintk("CPU#%u: releasing %u secondary cores ...n", cpuId, CORE_NUM - 1);
    //ARCH_ReleaseSecondaryCores();
    /* wait until all APs are ready */
    //while (RTOS_ATOMIC_Read(&cpus) < CORE_NUM) {
    //    ARCH_WFE();
    //}

    //OS_Start();

    while(1) {
        uss = ARCH_ClockGetUs();

        s = uss / 1000000;
        m = s / 60;
        h = m / 60;
        m = m % 60;
        s = s % 60;

        uss = uss % 1000000;

        ms = uss / 1000;
        us = uss % 1000;
        
        eprintk("rCPU#%u: %u:%02u:%02u.%03u.%03u WFI",
                cpuId, h, m, s, ms, us);
        ARCH_WFI();
    }

    呈现时钟效果

    CPU#0: 0:08:35.210.000 WFI

 

但是呢,中断没有,一直在找原因,为什么呢没有中断产生,

然后各种找,各种想,某一刻看到

/* arch/hw.S */
os_base_t ARCH_HW_InterruptDisable(void);
void ARCH_HW_InterruptEnable(os_base_t level);

ARCH_HW_InterruptDisable()在一开始执行了,那就要调用ARCH_HW_InterruptEnable()?

一试,还真可以了。

修改,

static void OS_TickHandler(void *param)
{
    u32 cpuId = ARCH_CurCpuId();
    u32 intSave;

    ARCH_ClockStop();

    //TICK_LOCK(intSave);
    ++gTickCount[cpuId];
    eprintk("CPU#%u: tick %un", cpuId, gTickCount[cpuId]);
    //TICK_UNLOCK(intSave);

    //OsTimesliceCheck();
    //OsTaskScan(); /* task timeout scan */
    //OsSwtmrScan();

    ARCH_ClockContinue();
}

void RTOS_Main(os_base_t osMemStart)
{
    s32 ret = 0;
    //u32 cpuId = ARCH_CurCpuId();

    ARCH_HW_InterruptDisable();

    RTOS_HAL_Init();

    eprintk("nRTOS SMP %s*%d [v%d.%d.%d %s %s]n",
            ARCH_GetCpuInfo(), CORE_NUM, 
            KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH,
            __DATE__, __TIME__);

    RTOS_MEM_Init(osMemStart, KERNEL_VADDR_SIZE - (osMemStart - KERNEL_VADDR_BASE));

    ARCH_ClockInit();
    
    ret = RTOS_HAL_HwiCreate(OS_TICK_INT_NUM, OS_TickHandler, OS_NULL);
    if (ret != OS_ERR_NOERR) {
        EPRINTK_ERR("create HWI os tick irq failed, ret:0x%08Xn", ret);
        RTOS_Hang();
    }

    ARCH_ClockStart(OS_TICK_INT_NUM);

    //eprintk("CPU#%u: releasing %u secondary cores ...n", cpuId, CORE_NUM - 1);
    //ARCH_ReleaseSecondaryCores();
    /* wait until all APs are ready */
    //while (RTOS_ATOMIC_Read(&cpus) < CORE_NUM) {
    //    ARCH_WFE();
    //}

    //OS_Start();

    while(1) {
        ARCH_WFI();
    }
}
 

运行,

hisilicon # go 0x80000000
## Starting application at 0x80000000 ...

RTOS SMP Cortex-A7*2 [v0.1.0 Oct  4 2020 17:01:51]
[DBG]{ARCH_IrqUnmask() L335} enable irq 29
CPU#0: tick 1
CPU#0: tick 2
CPU#0: tick 3
CPU#0: tick 4
CPU#0: tick 5
CPU#0: tick 6
CPU#0: tick 7
CPU#0: tick 8
CPU#0: tick 9
CPU#0: tick 10
CPU#0: tick 11
CPU#0: tick 12
CPU#0: tick 13
CPU#0: tick 14
CPU#0: tick 15
CPU#0: tick 16
CPU#0: tick 17
CPU#0: tick 18
CPU#0: tick 19
CPU#0: tick 20

最后

以上就是甜甜柠檬为你收集整理的OpenHarmony(4) —— system counter的全部内容,希望文章能够帮你解决OpenHarmony(4) —— system counter所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部