Skip to main content
Graduate II
February 10, 2025
Solved

Code 16 and Code 32 on STM32F103C8T6

  • February 10, 2025
  • 4 replies
  • 2802 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 

     

    4 replies

    Graduate II
    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
    JerryMC22Author
    Graduate II
    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 ?

    Graduate II
    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

    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

     

    Graduate
    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.

    JerryMC22Author
    Graduate II
    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)
     }
    }

     

    Graduate
    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?

    JerryMC22Author
    Graduate II
    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
    Graduate II
    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  ... :)