; Interrupt driven hello world program for the LPC2131 ; UART0 registers U0RBR EQU 0xE000C000 U0THR EQU 0xE000C000 U0IER EQU 0xE000C004 U0IIR EQU 0xE000C008 U0FCR EQU 0xE000C008 U0LCR EQU 0xE000C00C U0LSR EQU 0xE000C014 U0SCR EQU 0xE000C01C U0DLL EQU 0xE000C000 U0DLM EQU 0xE000C004 PINSEL0 EQU 0xE002C000 ; VIC registers VICIRQStatus EQU 0xFFFFF000 VICFIQStatus EQU 0xFFFFF004 VICRawIntr EQU 0xFFFFF008 VICIntSelect EQU 0xFFFFF00C VICIntEnable EQU 0xFFFFF010 VICIntEnClr EQU 0xFFFFF014 VICSoftInt EQU 0xFFFFF018 VICSoftIntClr EQU 0xFFFFF01C VICProtection EQU 0xFFFFF020 VICVectAddr EQU 0xFFFFF030 VICDefVectAddr EQU 0xFFFFF034 VICVectAddr0 EQU 0xFFFFF100 VICVectAddr1 EQU 0xFFFFF104 VICVectAddr2 EQU 0xFFFFF108 VICVectAddr3 EQU 0xFFFFF10C VICVectAddr4 EQU 0xFFFFF110 VICVectAddr5 EQU 0xFFFFF114 VICVectAddr6 EQU 0xFFFFF118 VICVectAddr7 EQU 0xFFFFF11C VICVectAddr8 EQU 0xFFFFF120 VICVectAddr9 EQU 0xFFFFF124 VICVectAddr10 EQU 0xFFFFF128 VICVectAddr11 EQU 0xFFFFF12C VICVectAddr12 EQU 0xFFFFF130 VICVectAddr13 EQU 0xFFFFF134 VICVectAddr14 EQU 0xFFFFF138 VICVectAddr15 EQU 0xFFFFF13C VICVectCntl0 EQU 0xFFFFF200 VICVectCntl1 EQU 0xFFFFF204 VICVectCntl2 EQU 0xFFFFF208 VICVectCntl3 EQU 0xFFFFF20C VICVectCntl4 EQU 0xFFFFF210 VICVectCntl5 EQU 0xFFFFF214 VICVectCntl6 EQU 0xFFFFF218 VICVectCntl7 EQU 0xFFFFF21C VICVectCntl8 EQU 0xFFFFF220 VICVectCntl9 EQU 0xFFFFF224 VICVectCntl10 EQU 0xFFFFF228 VICVectCntl11 EQU 0xFFFFF22C VICVectCntl12 EQU 0xFFFFF230 VICVectCntl13 EQU 0xFFFFF234 VICVectCntl14 EQU 0xFFFFF238 VICVectCntl15 EQU 0xFFFFF23C ; main segment AREA main, CODE, READONLY EXPORT __main __main bl init loop b loop HSTR = "Hello world\n\r", 0 align ;; initialises uart0 and vic init mov r1, #0x5 ; PINSEL0 = 0x5 ldr r0, =PINSEL0 str r1, [r0] mov r1, #0x7 ; U0FCR = 0x7 ldr r0, =U0FCR strb r1,[r0] mov r1, #0x83 ; U0LCR = 0x83 ldr r0, =U0LCR strb r1,[r0] mov r1, #90 ; U0DLL = 15 (57600) or 90 (9600) ldr r0, =U0DLL strb r1,[r0] mov r1, #0x00 ; U0DLM = 0x0 ldr r0, =U0DLM strb r1,[r0] mov r1, #0x03 ; U0LCR = 0x03 ldr r0, =U0LCR strb r1,[r0] ldr r0,=HSTRp ; init pointer for ISR ldr r1,=HSTR ; i.e. *HSTRp = HSTR; str r1,[r0] ; now initialise VIC mov r1,#0x0 ; VICIntSelect = 0x00 (all IRQ) ldr r0,=VICIntSelect ; UART0 is channel 6 str r1,[r0] mov r1,#0x40 ; VICIntEnable = 0x40 ldr r0,=VICIntEnable ; UART0 is channel 6 str r1,[r0] ldr r1,=uart0_isr ; VICVectAddr0 = &uart0_isr; ldr r0,=VICVectAddr0 ; address of interrupt 0 str r1,[r0] mov r1,#0x26 ; VICVectCntl0 = 0x26 source 0 is UART0 ldr r0,=VICVectCntl0 ; address of interrupt 0 str r1,[r0] mov r1, #0x02 ; finally U0IER = 0x02 i.e. enable tx interrupts ldr r0, =U0IER strb r1,[r0] mov r0,#'I' ; send first char ldr r1, =U0THR strb r0, [r1] bx r14 ; return from subroutine uart0_isr stmfd sp!,{r0,r1,r2} ldr r2,=HSTRp ; address of pointer to next char ldr r1,[r2] ; value of HSTRp ldrb r0,[r1] ; is value zero? cmp r0,#0 ldreq r1,=HSTR ; if so restore HSTRp ldrbeq r0,[r1] ; and get character add r1,#1 ; advance to next position str r1,[r2] ; store in HSTRp ldr r1,=U0THR ; write next char, this also clears interrupt strb r0,[r1] mov r0,#0xff ; clear VIC interrupt ldr r1,=VICVectAddr str r0,[r1] ldmfd sp!,{r0,r1,r2} subs pc,lr,#4 ; return from interrupt AREA vars, DATA, READWRITE HSTRp dcw 0 ; pointer to HSTR ; uart0 interrupt service routine ; this will continually write "hello world" END