原点实验室 2018-02-16
结合之前的串口实验(轮询方式)与中断体系分析,我们来做下中断方式的串口接收实验。
.global _start .global IRQ_handle _start: /* 关 Watch Dog */ ldr r0, =0xE2700000 mov r1, #0 str r1, [r0] /* 设置系统模式栈指针 */ ldr sp, =0x40000000 /* 开 IRQ 总中断开关 */ mov r0, #0x53 msr CPSR_cxsf, r0 /* 时钟初始化 */ bl clock_init bl main halt: b halt IRQ_handle: /* 设置 IRQ 模式栈指针 */ ldr sp, =0xD0037F80 /* 设置 lr */ sub lr, lr, #4 stmfd sp!, {r0-r12, lr} /* 另一个 ISR 的接口 */ bl irq_handler /* 弹出保存的数据 */ ldmfd sp!, {r0-r12, pc}^
#define UART_UBRDIV_VAL 34 #define UART_UDIVSLOT_VAL 0xDFDD void uart_init() { /* 配置引脚为串口模式 */ GPA0CON = 0x22; /* 不使用 FIFO */ UFCON0 = 0x00; /* 无流控 */ UMCON0 = 0x00; /* 配置数据格式 */ ULCON0 = 0x03; /* 配置 UART */ UCON0 = 0x105; /* 配置波特率 */ UBRDIV0 = UART_UBRDIV_VAL; UDIVSLOT0 = UART_UDIVSLOT_VAL; /* 开放 RX0 中断 */ UINTM = 0x0e; }
所调用的 API 可在之前串口实验文章中找到。
/* 初始化异常向量 */ system_initexception(); /* 配置 ISR 函数 */ intc_setvectaddr(NUM_UART0, handler); /* 使能 NUM_UART0 中断 */ intc_enable(NUM_UART0);
void handler(void) { /* 发送 +1 后的结果 */ putc(getc()+1); /* 清 VICnADDR */ intc_clearvectaddr(); /* 清除中断标志 */ UINTP = 0x0f; UINTSP = 0x0f; }
向 S5PV210 发送一个字符,会得到这个字符 +1 后的字符。