概述
进入多核时代后,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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复