当前位置:首页 > 应用开发

鸿蒙内核源码分析(中断管理篇) | 硬中断的实现<>观察者模式

想了解更多内容,鸿蒙请访问:

和华为官方合作共建的内核鸿蒙技术社区

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; 

注册硬中断

/

分享到:

滇ICP备2023006006号-16