Minimal blinky in ARM Cortex M0 assembler

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 

2 thoughts on “Minimal blinky in ARM Cortex M0 assembler

  1. hsarc March 11, 2016 / 6:41 am

    why yo dont use bsrr register?

    Like

    • fduignan March 11, 2016 / 7:25 am

      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.

      Like

Leave a comment