Загрузка данных
THUMB
; Register addresses
RCC_APB2ENR EQU 0x40021018
; AFIO - selects which port feeds each EXTI line
AFIO_EXTICR2 EQU 0x4001000C
AFIO_EXTICR3 EQU 0x40010010
AFIO_EXTICR4 EQU 0x40010014
; EXTI - external interrupt controller
EXTI_IMR EQU 0x40010400
EXTI_RTSR EQU 0x40010408
EXTI_FTSR EQU 0x4001040C
EXTI_PR EQU 0x40010414
; GPIOA
GPIOA_CRL EQU 0x40010800
GPIOA_CRH EQU 0x40010804
GPIOA_IDR EQU 0x40010808
GPIOA_ODR EQU 0x4001080C
GPIOA_BSRR EQU 0x40010810
; GPIOB
GPIOB_CRL EQU 0x40010C00
GPIOB_CRH EQU 0x40010C04
GPIOB_IDR EQU 0x40010C08
GPIOB_ODR EQU 0x40010C0C
GPIOB_BSRR EQU 0x40010C10
; NVIC - interrupt enable in the core
NVIC_ISER0 EQU 0xE000E100
NVIC_ISER1 EQU 0xE000E104
;Bit-band alias addresses, computed from base + offset*32 + bit*4
PER_BB_BASE EQU 0x42000000
PER_BASE EQU 0x40000000
; Offsets of registers from the peripheral base
GPIOA_ODR_OFF EQU 0x0001080C
GPIOB_ODR_OFF EQU 0x00010C0C
GPIOA_IDR_OFF EQU 0x00010808
GPIOB_IDR_OFF EQU 0x00010C08
; Alias addresses for LED output bits (ODR)
PA5_ODR_BB EQU PER_BB_BASE + GPIOA_ODR_OFF * 32 + 5 * 4
PB0_ODR_BB EQU PER_BB_BASE + GPIOB_ODR_OFF * 32 + 0 * 4
PB13_ODR_BB EQU PER_BB_BASE + GPIOB_ODR_OFF * 32 + 13 * 4
; Alias addresses for button input bits (IDR)
PA8_IDR_BB EQU PER_BB_BASE + GPIOA_IDR_OFF * 32 + 8 * 4
PB5_IDR_BB EQU PER_BB_BASE + GPIOB_IDR_OFF * 32 + 5 * 4
PB15_IDR_BB EQU PER_BB_BASE + GPIOB_IDR_OFF * 32 + 15 * 4
AREA LAB2MAIN, CODE, READONLY
EXPORT main
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
main
; Enable clocks: AFIO (bit 0), GPIOA (bit 2), GPIOB (bit 3)
LDR R0, =RCC_APB2ENR
LDR R1, [R0]
ORR R1, R1, #0x0D
STR R1, [R0]
; Preset ODR to 1 while pins are still inputs.
; Otherwise LEDs would flash ON at the moment pins become outputs.
; PA8=1 also selects pull-up direction.
LDR R0, =GPIOA_ODR
LDR R1, =0x00000120
STR R1, [R0]
LDR R0, =GPIOB_ODR
LDR R1, =0x00002001
STR R1, [R0]
; PA5 - output push-pull 2 MHz
LDR R0, =GPIOA_CRL
LDR R1, [R0]
LDR R2, =0xFF0FFFFF
AND R1, R1, R2
LDR R2, =0x00200000
ORR R1, R1, R2
STR R1, [R0]
; PA8 - input with pull-up
LDR R0, =GPIOA_CRH
LDR R1, [R0]
LDR R2, =0xFFFFFFF0
AND R1, R1, R2
ORR R1, R1, #0x8
STR R1, [R0]
; PB0 - output, PB5 - input with pull-down
LDR R0, =GPIOB_CRL
LDR R1, [R0]
LDR R2, =0xFF0FFFF0
AND R1, R1, R2
LDR R2, =0x00800002
ORR R1, R1, R2
STR R1, [R0]
; PB13 - output, PB15 - input with pull-down
LDR R0, =GPIOB_CRH
LDR R1, [R0]
LDR R2, =0x0F0FFFFF
AND R1, R1, R2
LDR R2, =0x80200000
ORR R1, R1, R2
STR R1, [R0]
; AFIO: EXTI5 -> PB5
LDR R0, =AFIO_EXTICR2
LDR R1, [R0]
BIC R1, R1, #0xF0
ORR R1, R1, #0x10
STR R1, [R0]
; AFIO: EXTI8 -> PA8
LDR R0, =AFIO_EXTICR3
LDR R1, [R0]
BIC R1, R1, #0x0F
STR R1, [R0]
; AFIO: EXTI15 -> PB15
LDR R0, =AFIO_EXTICR4
LDR R1, [R0]
BIC R1, R1, #0xF000
ORR R1, R1, #0x1000
STR R1, [R0]
; Rising edge on lines 5 and 15
LDR R0, =EXTI_RTSR
LDR R1, [R0]
LDR R2, =0x00008020
ORR R1, R1, R2
STR R1, [R0]
; Falling edge on line 8
LDR R0, =EXTI_FTSR
LDR R1, [R0]
ORR R1, R1, #(1 << 8)
STR R1, [R0]
; Unmask lines 5, 8, 15
LDR R0, =EXTI_IMR
LDR R1, [R0]
LDR R2, =0x00008120
ORR R1, R1, R2
STR R1, [R0]
; NVIC: enable IRQ23 (EXTI 5..9)
LDR R0, =NVIC_ISER0
MOV R1, #(1 << 23)
STR R1, [R0]
; NVIC: enable IRQ40 (EXTI 10..15)
LDR R0, =NVIC_ISER1
MOV R1, #(1 << 8)
STR R1, [R0]
CPSIE I
; Main loop: sleep until a button interrupt arrives
loop
LDR R0, =Events
LDR R1, [R0]
CMP R1, #0
BNE process
WFI
B loop
process
; Clear event flag
MOV R2, #0
STR R2, [R0]
; Debounce ~10 ms
LDR R3, =100000
BL Delay
; Check PB5 (active HIGH) -> green LED on PB0
LDR R0, =PB5_IDR_BB
LDR R1, [R0]
CMP R1, #0
BEQ chk_pa8
LDR R0, =PB0_ODR_BB
LDR R1, [R0]
EOR R1, R1, #1
STR R1, [R0]
chk_pa8
; Check PA8 (active LOW) -> red LED on PA5
LDR R0, =PA8_IDR_BB
LDR R1, [R0]
CMP R1, #0
BNE chk_pb15
LDR R0, =PA5_ODR_BB
LDR R1, [R0]
EOR R1, R1, #1
STR R1, [R0]
chk_pb15
; Check PB15 (active HIGH) -> blue LED on PB13
LDR R0, =PB15_IDR_BB
LDR R1, [R0]
CMP R1, #0
BEQ loop
LDR R0, =PB13_ODR_BB
LDR R1, [R0]
EOR R1, R1, #1
STR R1, [R0]
B loop
; Delay. R3 is the counter, set before call
Delay
SUBS R3, R3, #1
BNE Delay
BX LR
; ISR for EXTI 5..9 (handles PB5 and PA8)
EXTI9_5_IRQHandler
; Read pending flags
LDR R0, =EXTI_PR
LDR R1, [R0]
; Store them in Events
LDR R2, =Events
LDR R3, [R2]
ORR R3, R3, R1
STR R3, [R2]
; Clear flags (write 1 to clear)
STR R1, [R0]
BX LR
; ISR for EXTI 10..15 (handles PB15)
EXTI15_10_IRQHandler
LDR R0, =EXTI_PR
LDR R1, [R0]
LDR R2, =Events
LDR R3, [R2]
ORR R3, R3, R1
STR R3, [R2]
STR R1, [R0]
BX LR
; Variable passed from ISR to main loop
AREA LAB2DATA, DATA, READWRITE
Events DCD 0
ALIGN
END
------------------------------------------------------------------
PRESERVE8
THUMB
Stack_Size EQU 0x400
; Stack area
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
Stack_Top
; Vector table
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors
DCD Stack_Top
DCD Reset_Handler
DCD NMI_Handler
DCD HardFault_Handler
; Skip system exceptions (12 slots), reach IRQ0
SPACE 12 * 4
; IRQ0..IRQ4 - EXTI lines 0..4, unused but slots must exist
DCD EXTI0_IRQHandler
DCD EXTI1_IRQHandler
DCD EXTI2_IRQHandler
DCD EXTI3_IRQHandler
DCD EXTI4_IRQHandler
; Skip IRQ5..IRQ22 (18 slots), next is IRQ23
SPACE 18 * 4
; IRQ23 - shared vector for EXTI 5..9 (PB5 and PA8)
DCD EXTI9_5_IRQHandler
; Skip IRQ24..IRQ39 (16 slots), next is IRQ40
SPACE 16 * 4
; IRQ40 - shared vector for EXTI 10..15 (PB15)
DCD EXTI15_10_IRQHandler
SPACE 2 * 4
AREA LAB2, CODE, READONLY
IMPORT main
ENTRY
EXPORT Reset_Handler
; After reset jump to main in main.s
Reset_Handler
LDR R0, =main
BX R0
; If something goes wrong, spin here
EXPORT HardFault_Handler [WEAK]
HardFault_Handler
B .
; Default stubs for unused interrupts
Default_Handler
EXPORT NMI_Handler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
NMI_Handler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
B .
; Stub required by Keil
EXPORT __main
__main
B .
ALIGN
END