过五关斩六将
GPX1CON
GPX1CON[1] [7:4] RW 0xF = WAKEUP_INT1[1] //设为中断模式
EXT_INT41CON
EXT_INT41_CON[1] [6:4]: 0x2 = Triggers Falling edge //下降沿触发中断
EXT_INT41_MASK
EXT_INT41_MASK[1] [1]: 0x0 = Enables Interrupt //使能中断,可以让中断发生
找到中断控制章节,查看简介如下:
翻译:
9 中断控制器
9.1 概述
通用中断控制器(GIC)是支持和管理系统中中断的集中资源。
GIC提供:
用于管理一个或多个处理器的中断源、中断行为和中断路由的寄存器。
ARM 架构安全扩展:
从硬件(外设)中断源启用、禁用和产生处理器中断。
生成软件中断:
中断屏蔽和优先级排序
GIC将系统级断言的中断,向每个连接的处理器发送相应的信号。
当GIC实现安全扩展时,它可以向连接的处理器实现两个中断请求。
架构将这些请求标识为IRQ和FIQ。
9.1.1 功能
GIC的特点是:1.
支持三种中断类型。
软件生成中断(SGI)。
私有外设中断(PPI)
共享外设中断(SPI)
可编程的中断,使你能够设置中断的:
中断的安全状态。
中断的优先级别。
中断的启用或禁用。
接收中断的处理器。
查看示例代码(一般由厂家提供)
示例代码: ICDISER1_CPU0 = ICDISER1_CPU0 | (1<<25);
ICDISER1 //使能当前中断
Set-enable bits [31:0]: 25 1-enable
ICDDCR //全局使能GIC,让所有中断都可以通过GIC到达CPU接口
Enable [0]: 1 = GIC monitors the peripheral interrupt signals and forwards pending interrupts to the CPU interfaces.
ICCPMR_CPU0 //设置优先级的门槛,当前发生的中断的优先级高于这个门槛才能通过
Priority [7:0]: 0xff //0xff表示优先级最低,所有的中断都可以通过
全局使能中断,所有中断都可以通过CPU接口到达处理器
ICCICR_CPU0 // Global enable for signaling of interrupts by the CPU Interface to the connected processors.
Enable [0]:1 = Enables signaling of interrupts
ICDIPTR14 //将57号中断交给CPU0来处理
CPU targets, byte offset 1 [15:8]; 0x1
注:具体含义不做深究,在以后工作学习中经常会碰到类似的情况,拿来厂家给的示例代码,读不懂的就直接拿来用,若不能达到效果再仔细研读
示例代码 ICDIPTR14_CPU0 = 0x01010101;
进入中断以后,要提取中断号,并相应的做出反应;处理完中断后,要进行中断恢复:
ICCIAR_CPU0 //当前发生中断的中断号
ACKINTID [9:0] R The interrupt ID
EXT_INT41_PEND
EXT_INT41_PEND[1] [1]:0x1 = Interrupt Occurs //这里特殊,写1清中断,在中断
ICDICPR1_CPU0
Clear-pending bits [31:0]: 25 写1 清中断
ICCEOIR_CPU0 //当中断处理程序结束,将中断号写回这个寄存器,代表中断处理完成
EOIINTID [9:0] W The ACKINTID value from the corresponding ICCIAR access.
//uart #define GPA1CON 0x11400020 #define ULCON2 0x13820000 #define UCON2 0x13820004 #define UBRDIV2 0x13820028 #define UFRACVAL2 0x1382002c #define UTXH2 0x13820020 #define UTRSTAT2 0x13820010 #define rGPA1CON (*(volatile unsigned int*)GPA1CON) #define rULCON2 (*(volatile unsigned int*)ULCON2) #define rUCON2 (*(volatile unsigned int*)UCON2) #define rUBRDIV2 (*(volatile unsigned int*)UBRDIV2) #define rUFBRACVAL2 (*(volatile unsigned int*)UFRACVAL2) #define rUTXH2 (*(volatile unsigned int*)UTXH2) #define rUTRSTAT2 (*(volatile unsigned int*)UTRSTAT2) //interrupt #define GPX1CON 0x11000c20 #define EXT_INT41CON 0x11000E04 #define EXT_INT41_MASK 0x11000F04 #define ICDISER1_CPU0 0x10490104 #define ICDDCR 0x10490000 #define ICCPMR_CPU0 0x10480004 #define ICCICR_CPU0 0x10480000 #define ICCIAR_CPU0 0x1048000C #define EXT_INT41_PEND 0X11000F44 #define ICDICPR1_CPU0 0x10490284 #define ICCEOIR_CPU0 0x10480010 #define ICDIPTR14_CPU0 0x10490838 #define rGPX1CON (*(volatile unsigned int*)GPX1CON) #define rEXT_INT41CON (*(volatile unsigned int*)EXT_INT41CON) #define rEXT_INT41_MASK (*(volatile unsigned int*)EXT_INT41_MASK) #define rICDISER1_CPU0 (*(volatile unsigned int*)ICDISER1_CPU0) #define rICDDCR (*(volatile unsigned int*)ICDDCR) #define rICCPMR_CPU0 (*(volatile unsigned int*)ICCPMR_CPU0) #define rICCICR_CPU0 (*(volatile unsigned int*)ICCICR_CPU0) #define rICCIAR_CPU0 (*(volatile unsigned int*)ICCIAR_CPU0) #define rEXT_INT41_PEND (*(volatile unsigned int*)EXT_INT41_PEND) #define rICDICPR1_CPU0 (*(volatile unsigned int*)ICDICPR1_CPU0) #define rICCEOIR_CPU0 (*(volatile unsigned int*)ICCEOIR_CPU0) #define rICDIPTR14_CPU0 (*(volatile unsigned int*)ICDIPTR14_CPU0) void uart_putc(char c); void do_irq(void); int main(int argc, const char *argv[]) { //KEY3 /* 设置GPA1控制器为UART模式 */ rGPA1CON &= ~(0xff<<0); //把寄存器的bit0~7全部清零 rGPA1CON |= 0X22<<0; //Rx,Tx /* 设置串口协议 */ rULCON2 = 0x03; //0校验位 ,8数据位,1停止位 rUCON2 = 0x05; //轮询模式 /* * 设置波特率: *UART时钟信号源的值为: *100Mhz= 100 000khz = 100 000 000hz *本实验波特率值位115200,DIV_VAL = 100000000/(115200*16) -1 = 54.25 -1 = 53.25 *UBRDIVn = 53 *UFRACVALn/16 = 0.25 ----> UFRACVALn = 4 */ rUBRDIV2 = 53; rUFBRACVAL2 = 4; //INT /* 外设层次上,配置管脚工作模式 */ rGPX1CON &= ~(0xf<<4); //设置为中断模式 rGPX1CON |= (0xF<<4); rEXT_INT41CON &= ~(0X7<<4); rEXT_INT41CON |= (0X02<<4); //设置为下降沿触发 rEXT_INT41_MASK &= ~(1<<1); //外设引脚使能中断,可以让中断发生 /* GIC(通用中断控制器)层次上 */ rICDISER1_CPU0 = rICDISER1_CPU0 | (1<<25); //使能当前中断 rICDDCR |= (1<<0); //全局使能GIC 让所有中断可以通过GIC到达CPU rICCPMR_CPU0 |= (0xFF<<0); //设置中断优先级掩码级别为255 /* CPU内核层次上 */ rICCICR_CPU0 |= (1<<0); //CPU0的全局使能中断,所有中断都可以通过CPU接口到达内核 rICDIPTR14_CPU0 = 0x01010101; //照抄,意义不明 /* 发送状态判断 */ while(1) { uart_putc('c'); delay1s(); } return 0; } void uart_putc(char c) { while(!(rUTRSTAT2&0X02)); rUTXH2 = c; return; } void do_irq(void) //参数中的void表示该函数不允许接受参数,理论上不写也可以,为了方便编译器通过,处于严谨考虑,还是要写上 { int irq_num; irq_num = rICCIAR_CPU0&0x3FF; //获取中断号 switch(irq_num) { case 57: uart_putc('k'); uart_putc('2'); rEXT_INT41_PEND |= 1<<1; //清GPX1_1中断位 rICDICPR1_CPU0 |= 1<<25; //清GIC GPX1_1中断位 break; default: uart_putc('x'); break; } rICCEOIR_CPU0 &= (~0x3FF); rICCEOIR_CPU0 |= irq_num; //结束中断 将处理完成的中断ID号写入该寄存器 表示相应的中断处理完成 }
.global delay1s @.C文件要调用delay1s函数,因此要设置成全局函数
.text
.global _start @
_start:
b reset @0x00
ldr pc,_undefined_instruction @0x04
ldr pc,_software_interrupt
ldr pc,_prefetch_abort
ldr pc,_data_abort
ldr pc,_not_used
ldr pc,_irq
ldr pc,_fiq
_undefined_instruction: .word _undefined_instruction
_software_interrupt: .word _software_interrupt
_prefetch_abort: .word _prefetch_abort
_data_abort: .word _data_abort
_not_used: .word _not_used
_irq: .word irq_handle
_fiq: .word _fiq
reset:
ldr r0,=0x40008000 @设置异常向量表的起始地址为 0x40008000
mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register
init_stack:
ldr r0,stacktop /*get stack top pointer*/
/********svc mode stack********/@设置各种模式的堆栈
mov sp,r0
sub r0,#128*4 /*512 byte for irq mode of stack*/
/****irq mode stack**/
msr cpsr,#0xd2 /* 初始化阶段要禁止IRQ,FIQ中断,I位=1,r位=1,mode位=10010 集合到一起就是d2 */
mov sp,r0
sub r0,#128*4 /*512 byte for irq mode of stack*/
/***fiq mode stack***/
msr cpsr,#0xd1
mov sp,r0
sub r0,#0
/***abort mode stack***/
msr cpsr,#0xd7
mov sp,r0
sub r0,#0
/***undefine mode stack***/
msr cpsr,#0xdb
mov sp,r0
sub r0,#0
/*** sys mode and usr mode stack ***/
msr cpsr,#0x10
mov sp,r0 /*1024 byte for user mode of stack*/
b main
irq_handle:
sub lr,lr,#4
stmfd sp!,{r0-r12,lr}
bl do_irq
irq_handle_end:
ldmfd sp!,{r0-r12,pc}^
delay1s: /* 延时1s函数 */
ldr r4,=0x1ffffff
delay1s_loop:
sub r4,r4,#1
cmp r4,#0
bne delay1s_loop
mov pc,lr
.align 4 /* 4字节对齐 */
/**** swi_interrupt handler ****/
stacktop: .word stack+4*512
.data
stack:
.space 4*512
.end
all:
arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S
arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c
arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf
arm-none-linux-gnueabi-objcopy -O binary uart.elf uart.bin
arm-none-linux-gnueabi-objdump -D uart.elf > uart.dis
clean:
rm -rf *.bak start.o main.o uart.elf uart.bin uart.dis
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x40008000; /*ָ 程序加载地址 */
. = ALIGN(4);
.text :
{
start.o(.text)
*(.text)
}
. = ALIGN(4);
.data :
{ *(.data) }
. = ALIGN(4);
.bss :
{ *(.bss) }
}