ARMv7 GICv2 GenericTimer 实战演练

  • 平台介绍
qemu-system-arm -M virt,secure=on -cpu cortex-a7 -m 32M
  • 中断产生过程
arch_timer -PPI中断-> gic Distributor  -> gic CPU interface --IRQ中断--> CPU
  • gic 版本
gic v1 : GIC-390  : Cortex-A9 MPCore
gic v2 : GIC-400  : Cortex-A7 MPCore
gic v3 : GIC-500/600 :
  • gic 优先级 与 亲和性
part7
part6
各模块的参考手册
  • Generic Timer
ARMv7 ref : P1481
	CNTP_TVAL // PL1 Physical Timer
	CNTP_CTL
  • PPI 中断
cortex-a7 trm P179
	Private Peripheral Interrupts // PPI2
  • GIC 版本
cortex-a7 trm P177
	The integrated GIC is compliant with the version 2.0 of 
	the ARM Generic Interrupt Controller (GIC) Architecture Specification.
  • GIC 基址
ARMv7 ref : P1481
	c15 寄存器
cortex-a7 trm P79
	CBAR : // 基址(是个40bit的数据)需要重新拼接一下
		   // 但如果 PERIPHBASE[39:32] 为 0的话 ,拼接后的结果(即GIC基址)和 CBAR 的值一样
CBAR 为 0x8000000
所以 基址 为 0x8000000

查看设备树,设备树上写的为 reg = <0x00 0x8000000 0x00 0x10000 0x00 0x8010000 0x00 0x10000>; 
即 基地址 为 0x8000000

这两个不知道以哪个为准,反正都是相同的.

  • GIC各模块偏移地址
cortex-a7 trm P178
	我们只需要关注
		0x1000 - 0x1FFF Distributor
		0x2000 - 0x3FFF CPU interface
	但是实际情况为 	基址 + 0x1000  这块内存并不存在

查看设备树,设备树上写的为 reg = <0x00 0x8000000 0x00 0x10000 0x00 0x8010000 0x00 0x10000>; 
即 基地址 为 0x8000000 0x8010000 ,根据我从CBAR读出的值可以判定 如下
	Distributor 	的偏移地址 为 0x00000
	CPU interface	的偏移地址 为 0x10000
  • GIC Distributor 寄存器描述
gic ref P75 // 描述的不完全
	Distributor register map
cortex-a7 trm P181 // 以这个为准
	Distributor register summary

  • GIC CPU interface 寄存器描述
gic ref P76  // 描述的不完全
	CPU interface register map
cortex-a7 trm P188 // 以这个为准
	CPU Interface register summary
代码
  • timer 代码
$ cat arch/arm32/driver/timer.c 
/*************************************************************************
  > File Name: timer.c
  > Author: SuWeishuai
  > Mail: suwsl@foxmail.com
  > Created Time: Wed 27 Apr 2022 04:10:31 PM CST
 ************************************************************************/

#include "platform.h"
#include "reg_ops.h"
#include "pt_regs.h"

#define TIMER_USE_TVAL

int timer_init(void){
#ifdef TIMER_USE_TVAL
    sreg_wr(CNTP_TVAL,TIMER_PERIOD);
#else
    sreg64_wr(CNTP_CVAL,sreg64_rd(CNTPCT)+TIMER_PERIOD);
#endif
    sreg_wr(CNTP_CTL, (1 << 0) | (0 << 1));
    return 0;
}

void timer_handler(unsigned long cause,struct pt_regs *pt_regs){
#ifdef TIMER_USE_TVAL
    sreg_wr(CNTP_TVAL,TIMER_PERIOD);
#else
    sreg64_wr(CNTP_CVAL,sreg64_rd(CNTPCT)+TIMER_PERIOD);
#endif
    return ;
}
  • gic_v2 代码
$ cat arch/arm32/driver/gic_v2.c 
/*************************************************************************
  > File Name: gic_v2.c
  > Author: SuWeishuai
  > Mail: suwsl@foxmail.com
  > Created Time: Thu 28 Apr 2022 04:18:56 PM CST
 ************************************************************************/

#include "platform.h"
#include "reg_ops.h"
#include "gic_v2.h"

gic_v2_dist_t * gic_dist  = 0;
gic_v2_cpu_t  * gic_cpu   = 0;

int gic_v2_init(void){
    int i = 0;
    unsigned cbar = 0;

    cbar =  sreg_rd(CBAR);

    gic_dist = (gic_v2_dist_t *)cbar;
    gic_cpu  = (gic_v2_cpu_t  *)(cbar+0x10000);

#if 0
    // The GICD_IPRIORITYRs provide an 8-bit priority field for each interrupt supported by the GIC.
    for(i = 0 ; i < 32; i++){
        gic_dist->D_IPRIORITYR[i] = 0x5 << 3;
    }
#endif

    // Provides an interrupt priority filter.
    gic_cpu->C_PMR = 0XF8;

#if 0
    // The value of this field controls how the 8-bit interrupt priority field is split into a group priority field
    // 0X2
    // Group priority field : Subpriority field
    // [7:3]                : [2:0]
    // ggggg                : sss
    gic_cpu->C_BPR = 0X2;
#endif


    // The GICD_ISENABLERs provide a Set-enable bit for each interrupt supported by the GIC.
    // Writing 1 to a Set-enable bit enables forwarding of the corresponding interrupt from the
    // Distributor to the CPU interfaces.
    gic_dist->D_ISENABLER[0] = (1 << 29);

    // Enables the forwarding of pending interrupts from the Distributor to the CPU interfaces.
    gic_dist->D_CTLR = 0X1;

    // Enables the signaling of interrupts by the CPU interface to the connected processor
    gic_cpu->C_CTLR = 0X1;

    return 0;
}
名词解释
  • 几个名词
system counter
processor counter
generic timer counter 
其中 system counter 和 generic timer counter 一致 , 以后只说  system counter
其中 processor counter 是 processor 运行的 计数
system counter 的频率 是 1MHZ-50MHZ , 可设置
processor counter 的频率更高,可以达到 2GHZ,即处理器的运行频率

  • system counter 是什么
和power domain类似,clock domain也是不同的,system counter和 processor 工作在不同的clock下,软件修改了CPU的频率也不会影响system counter的工作节奏,从而也不会改变timer的行为。

Notes:System counter提供一个计数,分发到各个timer中。Timer定时器基于System counter计数值,超时后触发一个信号到GIC,超时函数进行处理。考虑到功耗,各CPU专属的Timer、电路可以被单独关闭;而System counter保持运行。

processor   按 时钟 动作
generic  timer       按 时钟 动作

cpu 和 timer的 clock domain  和 power domain 都不一样

有没有一个 寄存器可以显示 processor 的 count 数
为什么 system counter 是 timer 的计数,而不是 processor 的 计数

  • generic timer 的 寄存器
armv7v8中的 CNTFRQ 是 clock 的频率
armv7v8中的 CNTPCT 是 clock 的当前计数值,也叫system counter
  • CNTFRQ
The CNTFRQ register indicates the clock frequency of the system counter.

Programming CNTFRQ does not affect the system clock frequency.
However, on system initialization, CNTFRQ must be correctly 
programmed with the system clock frequency, to make this value
available to software. 


Typically, the system drives the system counter at a fixed frequency and the CNTFRQ register must be programmed
to this value during the system boot process. 

写入 CNTFRQ  不影响 system clock  frequency , 那会影响什么呢?
既然不影响  system clock  frequency , 写入 这个寄存器的目的是什么呢?

riscv 中的 mtimer

我感觉 riscv中的mtimer 可以等价于 generic timer ,都是 必备的,而不是外部的IP

riscv 中的 mcycle/mcycleh 寄存器,在 armv7v8中有没有对应的寄存器
有 , 叫 cycle counter , 也叫 processor counter

mtimer/generic timer 的频率 必然远远低于 mcycle/cycle counter 的计数频率

processor counter在不同的微架构上访问方式不同
	arm11MP :  // https://developer.arm.com/documentation/ddi0360/f/control-coprocessor-cp15/register-descriptions/c15--cycle-counter-register--ccnt-
		MRC p15, 0, <Rd>, c15, c12, 1 ; Read Cycle Counter Register
		MCR p15, 0, <Rd>, c15, c12, 1 ; Write Cycle Counter Register
	
	cortex-M : // https://stackoverflow.com/questions/11530593/cycle-counter-on-arm-cortex-m4-or-m3
		DWT_CYCCNT
		CPU_CYCLES
	
	cortex-A : // https://developer.arm.com/documentation/ddi0601/2022-03/?lang=en
		PMCCNTR_EL0
			// https://aijishu.com/a/1060000000212593
			// https://ilinuxkernel.com/?p=1755
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值