Skip to main content
Associate III
February 10, 2025
Solved

Code 16 and Code 32 on STM32F103C8T6

  • February 10, 2025
  • 20 replies
  • 2897 views

Hi,

Can someone explain me why I have to use "+1" in vector table of STM32F103C8T6: 

vectors:
 .word STACKINIT @ stack pointer
 .word _start + 1 @ reset vector 
 .word _nmi_handler + 1 @
 .word _hard_fault + 1 @
 .word _memory_fault + 1 @
 .word _bus_fault + 1 @
 .word _usage_fault + 1 @

 instead of:  

 .word STACKINIT @ stack pointer 
 .word _start @ reset vector 
 .word _nmi_handler @
 .word _hard_fault @
 .word _memory_fault @
 .word _bus_fault @
 .word _usage_fault @

I thought that STM32F103C8T6 is 32bit processor and thus I can use:

 .code 32 
 .cpu cortex-m3
 .syntax unified

But it is NOT true. I can use only THUMB (code 16) instructions.

 

This topic has been closed for replies.
Best answer by JerryMC22

I finally found interesting solution - see below, it is possible to fix the reset handler address as e.g. 0x301 and reset handler place to .org 0x300 :)  cute solution

 

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



 .org 0x300
Reset_Handler:
 ldr sp, =STACKINIT 

 

20 replies

Tesla DeLorean
Guru
February 10, 2025

The registers and operations are 32-bit, but the Cortex-Mx only supports Thumb(2) which consists of 16-bit opcodes

 .syntax unified
 .cpu cortex-m3
 .fpu softvfp
 .thumb
Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
JerryMC22Author
Associate III
February 10, 2025

ok, so may I use:

 .syntax unified
 .cpu cortex-m3
 .code 16
 .aligh 2

and omit the "+1" in my vector table ?

Tesla DeLorean
Guru
February 10, 2025

Shouldn't be necessary if the assembler is in the right mode

Perhaps look at examples in the repo

STM32Cube_FW_F1_V1.6.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\gcc\startup_stm32f103xb.s

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
KnarfB
Super User
February 10, 2025

yes, 32-bit ALU, registers, data buses and addressing. 16-bit "compressed" thumb instructions give higher code density, less memory access for a subset of commonly used instructions. 

hth

KnarfB

 

gbm
Super User
February 10, 2025

Generally you don't need to use these "+1"s if the assembler correctly recognizes the symbol as Thumb code label, which is quite easy to achieve - look at the default startupxxxx.s files supplied with STM32Cube or Keil MDK-ARM and check the "thumb" directives.

Of course every Cortex-M is a 32/bit processor but in Thumb instruction set some instructions are encoded as 16-bits and the others, more complex or less frequently used, as 32-bits.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
JerryMC22Author
Associate III
February 10, 2025

I have correctly directed thumb instructions by:

 

 .syntax unified
 .cpu cortex-m3
 .fpu softvfp
 .thumb

in my code, but I have to use the "+1" still. If I omit it the processor does not run. My complette code is:

but I still do not see the "problem" :( I am SAD

@ arm-none-eabi-as -mcpu=cortex-m3 LED.s -o LED.o
@ arm-none-eabi-ld -v -T stm32.ld -o LED.elf LED.o 
@ arm-none-eabi-objcopy -O binary LED.elf LED.bin
@

@@@ Directives
 .code 16 @ (same as saying '.code 16')
 .cpu cortex-m3
 .syntax unified
 .fpu softvfp
 .section .text._start 

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

 .equ LEDDELAY, 0x80000

.section .text
 .align
 .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 31,30 to 0x00
 @@ and bits 29,28 to 0x10 to be a push-pull output (up to 20 MHz) 
 @@ to '0010'.

 ldr r6, = GPIOB_CRH
 mov r0, 0x20000000
 str r0, [r6]

 @@ Load R2 and R3 with the "on" and "off" constants, 0 is on, 1 is off
 mov r2, 0x0000 @ 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, 0x01
 bne delay1

 str r3, [r6] @ set Port b, pin 15, turning off LED
 ldr r1, = LEDDELAY
delay2:
 subs r1, 0x01
 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

 

/* Simple linker script for the STM32 ARM Cortex M3. Link the text
 of the program into on-board flash and use on-board RAM for data and stack.
*/

SECTIONS
{
 /* interrupt vectors start at zero */
 . = 0x08000000; /* start of flash */

 .text : { *(.text) }

 /* constant data follows code but still in flash */
 .data :
 {
 *(.data)
 *(.rom)
 }

 /* internal RAM starts at 0x20000000 */
 . = 0x20000000;
 .ram : { *(.ram) }

 .bss :
 {
 *(.bss)
 *(.ram)
 }
}

 

gbm
Super User
February 10, 2025

And why exactly don't you use the working, good startupxxx.s file as a starting point and reference. Also, you ignore all the remarks from the posts above on using some form of THUMB directive for the assembler. In addition to that, your linker script file looks strange. .data section should go to RAM - again, why don't you compare your bad files against the working ones?

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
JerryMC22Author
Associate III
February 11, 2025

I am trying to learn "how to" with STM32. This is my first touch. That is all.

So, I tried to add ".org 201" to "create" the "odd" address but program is not working it is very suspicious.

 

@@@ Directives
 .code 16 @ (same as saying '.code 16')
 .cpu cortex-m3
 .syntax unified
 .fpu softvfp
 .section .text.Reset_Handler
 @ .weak Reset_Handler
 @ .type Reset_Handler, %function /* this should be ODD in thumb/16-bit mode */
 @ .size Reset_Handler, .-Reset_Handler /* this code does not compile my compiler it ends with error */


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

 .equ LEDDELAY, 0x80000

.section .text
 @ .align 2
 .org 0

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


 .org 0x201
Reset_Handler:
 ldr sp, =STACKINIT 

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

- it is very 

JerryMC22Author
Associate III
February 11, 2025

I finally found interesting information:

2.3.4 Vector table
The vector table contains the reset value of the stack pointer, and the start addresses, also
called exception vectors, for all exception handlers. Figure 11 on page 40 shows the order
of the exception vectors in the vector table. The least-significant bit of each vector must be
1, indicating that the exception handler is Thumb code.

 

ok, "least-significant bit of each vector"  there is one simple way to add the "+1".

write:   .word Reset_Handler +1   :)

or .... and tis is very QUEER - write these two commands:

 

.weak Reset_Handler
.type Reset_Handler, %function

 

:)  I really do understand to GNU STM32 assembler  ... :)