2013-04-30 03:02 PM
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-c2013-05-01 12:50 PM
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
2013-05-02 05:43 AM
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 */
2013-05-02 08:05 AM
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.
2013-05-02 08:29 AM
2013-05-02 08:49 AM
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
2013-05-02 11:17 AM
; 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
2013-05-02 12:23 PM
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?2013-05-02 01:00 PM
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.2014-01-07 01:42 AM
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.pl2014-01-07 02:36 AM
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