Skip to main content
drobison
Associate III
April 30, 2013
Question

Assembly Code Example

  • April 30, 2013
  • 25 replies
  • 6356 views
Posted on May 01, 2013 at 00:02

I've made up a board and embedded a STM32F4 on it.  I want example assembly code to compile and upload to the chip.  I can't find any on the entire internet for a Cortex-M4.  Does anyone have a link to a generic GPIO blinking program I can run to get myself started, like a hello world in assembly for the STM32?

#assembly-gpio-code-example-corte #mixing-assm-code-with-c
This topic has been closed for replies.

25 replies

drobison
drobisonAuthor
Associate III
April 30, 2013
John F.
Associate III
May 1, 2013
Posted on May 01, 2013 at 10:11

While I appreciate you want something simple to begin with, you really ought to consider the CMSIS and ST Peripheral Library. Apart from anything else, use of the library will greatly increase your chances of getting useful support here. Using the peripheral library does not prevent you from writing efficient code.

Tesla DeLorean
Guru
May 1, 2013
Posted on May 01, 2013 at 15:11

I wouldn't discourage anyone from trying to use assembly, the Cortex-M3 is designed for easy C usage, but being able to read/write assembler is very useful, and a skill many do not possess. I'll post some example if it helps, and take questions.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
emalund
Associate III
May 1, 2013
Posted on May 01, 2013 at 17:03

I wouldn't discourage anyone from trying to use assembly, the Cortex-M3 is designed for easy C usage, but being able to read/write assembler is very useful, and a skill many do not possess. I'll post some example if it helps, and take questions.

I do partially agree.  I do know, and agree it is essential, enough M3 assembly to read the disassembly, but would never attempt to get fluent enough to write it beyond possibly a very small routine.

if the OP is, in effect, saying ''I do not know C'' my absolute recommendation is, forget about the M3 till you have learned C.

Erik
John F.
Associate III
May 1, 2013
Posted on May 01, 2013 at 17:05

''Examples'' ... Yes please. ''Discourage'' not intended ... but I stand by my comments.

dthedens23
Associate
May 1, 2013
Posted on May 01, 2013 at 17:10

I look at C vs ASM as a ''time to market'' thing.

With C, I can get to the minimum viable product in much less time than using ASM with less defects and better readability.

the microcontrollers offered these days have large code and data space so there is less need of hand tuned firmware.

ASM is used only when there is a need to optimize some portion of code.

Agile Development suggests that optimization should not be done until one measures and determines that there is a need.

So, last time I used ASM was two years ago!  The C/C++ compilers are good.

drobison
drobisonAuthor
Associate III
May 1, 2013
Posted on May 01, 2013 at 17:18

I know C++, FORTRAN, JAVA, HTML, BASIC ...  I even taught a class on C at ITT Tech.  My situation is the STM32 will be used to input Analog signals and output PWMs.  So the STM32 is like a closed loop feedback path.  The code will primarily be interrupt service routines, that take digitally processed signals in real time and use that info to modulate digital PWMs for output.  Timing need to be under 50us for everything.  Is there a library for high power applications?

I have another question though.  I see my sample code will starts at 0x00000000, while my flash memory starts at 0x08000000.  The Cortex-M? literature says my vector table should start at 0x00000000, but I read that for STM32 the vector table starts at 0x08000000. The flash starts at 0x08000000.  How is this?  Is it shadowed at 0x00000000?  Is this part of the flash ART?  Its a huge idioscncracy I have yet found an explanation for.

Tesla DeLorean
Guru
May 1, 2013
Posted on May 01, 2013 at 18:52

The zero mapping/shadowing is defined by the BOOTx pins, a behaviour outside the core defined by the implementer, in this case ST.

After boot you can reprogram SCB->VTOR to change the vector table address, based on the vector usage by ST, this needs to fall on a 512 byte boundary.

For the F4 see RM0090 Rev 4 see ''2.4 Boot Configuration'', and ''8.2.1 SYSCFG memory remap register (SYSCFG_MEMRMP)''

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
dthedens23
Associate
May 1, 2013
Posted on May 01, 2013 at 19:15

OK, that sheds a better light.

I would still start up everything in C using CMSIS which will do all the setup; the stuff that is not your core competence.

Then, after all is setup and good to go,  your main loop can venture off into ASM land.

easier to understand C->ASM calling convention than do all the startup stuff.

Tesla DeLorean
Guru
May 1, 2013
Posted on May 01, 2013 at 21:50

Hello World!

Fixed a couple of bit offsets for pin 10/11 register settings

; Keil Syntax, no claims of high efficiency, just workable demo - sourcer32@gmail.com

Reset_Handler PROC

;...

BL InitUSART3

LDR R0, =Hello

BL _OutString

;...

ENDP ; Reset_Handler

Hello DCB ''Hello World!'', 0

ALIGN

;*****************************************************************************

; Assumes system running from 16 MHz, HSI (Normal at Reset)

; USART3 PB10 TX, PB11 RX

InitUSART3 PROC

ldr r0, =0x40023800 ; RCC

ldr r1, [r0, &sharp0x30] ; RCC_AHB1ENR

orr r1, &sharp2 ; GPIOBEN (1 << 
1
)

str r1, [r0, &sharp0x30]

ldr r1, [r0, &sharp0x40] ; RCC_APB1ENR

orr r1, &sharp0x40000 ; USART3EN (1 << 18)

str r1, [r0, &sharp0x40]

ldr r0, =0x40020400 ; GPIOB

ldr r1, [r0, &sharp0x00] ; GPIOx_MODER

bic r1, &sharp0xF00000 ; Mask PB10/11

orr r1, &sharp0xA00000 ; =AF Mode

str r1, [r0, &sharp0x00]

ldr r1, [r0, &sharp0x04] ; GPIOx_OTYPE

bic r1, &sharp0xC00 ; Mask PB10/11, 
0
=
PP

str r1, [r0, &sharp0x04]

ldr r1, [r0, &sharp0x08] ; GPIOx_OSPEEDR

bic r1, &sharp0xF00000 ; Mask PB10/11, 
0
=
2
MHz (adequate)

str r1, [r0, &sharp0x08]

ldr r1, [r0, &sharp0x0C] ; GPIOx_PUPDR

bic r1, &sharp0xF00000 ; Mask PB10/11, 
0
=
No
Pull

str r1, [r0, &sharp0x0C]

ldr r1, [r0, &sharp0x24] ; GPIOx_AFRH

bic r1, &sharp0xFF00 ; Mask PB10/11

orr r1, &sharp0x7700 ; =AF7 USART3

str r1, [r0, &sharp0x24]

ldr r0, =0x40004800 ; USART3

movs r1, &sharp139 ; 16MHz / 139 == 115200

strh r1, [r0, &sharp8] ; +8 USART_BR

movs r1, &sharp0x0600

strh r1, [r0, &sharp16] ; +16 
USART_CR2
= 
0x600

movs r1, &sharp0

strh r1, [r0, &sharp16] ; +16 
USART_CR2
= 
0

movs r1, &sharp0

strh r1, [r0, &sharp20] ; +20 
USART_CR3
= 
0

movs r1, &sharp0

strh r1, [r0, &sharp24] ; +24 
USART_GTPR
= 
0
- Prescaler

movw r1, &sharp0x200C ; 8-bit, no parity, enable TX,TX

strh r1, [r0, &sharp12] ; +12 USART_CR1

ldr r2, =10 ; Output 10 pound/hash symbols, no reason

iu1 ldrh r1, [r0, &sharp0] ; USART->SR

ands r1, &sharp0x80 ; TXE

beq iu1

mov r1, ♯'♯'

strh r1, [r0, &sharp4] ; USART->DR

subs.w r2, r2, &sharp1 ; $1

bne.n iu1

bx lr

ENDP ; InitUSART3

;*****************************************************************************

; Uses

; r0 Character to output, masked

; r1 scratch, destroyed

; r2 scratch, destroyed

_OutChar PROC

ldr r2, =0x40004800 ; USART3 F2/F4

and r0, &sharp0xFF

_OutChar10 ldrh r1, [r2, &sharp0] ; USART->SR

ands r1, &sharp0x80 ; TXE

beq _OutChar10

strh r0, [r2, &sharp4] ; USART->DR

bx lr

ENDP ; _OutChar

;*****************************************************************************

; Uses

; r0 String to output, destroyed

; r1,r2,r3 assumed scratch

_OutString PROC

push {r4, lr}

mov r4, r0

_OutString10 ldrb.w r0, [r4], &sharp1 ; r0 = *r4++ (BYTE)

orrs r0, r0

beq _OutString20

bl _OutChar

b _OutString10

_OutString20 pop {r4, pc}

ENDP ; _OutString

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..