Update: A variation of this for the LPC11148FN28 can be found here
I wanted to try to write a minimal assembler blinky program that flashes the blue LED on an STM32F0 Value Line discovery board (STM32F030R8T6 MCU).
The linker script and Makefile are tagged on at the end
// Minimal assembler blinky example for stm32f030 // (stm32f0 Value line discovery board) // LED is on GPIOC bit 8 .thumb // Cortex micros only understand thumb(2) code .syntax unified // use newer style instructions .text // what follows is code // Set up interrupt vector table: // entry 0: initial stack pointer // entry 1: reset address Vector_Table: .word 0x20002000 // Top of Stack /* The interrupt vectors that follow are manually forced to be aligned along odd addresses. The reason for this is that the address for a Thumb instruction must always have its LSB set to 1. This does not mean that the instruction is stored at an odd number address. The LSB is used as a flag to indicate that an ARM (LSB=0) or a Thumb (LSB=1) instruction is being addressed. */ ResetVector: .word start + 1 // Reset Handler // the program starts here start: // Do initial IO configuration // Turn on clock for GPIOC ldr R1,=RCCAHBENR // pointer to register ldr R2,=RCCAHBENRMASK // mask bl set_bits // Make port pin behave as an output ldr R1,=GPIOCMODER // pointer to register ldr R2,=GPIOCMODERMASK // mask bl set_bits // Now enter the main loop main_loop: // Turn LED on ldr R1,=GPIOCODR // pointer to register ldr R2,=LEDMASK // mask bl set_bits // wait a while ldr R0,=DELAYLENGTH bl delay // Turn LED off ldr R1,=GPIOCODR // pointer to register ldr R2,=LEDMASK // mask bl clear_bits // wait a while ldr R0,=DELAYLENGTH bl delay b main_loop // branch back to start of loop // subroutines are down here // Delay subroutine. Pass the length of the delay in R0 delay: subs R0,R0,#1 bne delay bx LR // on entry, R1 contains address where target address is stored // R2 contains address where mask bits are stored set_bits: ldr R0,[R1] // read register contents orrs R0,R0,R2 // combine with register contents str R0,[R1] // write back contents bx LR // return to caller // on entry, R1 contains address where target address is stored // R2 contains address where mask bits are stored clear_bits: ldr R0,[R1] // read register contents bics R0,R0,R2 // combine with register contents str R0,[R1] // write back contents bx LR // return to caller // constant definitions are below here. .equ RCCAHBENR, 0x40021014 .equ GPIOCMODER, 0x48000800 .equ GPIOCODR, 0x48000814 .equ RCCAHBENRMASK, 0x00080000 .equ GPIOCMODERMASK, 0x00010000 .equ LEDMASK, 0x00000100 .equ DELAYLENGTH, 0x000fffff
Linker script
MEMORY { flash : org = 0x08000000, len = 64k ram : org = 0x20000000, len = 8k } SECTIONS { . = ORIGIN(flash); .text : { } >flash . = ORIGIN(ram); .data : { } >ram }
Makefile
# Specify the assembler to use AS=arm-none-eabi-as # Specity the linker to use LD=arm-none-eabi-ld ASFLAGS=-mcpu=cortex-m0 -mthumb -g # List the object files involved in this project OBJS= blinky.o blinky.elf : $(OBJS) $(LD) $(OBJS) -T linker_script.ld --cref -Map blinky.map -nostartfiles -o main.elf objcopy -O ihex main.elf main.hex blinky.o: blinky.s $(AS) $(ASFLAGS) blinky.s -asghl=blinky.lst -o blinky.o # if someone types in 'make clean' then remove all object files and executables # associated wit this project clean: rm $(OBJS) rm blinky.elf
why yo dont use bsrr register?
LikeLike
I agree that would be a better solution for this device however not all MCU’s have such a register and I wanted this to be a more general demonstration. Thanks for the comment.
LikeLike