Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Definitions -- references to 'UM' are to the User Manual.
- ; Timer Stuff -- UM, Table 173
- T0 equ 0xE0004000 ; Timer 0 Base Address
- T1 equ 0xE0008000
- IR equ 0 ; Add this to a timer's base address to get actual register address
- TCR equ 4
- MCR equ 0x14
- MR0 equ 0x18
- TimerCommandReset equ 2
- TimerCommandRun equ 1
- TimerModeResetAndInterrupt equ 3
- TimerResetTimer0Interrupt equ 1
- TimerResetAllInterrupts equ 0xFF
- ; VIC Stuff -- UM, Table 41
- VIC equ 0xFFFFF000 ; VIC Base Address
- IntEnable equ 0x10
- VectAddr equ 0x30
- VectAddr0 equ 0x100
- VectCtrl0 equ 0x200
- Timer0ChannelNumber equ 4 ; UM, Table 63
- Timer0Mask equ 1<<Timer0ChannelNumber ; UM, Table 63
- IRQslot_en equ 5 ; UM, Table 58
- IO1DIR EQU 0xE0028018
- IO1SET EQU 0xE0028014
- IO1CLR EQU 0xE002801C
- IO1PIN EQU 0xE0028010
- IO0DIR EQU 0xE0028008
- IO0SET EQU 0xE0028004
- IO0CLR EQU 0xE002800C
- AREA InitialisationAndMain, CODE, READONLY
- IMPORT main
- ; (c) Mike Brady, 2014–2016.
- EXPORT start
- start
- ; |----------------------------|
- ; |----INITIALISTION CODE------|
- ; |----------------------------|
- ; Initialise the VIC
- ldr r0,=VIC ; looking at you, VIC!
- ldr r1,=irqhan
- str r1,[r0,#VectAddr0] ; associate our interrupt handler with Vectored Interrupt 0
- mov r1,#Timer0ChannelNumber+(1<<IRQslot_en)
- str r1,[r0,#VectCtrl0] ; make Timer 0 interrupts the source of Vectored Interrupt 0
- mov r1,#Timer0Mask
- str r1,[r0,#IntEnable] ; enable Timer 0 interrupts to be recognised by the VIC
- mov r1,#0
- str r1,[r0,#VectAddr] ; remove any pending interrupt (may not be needed)
- ; Initialise Timer 0
- ldr r0,=T0 ; looking at you, Timer 0!
- mov r1,#TimerCommandReset
- str r1,[r0,#TCR]
- mov r1,#TimerResetAllInterrupts
- str r1,[r0,#IR]
- ldr r1,=(14745600/2)-1 ; 5 ms = 1/200 second
- str r1,[r0,#MR0]
- mov r1,#TimerModeResetAndInterrupt
- str r1,[r0,#MCR]
- mov r1,#TimerCommandRun
- str r1,[r0,#TCR]
- ;from here, initialisation is finished, so it should be the main body of the main program
- ; |----------------------------|
- ; |---INITIALISE SCHEDULER-----|
- ; |----------------------------|
- LDR lr,=programTwo
- LDR sp,=stackTwo
- STMFD sp!, {r0-r12, lr}
- LDR R1,=stackPointTwo
- STR sp, [R1]
- LDR R0,=programRunning
- MOV R1, #1
- STR R1, [R0]
- LDR sp,=stackOne
- B programOne
- ; |----------------------------|
- ; |---------THREAD ONE---------|
- ; |----------------------------|
- programOne
- ldr r1,=IO1DIR
- ldr r2,=0x000f0000 ;select P1.19--P1.16
- str r2,[r1] ;make them outputs
- ldr r1,=IO1SET
- str r2,[r1] ;set them to turn the LEDs off
- ldr r2,=IO1CLR
- ; r1 points to the SET register
- ; r2 points to the CLEAR register
- ldr r5,=0x00100000 ; end when the mask reaches this value
- wloop ldr r3,=0x00010000 ; start with P1.16.
- floop str r3,[r2] ; clear the bit -> turn on the LED
- ;delay for about a half second
- ldr r4,=2000000
- dloop subs r4,r4,#1
- bne dloop
- str r3,[r1] ;set the bit -> turn off the LED
- mov r3,r3,lsl #1 ;shift up to next bit. P1.16 -> P1.17 etc.
- cmp r3,r5
- bne floop
- b wloop
- endProgramOne b endProgramOne
- ; |----------------------------|
- ; |---------THREAD TWO---------|
- ; |----------------------------|
- programTwo
- ldr r1,=IO1DIR
- ldr r2,=0x000f0000 ;select P1.19--P1.16
- str r2,[r1] ;make them outputs
- ldr r1,=IO1SET
- str r2,[r1] ;set them to turn the LEDs off
- ldr r2,=IO1CLR
- ; r1 points to the SET register
- ; r2 points to the CLEAR register
- ldr r5,=0x00100000 ; end when the mask reaches this value
- wloop2 ldr r3,=0x00010000 ; start with P1.16.
- floop2 str r3,[r2] ; clear the bit -> turn on the LED
- ;delay for about a half second
- ldr r4,=200000
- dloop2 subs r4,r4,#1
- bne dloop2
- str r3,[r1] ;set the bit -> turn off the LED
- mov r3,r3,lsl #1 ;shift up to next bit. P1.16 -> P1.17 etc.
- cmp r3,r5
- bne floop2
- b wloop2
- endProgramTwo b endProgramTwo
- ; |----------------------------|
- ; |---------INTERRUPTS---------|
- ; |----------------------------|
- AREA InterruptStuff, CODE, READONLY
- irqhan sub lr,lr,#4
- stmfd sp!,{r0-r12, lr} ; the lr will be restored to the pc
- LDR R0,=programRunning
- LDR R1, [R0]
- CMP R1, #1
- LDRNE R2,=stackPointTwo
- LDREQ R2,=stackPointOne
- STR sp, [R2]
- LDRNE R2,=stackPointOne
- LDREQ R2,=stackPointTwo
- LDR sp, [R2]
- EOR R1, #0x3
- STR R1, [R0]
- ;here you'd put the unique part of your interrupt handler
- ;all the other stuff is "housekeeping" to save registers and acknowledge interrupts
- ;this is where we stop the timer from making the interrupt request to the VIC
- ;i.e. we 'acknowledge' the interrupt
- ldr r0,=T0
- mov r1,#TimerResetTimer0Interrupt
- str r1,[r0,#IR] ; remove MR0 interrupt request from timer
- ;here we stop the VIC from making the interrupt request to the CPU:
- ldr r0,=VIC
- mov r1,#0
- str r1,[r0,#VectAddr] ; reset VIC
- ldmfd sp!,{r0-r12, pc}^ ; return from interrupt, restoring pc from lr
- ; and also restoring the CPSR
- ; |----------------------------|
- ; |---------SUBROUTINE---------|
- ; |----------------------------|
- AREA Subroutines, CODE, READONLY
- AREA Stuff, DATA, READWRITE
- programRunning DCD 0
- stackOne SPACE 1024
- stackTwo SPACE 1024
- stackPointOne DCD 0
- stackPointTwo DCD 0
- fireWorks DCD 0x1, 0x2, 0x4, 0x8
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement