Skip to main content
Graduate II
February 4, 2025
Question

LED blinking in assembler for STM32F103C8T6

  • February 4, 2025
  • 2 replies
  • 1230 views

Hello,

I am trying small example LED blinking written in assembly only - see below. LED is placed to PB15. I am able to compile the program without error using this commands:

arm-none-eabi-gcc -save-temps -nostdlib -nostartfiles -mcpu=cortex-m3 -ffreestanding -O2 led-stm32.s -o led-stm32.elf
arm-none-eabi-objcopy -O binary led-stm32.elf led-stm32.bin

I am using "gcc-arm-none-eabi-10.3-2021.10-win32.exe". I am able to write the program to processor STM32F103C8T6 using STLINKV2, but nothing happend. LED on PB15 is no blinking, LED is no shining. LED is off. .

Can someone help me where is problem ?  :)  Do you (someone) have working example in assembly ?

 

@@@ led-stm32.asm

@@@ Directives
 .cpu cortex-m3
 .code 16 @
 .syntax unified
 .global _start
 .align 2

@@@ Equates
 .equ GPIOB_CRH, 0x40010C04
 .equ GPIOB_ODR, 0x40010C0C
 .equ RCC_APB2ENR, 0x40021018
 .equ STACKINIT, 0x20005000

 .equ LEDDELAY, 0x4E20 @20000

.section .text
 .org 0

@@@ Vectors
vectors:
 .word STACKINIT @ stack pointer value when stack is empty
 .word _start + 1 @ reset vector (manually adjust to odd for thumb)
 .word _nmi_handler + 1 @
 .word _hard_fault + 1 @
 .word _memory_fault + 1 @
 .word _bus_fault + 1 @
 .word _usage_fault + 1 @

_start:

 @@ Enable the Port B peripheral clock by setting bit 4
 ldr r6, = RCC_APB2ENR
 mov r0, #0x08
 str r0, [r6]

 @@ Set the config and mode bits for Port B bit 15 so it will
 @@ be a open drain output (up to 8 MHz) by setting bits 19-16
 @@ to '0110'.

 ldr r6, = GPIOB_CRH
 ldr r0, = #0x64444444 @ 0110 0100 0100 0100 0100 0100 0100 0100
 str r0, [r6]

 @@ Load R2 and R3 with the "on" and "off" constants
 mov r2, #0 @ value to turn on LED
 mov r3, #0x8000 @ value to turn off LED

 ldr r6, = GPIOB_ODR @ point to Port B output data register

loop:
 str r2, [r6] @ clear Port B, pin 15, turning on LED
 ldr r1, = LEDDELAY
delay1:
 subs r1, #1
 bne delay1

 str r3, [r6] @ set Port B, pin 15, turning off LED
 ldr r1, = LEDDELAY
delay2:
 subs r1, #1
 bne delay2

 b loop @ continue forever

_dummy: @ if any int gets triggered, just hang in a loop
_nmi_handler:
_hard_fault:
_memory_fault:
_bus_fault:
_usage_fault:
 add r0, #1
 add r1, #1
 b _dummy

 

    This topic has been closed for replies.

    2 replies

    Technical Moderator
    February 4, 2025

    I haven't checked your code yet due to time constraints, but you can use my ASM example that I once created for STM32G4 and the STM32CubeIDE as a guide. As Cortex-M4 and Cortex-M3 are very similar, you only need to adapt the ASM syntax to your toolchain and check the register addresses.

    Hope that helps?

    Regards
    /Peter

    JerryMC22Author
    Graduate II
    February 5, 2025

    So, I tested your program in asm + CubeIDE, but I was NOT able to get the code up and running. So I downloaded free Keil MDK 5.4:1 and I found this example

    https://www.youtube.com/watch?v=Zj4-fgRph1s

    on youtube and the code is working ok. Source code is in attachments. The compiler is armclang. it means that I did not use the queer GNU arm assembler.

     

     

    File1.asm
    
    stackStartAddress EQU 0x20000100
     
     AREA mySection1, DATA, READONLY
     
     DCD stackStartAddress
     DCD myResetHandler
     
     AREA mySection2, CODE, READONLY
     ENTRY
     
     
    myResetHandler 
     IMPORT myApplication
     
     B myApplication
     
     END
    
    
    File2.asm
    
     EXPORT myApplication
     
    RCC EQU 0x40021000
    Port_C EQU 0x40010C00
     
     
     AREA mySection3, CODE, READONLY
     
    myApplication
     ; enable the APB2 clock
     
     MOV r0, #0x08
     LDR r1, =RCC
     STR r0, [r1, #0x18]
    
    
     ; configure the GPIO C for output
    
     MOV r0, #0x20000000
     LDR r1, =Port_C
     STR r0, [r1, #0x04]
    
    
     ; set the builtin LED on/off
     
     MOV r0, #0x0000 ; #0x8000
     STR r0, [r1, #0x0C]
    
    
     B .
    
     ALIGN
    
     END
    
    
    First.sct – script for linker
    
    LR_IROM1 0x08000000 0x00010000 { ; load region size_region
     ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
     file1.o (mySection1, +First)
     file1.o (mySection2)
     file2.o (mySection3)
     
     ; .ANY (+RO)
     }
     RW_IRAM1 0x20000000 0x00005000 { ; RW data
     .ANY (+RW +ZI)
     }
    }
    JerryMC22Author
    Graduate II
    February 10, 2025

    Hi Jerry,

    I finally succeeded and LED PB15 blink example using GNU assebler is working ok :) See attached code.

    gcc-arm-none-eabi-10.3-2021.10-win32.exe is used from  https://developer.arm.com/downloads/-/gnu-rm

    :)