①、启动文件 start.s
需要添加一级中断向量表和中断处理函数的框架两部分的内容。
一级中断向量表如下:
3 _start: 4 ldr pc, =Reset_Handler /* 复位中断 */ 5 ldr pc, =Undefined_Handler /* 未定义指令中断 */ 6 ldr pc, =SVC_Handler /* SVC(Supervisor)中断 */ 7 ldr pc, =PrefAbort_Handler /* 预取终止中断 */ 8 ldr pc, =DataAbort_Handler /* 数据终止中断 */ 9 ldr pc, =NotUsed_Handler /* 未使用中断 */ 10 ldr pc, =IRQ_Handler /* IRQ中断 */ 11 ldr pc, =FIQ_Handler /* FIQ(快速中断)未定义中断 */
中断处理函数的框架(以SVC_Handler 为例)如下:
22 /* SVC中断 */ 23 SVC_Handler: 24 ldr r0, =SVC_Handler 25 bx r0
其中 ,进入C语言环境需要 Reset_Handler,中断实验用到了 IRQ_Handler,这两个处理函数有所不同。
Reset_Handler 是 start.s 中要进行的第一个程序,主要用于关闭 I/D Cache,[设置中断向量表偏移],设置堆栈指针,[使能IRQ中断],跳转到 main 函数。(包含方括号的为可选)。
IRQ_Handler 将程序跳转到 system_irqhandler() 函数中(该函数在bsp_int.c由用户中定义),并带一个参数,用于表示是当前的 IRQ 中断号(从 CP15 的C15保存当前中断号, CP15 的结构体在 core_ca7.h 中定义)。
另外,中断号由 NXP 官方在文件 MCIMX6Y2C.h 中定义,范围0~159共计160个,包含了 imx6ul 所有的中断。形如:
3 typedef enum IRQn { 4 /* Auxiliary constants */ 5 NotAvail_IRQn = -128, 6 7 /* Core interrupts */ 8 Software0_IRQn = 0, 9 Software1_IRQn = 1, ................................... /* Device specific interrupts */ 33 IOMUXC_IRQn = 32, 34 DAP_IRQn = 33, 35 SDMA_IRQn = 34, .................................... 157 PMU_IRQ2_IRQn = 159 } IRQn_Type;
这些中断可分为:
- ID0~ID15:这 16个 ID分配给 SGI。(软件中断,由软件触发的中断)
- ID16~ID31:这 16个 ID分配给 PPI。(私有中断,需要指定核心的中断)
- ID32~ID159:这 128个 ID分配给 SPI。(共享中断,所有核心都共享所有外部中断(IRQ)中断都属于 IRQ 中断。
②、中断驱动文件:bsp_int.c、bsp_int.h
在该文件中,设置二级中断向量函数表,承接上文 start.s IRQ中断中跳转的 system_irqhandler() 。
IRQ_Handler 将程序跳转到 system_irqhandler() 函数。
该函数内容如下:
68 void system_irqhandler(unsigned int giccIar) 69 { 70 71 uint32_t intNum = giccIar & 0x3FFUL; 72 73 /* 检查中断号是否符合要求 */ 74 if ((intNum == 1020) || (intNum >= NUMBER_OF_INT_VECTORS)) 75 { 76 return; 77 } 78 79 irqNesting++; /* 中断嵌套计数器加一 */ 80 81 /* 根据传递进来的中断号,在irqTable中调用确定的中断服务函数*/ 82 irqTable[intNum].irqHandler(intNum, irqTable[intNum].userParam); 83 84 irqNesting--; /* 中断执行完成,中断嵌套寄存器减一 */ 85 86 }
在该函数体中,用到了中断函数向量表
irqTable[intNum]
因此应该在 bsp_int.h 中定义相关结构体:
typedef void (*system_irq_handler_t) (unsigned int giccIar, void *param);
19 typedef struct _sys_irq_handle 20 { 21 system_irq_handler_t irqHandler; /* 中断处理函数 */ 22 void *userParam; /* 中断处理函数参数 */ 23 } sys_irq_handle_t;
然后在 bsp_int.c 中定义一个以上面结构体为单元的数组:
static sys_irq_handle_t irqTable[NUMBER_OF_INT_VECTORS];
③、使能中断、设置中断模式(边沿触发类型)函数:bsp_gpio.c
主要编写3个函数:
gpio_intconfig() 用于配置中断相关的设置(边沿触发类型)
gpio_enableint() 用于使能中断
gpio_clearintflags() 用于中断标志位清除函数。
gpio_intconfig() 如下:
/*
73 * @description : 设置GPIO的中断配置功能
74 * @param - base : 要配置的IO所在的GPIO组。
75 * @param - pin : 要配置的GPIO脚号。
76 * @param – pinInterruptMode: 中断模式,参考gpio_interrupt_mode_t
78 */
void gpio_intconfig(GPIO_Type* base, unsigned int pin, gpio_interrupt_mode_t pin_int_mode)
其中的中断模式结构体形如:
gpio_enableint()和 gpio_clearintflags() 如下:
125 void gpio_enableint(GPIO_Type* base, unsigned int pin) 126 { 127 base->IMR |= (1 << pin); 128 }
147 void gpio_clearintflags(GPIO_Type* base, unsigned int pin) 148 { 149 base->ISR |= (1 << pin); 150 }
④、用户中断函数文件:bsp_exti.c、bsp_exti.h
这部分有两个任务:
1. 编写用户中断函数 gpio1_io18_irqhandler(),
2. 在函数向量表中注册 gpio1_io18_irqhandler(),使其相应的中断号相互匹配。
内容如下:
该函数名应该在 bsp_int.c 中定义的
static sys_irq_handle_t irqTable[NUMBER_OF_INT_VECTORS];
的对应的第GPIO1_Combined_16_31_IRQn 个中断服务函数向量相同。
标签:函数,中断,步骤,int,Handler,IRQn,编写,gpio,imx6ul From: https://www.cnblogs.com/FBsharl/p/17328375.html