目录
- 0.源码
- 1. 中断初始化
- 2. 中断回调
- 3 start.S
上篇博文介绍了按键的轮询处理方式,本篇介绍按键的中断方式。
0.源码
GitHub:https://github.com/Kilento/4412NoOS
1. 中断初始化
void interrupt_init(void)
{/* 中断处理:* <1> IRQ模式: 中断irq引脚, 中断GIC* <2> GIC中断:中断号ID* Key2: GPX1_1/XEINT9* (1) Page 752: EINT9 ---> 中断ID: 57* (2) GPX1_1 配置成中断功能: 0xF* (3) GPX1_1 禁止上拉和下拉 PUD[3:2]* (4) EXT_INT41CON[1] : 0x2 ---> 下降沿触发中断falling edge* (5) EXT_INT41_MASK[1]: 0x0 ---> Enables Interrupt* <3> GIC 配置:* (1) ICCICR_CPU0[0] : 0x1048_0000 : 1 ---> enable* (2) ICDDCR: 0x1049_0000 : 1 ---> enable* (3) ICCPMR_CPU0[7:0]: 0x1048_004 : 255屏蔽优先级* ICDIPR_CPU0 偏移57个字节(每个中断占一个字节), 默认0,最高优先级* (4) ICCIAR_CPU0[9:0]: 0x1048_000C: 中断ID* (5) 结束中断* (6) ICDISER_CPU0[57]: Set-Enable Interrupt 1* (7) ICDIPTR_CPU: 选择该中断递送给哪一个CPU** <4> 中断清除* (1) EXT_INT41_PEND[1]: 0* (2) (4) ICCICPR_CPU0* (3) (5) ICCEOIR_CPU0[9:0]: 0x1048_0010: 回写ID给GIC*/printf("interrupt_init\n");/*GPX1_1 - HOME - EXT_INT41[1] - EINT[9] - SPI(25) - ID(57)GPX1_2 - BACK - EXT_INT41[2] - EINT[10] - SPI(26) - ID(58)GPX3_3 - SLEEP - EXT_INT43[3] - EINT[27] - SPI(32) - ID(64)GPX2_0 - VOL- - EXT_INT42[0] - EINT[16] - SPI(32) - ID(64)GPX2_1 - VOL+ - EXT_INT42[1] - EINT[17] - SPI(32) - ID(64)*/ICDDCR = 1; // 使能中断分配器ICDISER1_CPU0 |= 1 << 25; // 57/32 = 1...25// ICDISER1_CPU0 |= 1 << 26; // 58/32 = 1...26// ICDISER2_CPU0 |= 1 << 0; // 64/32 = 2...0// 设置SPI[25]/ID[57]由哪个cpu处理,当前设置为cpu0的irq中断ICDIPTR14_CPU0 |= 1 << 8;ICCPMR_CPU0 = 0xff;ICCICR_CPU0 = 1;return;
}
2. 中断回调
void irq_exception(void)
{int irq_num = 0;int key_id = 0;led_ctrl(0, 0);led_ctrl(1, 1);irq_num = ICCIAR_CPU0 & 0x3ff;printf("%d\n", irq_num);switch (irq_num){case 57:{key_id = KEY_HOME;EXT_INT41_PEND |= (0x1 << 1); // 清GPIO中断标志位put_key_value(key_id);break;}default:{printf("unknown irq number=%d", irq_num);break;}}ICCEOIR_CPU0 = (ICCEOIR_CPU0 & (~0x3FF)) | irq_num; // 清cpu中断标志return;
}
3 start.S
init_stack: /*svc mode stack*/msr cpsr, #0xd3ldr sp, _stack_svc_end/*undef mode stack*/msr cpsr, #0xdbldr sp, _stack_und_end/*abort mode stack*/ msr cpsr,#0xd7ldr sp,_stack_abt_end/*irq mode stack*/ msr cpsr,#0xd2ldr sp, _stack_irq_end/*fiq mode stack*/msr cpsr,#0xd1ldr sp, _stack_fiq_end/*user mode stack, enable FIQ/IRQ*/msr cpsr,#0x10ldr sp, _stack_usr_end/*Call main*/ldr pc, = main /* 使用长加载进行地址跳转,不能再使用 bl 进行跳转 */
b .irq_handler:/* 中断程序执行时,会自动将当前pc指针地址存入 lr 寄存器中 */sub lr,lr,#4 /* 由于 armv7 使用两级流水线,PC 指针地址= 当前执行指令地址 + 8,当前中断处理程序地址 = pc - 4 */stmfd sp!,{r0-r12,lr} /* 将所有寄存器(r0-r12, lr)的值按顺序存储到当前栈顶位置 */bl irq_exception /* 跳转到中断程序 */ldmfd sp!,{r0-r12,pc}^ /* 中断返回程序会从栈中弹出之前存储的所有寄存器的值,并跳转回原来的程序入口地址 */_stack_svc_end: .word stack_svc + 512
_stack_und_end: .word stack_und + 512
_stack_abt_end: .word stack_abt + 512
_stack_irq_end: .word stack_irq + 512
_stack_fiq_end:.word stack_fiq + 512
_stack_usr_end: .word stack_usr + 512.data
stack_svc: .space 512
stack_und:.space 512
stack_abt: .space 512
stack_irq: .space 512
stack_fiq: .space 512stack_usr: .space 512
2024年02月13日
Kilento