Bootstrap and definition library for programming STM32L100RC in ARM assembler. This was a class project to learn ARM assembly
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

254 lines
7.1 KiB

;***************************************************************************************************
;*
;* Place : CVUT FEL, Katedra Mereni
;* Lecturer : Doc. Ing. Jan Fischer,CSc.
;* Subject : A4M38AVS, A4B38NVS
;* Development kit : STM32L100 DISCOVERY (STM32L100RC)
;* Authors : Michal TOMAS (2010), Ondrej Hruska (2015)
;*
;***************************************************************************************************
;***************************************************************************************************
;* Include library files
;***************************************************************************************************
; Base library file
GET lib/INI_BASE.s
; Peripheral modules
GET lib/INI_GPIO.s
GET lib/INI_SYSTICK.s
GET lib/INI_RCC.s
GET lib/INI_FLASH.s
;***************************************************************************************************
;* Start program AREA and pass compiler flags to the startup script...
;***************************************************************************************************
AREA MAIN, CODE, READONLY
; This is a compiler flag imported by the startup script.
__use_two_region_memory
EXPORT __use_two_region_memory
;***************************************************************************************************
;* System config (clock, ports, timers...)
;*
;* Called by the startup script before calling __main
;***************************************************************************************************
SystemInit PROC
EXPORT SystemInit ; Export the address to startup script
PUSH {LR}
BL RCC_CNF ; Configure clock sources
BL GPIO_CNF ; Configure GPIO power and pin settings
BL SYSTICK_CNF ; Configure SysTick timer
POP {PC}
ENDP
;***************************************************************************************************
;* Interrupt handlers...
;***************************************************************************************************
SysTick_Handler PROC
EXPORT SysTick_Handler ; Export the address to startup script (replaces a WEAK stub)
PUSH {LR}
; Toggle the PC8 LED (bit-banding access)
LDR R0, =BB_GPIOC_ODR_9
LDR R1, [R0]
EOR R1, R1, #1
STR R1, [R0]
; alternative - writing the register
; LDR R0, =GPIOC_ODR
; LDR R1, [R0]
; EOR R1, R1, #GPIO9
; STR R1, [R0]
POP {PC}
ENDP
;***************************************************************************************************
;* Main function
;*
;* Called by the startup script after SystemInit.
;* __main is called only once, and does not return!
;***************************************************************************************************
__main PROC
EXPORT __main ; Export the address to startup script
LOOP ; Main loop
; turn LED on
LDR R0, =BB_GPIOC_ODR_8 ; bit-banding address
MOV R1, #1
STR R1, [R0]
; wait
MOV R0, #40
BL DELAY
; turn LED off
LDR R0, =BB_GPIOC_ODR_8
MOV R1, #0
STR R1, [R0]
; wait
MOV R0, #10
BL DELAY
B LOOP
ENDP
;**************************************************************************************************
;* GPIO configuration
;*
;* Sets PC08 and PC09 as outputs, PA0 as input.
;**************************************************************************************************
GPIO_CNF PROC
PUSH {R0,R1,LR}
; Enable GPIO peripheral timing
LDR R0, =RCC_AHBENR ; Advanced High-speed Bus ENable Register
LDR R1, [R0]
LDR R2, =(RCC_AHBENR_GPIOAEN :OR: RCC_AHBENR_GPIOCEN)
ORR R1, R1, R2
STR R1, [R0]
; Output pins C8, C9
LDR R0, =GPIOC_MODER
LDR R1, [R0]
; Clear the area we'll write to
BIC R1,R1, #(GPIO_MODER_8 :OR: GPIO_MODER_9)
; Write "OUTPUT" pattern (0x5555...) masked to the two bits
ORR R1,R1, #(GPIO_MODER_8 :OR: GPIO_MODER_9) & GPIO_MODER_OUTPUT
STR R1, [R0]
; Input pin A0
LDR R0, =GPIOA_MODER
LDR R1, [R0]
BIC R1,R1, #GPIO_MODER_0
; Write the "input" pattern into the bit config area
ORR R1,R1, #(GPIO_MODER_0 & GPIO_MODER_INPUT)
STR R1, [R0]
POP {R0,R1,PC}
ENDP
;**************************************************************************************************
;* SysTick configuration
;*
;* Configures SysTick to fire a SysTick interrupt at 1 Hz
;**************************************************************************************************
SYSTICK_CNF PROC
PUSH {R0, R1, LR}
; Use the core clock (undivided)
LDR R0, =SysTick_CSR
LDR R1, [R0]
ORR R1, R1, #SysTick_CSR_CLKSOURCE_CORE
STR R1, [R0]
; Configure the reload register to 1s
LDR R1, =0xFFFFFF
LDR R0, =SysTick_RELOAD
STR R1, [R0]
; Enable SysTick interrupt & start counting
LDR R0, =SysTick_CSR
LDR R1, [R0]
ORR R1, R1, #(SysTick_CSR_TICKINT :OR: SysTick_CSR_ENABLE)
STR R1, [R0]
POP {R0, R1, PC}
ENDP
;**************************************************************************************************
;* Delay routine
;*
;* Inputs: R0 = number of loop cycles
;**************************************************************************************************
DELAY PROC
PUSH {R2, LR} ; Push the changed registers & link register
WAIT_OUTER ; Outer loop
LDR R2, =40000 ; Length of inner loop
; Inner loop
WAIT_INNER SUBS R2, R2, #1 ; Decrement INNER loop counter
BNE WAIT_INNER ; Continue the loop if not done
SUBS R0, R0, #1 ; Decrement OUTER loop counter
BNE WAIT_OUTER ; Continue the loop if not done
POP {R2, PC} ; Pop & return
ENDP
;***************************************************************************************************
;* Clock configuration
;*
;* Set clock speed to 16 MHz
;**************************************************************************************************
RCC_CNF PROC
PUSH {R0, R1, LR}
; Flash timing configuration
LDR R0, =FLASH_ACR
LDR R1, [R0]
ORR R1, R1, #FLASH_ACR_ACC64
STR R1, [R0]
LDR R1, [R0]
ORR R1, R1, #(FLASH_ACR_PRFTEN :OR: FLASH_ACR_LATENCY)
STR R1, [R0]
; Power on HSI (runs from MSI on start)
LDR R0, =RCC_CR
LDR R1, [R0]
ORR R1, R1, #RCC_CR_HSION
STR R1, [R0]
; Wait for HSIRDY
NO_HSI_RDY LDR R1, [R0]
TST R1, #RCC_CR_HSIRDY
BEQ NO_HSI_RDY
; Select HSI as the core clock source
LDR R0, =RCC_CFGR
LDR R1, [R0]
BIC R1, R1, #RCC_CFGR_SW
ORR R1, R1, #RCC_CFGR_SW_HSI
STR R1, [R0]
POP {R0, R1, PC}
ENDP
;**************************************************************************************************
ALIGN ; Adds NOP if needed to complete a 32-bit word
END