
想了解更多内容,鸿蒙请访问:
和华为官方合作共建的内核鸿蒙技术社区
https://harmonyos.51cto.com
关于中断部分系列篇将用三篇详细说明整个过程.
● 中断概念篇 中断概念很多,比如中断控制器,中断源,中断向量,中断共享,中断处理程序等等.本篇做一次整理.先了解透概念才好理解中断过程.用海公公打比方说明白中断各个概念.可前往鸿蒙内核源码分析查看.
● 中断管理篇(本篇) 从中断初始化HalIrqInit开始,到注册中断的LOS_HwiCreate函数,到消费中断函数的 HalIrqHandler,剖析鸿蒙内核实现中断的过程,很像设计模式中的观察者模式.
● 中断切换篇 用自下而上的方式,从中断源头纯汇编代码往上跟踪代码细节.说清楚保存和恢复中断现场TaskIrqContext过程.可前往鸿蒙内核源码分析查看.
编译开关
系列篇编译平台为 hi3516dv300,整个工程可前往查看. 预编译处理过程会自动生成编译开关 menuconfig.h ,供编译阶段选择编译,可前往查看.
//.... #define LOSCFG_ARCH_ARM_VER "armv7-a" #define LOSCFG_ARCH_CPU "cortex-a7" #define LOSCFG_PLATFORM "hi3516dv300" #define LOSCFG_PLATFORM_BSP_GIC_V2 1 #define LOSCFG_PLATFORM_ROOTFS 1 #define LOSCFG_KERNEL_CPPSUPPORT 1 #define LOSCFG_HW_RANDOM_ENABLE 1 #define LOSCFG_ARCH_CORTEX_A7 1 #define LOSCFG_DRIVERS_HDF_PLATFORM_RTC 1 #define LOSCFG_DRIVERS_HDF_PLATFORM_UART 1 中断初始化
hi3516dv300 中断控制器选择了 LOSCFG_PLATFORM_BSP_GIC_V2 ,对应代码为 gic_v2.c GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器. 看这种代码因为涉及硬件部分,需要对照ARM中断控制器 gic_v2.pdf文档看.可前往地址查看.
//硬件中断初始化 VOID HalIrqInit(VOID) { UINT32 i; /* set externel interrupts to be level triggered, active low. */ //将外部中断设置为电平触发,低电平激活 for (i = 32; i < OS_HWI_MAX_NUM; i += 16) { GIC_REG_32(GICD_ICFGR(i / 16)) = 0; } /* set externel interrupts to CPU 0 */ //将外部中断设置为CPU 0 for (i = 32; i < OS_HWI_MAX_NUM; i += 4) { GIC_REG_32(GICD_ITARGETSR(i / 4)) = 0x01010101; } /* set priority on all interrupts */ //设置所有中断的源码优先级 for (i = 0; i < OS_HWI_MAX_NUM; i += 4) { GIC_REG_32(GICD_IPRIORITYR(i / 4)) = GICD_INT_DEF_PRI_X4; } /* disable all interrupts. */ //禁用所有中断。 for (i = 0; i < OS_HWI_MAX_NUM; i += 32) { GIC_REG_32(GICD_ICENABLER(i / 32)) = ~0; } HalIrqInitPercpu();//初始化当前CPU中断信息 /* enable gic distributor control */ GIC_REG_32(GICD_CTLR) = 1; //使能分发中断寄存器,分析该寄存器作用是允许给CPU发送中断信号 #if (LOSCFG_KERNEL_SMP == YES) /* register inter-processor interrupt *///注册核间中断,啥意思?就是CPU各核直接可以发送中断信号 //处理器间中断允许一个CPU向系统其他的CPU发送中断信号,处理器间中断(IPI)不是中断中断通过IRQ线传输的,而是管理作为信号直接放在连接所有CPU本地APIC的总线上。 LOS_HwiCreate(LOS_MP_IPI_WAKEUP,篇硬 0xa0, 0, OsMpWakeHandler, 0);//注册唤醒CPU的云南idc服务商中断处理函数 LOS_HwiCreate(LOS_MP_IPI_SCHEDULE, 0xa0, 0, OsMpScheduleHandler, 0);//注册调度CPU的中断处理函数 LOS_HwiCreate(LOS_MP_IPI_HALT, 0xa0, 0, OsMpScheduleHandler, 0);//注册停止CPU的中断处理函数 #endif } //给每个CPU core初始化硬件中断 VOID HalIrqInitPercpu(VOID) { /* unmask interrupts */ //取消中断屏蔽 GIC_REG_32(GICC_PMR) = 0xFF; /* enable gic cpu interface */ //启用gic cpu接口 GIC_REG_32(GICC_CTLR) = 1; } 解读
● 上来四个循环,是对中断控制器寄存器组的初始化,也就是驱动程序,驱动程序是配置硬件寄存器的过程.寄存器分通用和专用寄存器.图为 gic_v2 的寄存器功能 ,这里对照代码和datasheet重点说下中断配置寄存器

● 以下是GICD_ICFGRn的介绍
The GICD_ICFGRs provide a 2-bit Int_config field for each interrupt supported by the GIC. This field identifies whether the corresponding interrupt is edge-triggered or level-sensitive GICD_ICFGRs为GIC支持的每个中断提供一个2位配置字段。此字段标识相应的现观中断是边缘触发的还是电平触发的 ● GIC-v2支持三种类型的中断
◊ PPI:私有外设中断(Private Peripheral Interrupt),是模式每个CPU私有的中断。最多支持16个PPI中断,服务器托管鸿蒙硬件中断号从ID16~ID31。内核PPI通常会送达到指定的源码CPU上,应用场景有CPU本地时钟。分析
◊ SPI:公用外设中断(Shared Peripheral Interrupt),中断中断最多可以支持988个外设中断,管理硬件中断号从ID32~ID1019。
◊ SGI:软件触发中断(Software Generated Interrupt)通常用于多核间通讯,最多支持16个SGI中断,硬件中断号从ID0~ID15。SGI通常在内核中被用作 IPI 中断(inter-processor interrupts),并会送达到系统指定的CPU上,函数的最后就注册了三个核间中断的函数.
typedef enum { //核间中断 LOS_MP_IPI_WAKEUP, //唤醒CPU LOS_MP_IPI_SCHEDULE,//调度CPU LOS_MP_IPI_HALT, //停止CPU } MP_IPI_TYPE; 中断相关的结构体
size_t g_intCount[LOSCFG_KERNEL_CORE_NUM] = { 0};//记录每个CPUcore的中断数量 HwiHandleForm g_hwiForm[OS_HWI_MAX_NUM];//中断注册表 @note_why 用 form 来表示?有种写 HTML的感觉 :P STATIC CHAR *g_hwiFormName[OS_HWI_MAX_NUM] = { 0};//记录每个硬中断的名称 STATIC UINT32 g_hwiFormCnt[OS_HWI_MAX_NUM] = { 0};//记录每个硬中断的总数量 STATIC UINT32 g_curIrqNum = 0; //记录当前中断号 typedef VOID (*HWI_PROC_FUNC)(VOID); //中断函数指针 typedef struct tagHwiHandleForm { HWI_PROC_FUNC pfnHook; //中断处理函数 HWI_ARG_T uwParam; //中断处理函数参数 struct tagHwiHandleForm *pstNext; //节点,指向下一个中断,用于共享中断的情况 } HwiHandleForm; typedef struct tagIrqParam { //中断参数 int swIrq; // 软件中断 VOID *pDevId; // 设备ID const CHAR *pName; //名称 } HwiIrqParam; 注册硬中断
/