cancel
Showing results for 
Search instead for 
Did you mean: 

Assembly Code Example

drobison
Associate II
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
25 REPLIES 25
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 Venmo
Up vote any posts that you find helpful, it shows what's working..
John F.
Senior
Posted on May 02, 2013 at 14:43

Assembler. Yippee!

The OP wrote, ''the STM32 will be used to input Analog signals and output PWMs''. In that case, you could set up the ADC to scan several channels and DMA them into an array. Trigger the ADC in a timer interrupt. On each interrupt, before starting a new scan, process the Analog signals you've got and write new PWM settings. Writing new PWM values is as simple as,

/* Set the Capture Compare Register value */
TIMx->CCR4 = value;

Triggering the ADC is just,

//trigger a new set of measurements with an instruction that is the functional equivalent 
//of ADC_SoftwareStartConv(ADC1) which starts conversion of one group of regular conversions 
//and places the results into ADC_Results[8] by DMA transfer
ADC1->CR2 |= (uint32_t)ADC_CR2_SWSTART; /* Enable the selected ADC conversion for regular group */

drobison
Associate II
Posted on May 02, 2013 at 17:05

Thanks, this is an interesting example.  Something seems off about it, though.  Is this something you can download to the flash and run?  I don't see a vector table, or _start:.  Part of what I am interested is how to boot from user flash and what the vector table will look like.

ullasmann
Associate
Posted on May 02, 2013 at 17:29

http://www.ullasmann.eu/ARM.htm

Posted on May 02, 2013 at 17:49

Something seems off about it, though. Is this something you can download to the flash and run? I don't see a vector table, or _start:. Part of what I am interested is how to boot from user flash and what the vector table will look like.

The vector table can be very generic, I'd link it for 0x08000000, but zero would work equally well based on the shadowing. You should perhaps review the startup_stm32f4xx.s for the assorted platforms for desirable syntax.

Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
;..
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY

Reset_Handler PROC

;.. Code here gets executed when processor starts
 ENDP
 END 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 02, 2013 at 20:17

; Uses
; r0 32-bit unsigned number to output, destroyed
; r1,r2,r3 scratch, destroyed
_OutDecimal PROC
push {lr}
ldr r1, =0
push {r1} ; Stack NUL
ldr r2, =10 ; Base
_OutDecimal10 udiv r1, r0, r2 ; r1 = r0 / r2
mul r3, r1, r2 ; r3 = r1 * r2
rsb r3, r0 ; r3 = r0 % r2
orr r3, #'0' ; Remainder plus ASCII zero
push {r3} ; Stack Digit
movs r0,r1 ; Move quotient to dividend, zero check
bne _OutDecimal10
_OutDecimal20 pop {r0} ; Pop digit or NUL
orrs r0, r0 ; Zero check
beq _OutDecimal30 ; NUL
bl _OutChar
b _OutDecimal20
_OutDecimal30 pop {pc} ; sourcer32@gmail.com
ENDP ; _OutDecimal

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
drobison
Associate II
Posted on May 02, 2013 at 21:23

Thanks for your help.  I'm excited.  I got the vector table right, and was able to create a binary with

GNU Tools for ARM Embedded Processors

for windows. My first program is trivial.  I have the registers counting up and was able to confirm that through the st-link and free program from ST. Any tips for the cpu or programming it in assembly?  Any neat tricks you can share?

Posted on May 02, 2013 at 22:00

I got to M3 from ARM7/9, I have a bunch of ARM926 SoC and STR7, STR9 in there too, and it pushes some 30 years back from that to the original Acorn designs that ARM sprang from. I've worked through a lot of the ARM TRM's and found Joseph Yiu's book on the Cortex-M3 as a good contrasting source to those manuals.

A technique I use, and another colleague better described, is triangulation, ie take a lot of books and documentation, digest/skim, and then establish a view based on multiple perspectives. And also leveraging existing knowledge into new spaces.

I guess the clever tricks with ARM's ISA relate to the shifts and register side effects that make the instructions so powerful.

My mind's pretty fogged up with assembler for several dozen micros, so I'm probably not the best person to ask ''how do I start''. The assembler stuff I'm best known for is x86, but not many prospects there.

Maybe the best way would you to kick out a few ideas of what examples or snippets might be immediately helpful, and would fit in 50-100 lines, and work through those as building blocks you and others can apply.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
biuro
Associate II
Posted on January 07, 2014 at 10:42

Hi Clive,

I work on some projects using STM32F4 ( Keil5) and I see that you are familiar with the assembler

I want to mixture my C code with the assembler code.Saying the truth I want to start with the assembler- writing for example the watchdog settings in assembler and then mixture them with C.

I am familiar with C, know the structure of assembler, in-line assembler, but I dont know how to start. I want to be able to write myself some functions in assembler, for example time critical.

Could you please send me some code in assembler concerning such settings and tips how to mixture them?

I would appreciate your help.I would be very grateful. The matter is urgent.

Ted

biuro@tednet.pl

Posted on January 07, 2014 at 11:36

For

http://www.catb.org/~esr/faqs/smart-questions.html#urgent

one-on-one support you'll need to hire yourself a consultant.

Initializing and kicking the IWDG should just be a matter of implementing the load/store of constants. I can probably post some code fragment examples to the forum

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