简体   繁体   中英

Keil stm32, using assembly, scatter file and c. How to export c code entry point to assembly?

In order to combine .c and assembly , I want to pass start address of my .c code , and program microcontroller to know that its program starts at that address. As I am writing my startup file in assembly , I need to pass .c code starting address to assembly, and then to write this address to the specific memory region of microcontroller ( so the microcontroller can start execution on this address after RESET )

Trying to create a project for stm32f103 in Keil with this structure:

Some .c file, for example main.c (for the main part of the program).
Startup file in assembly language. Which gets the adress of entry to the function written in some .c file, to be passed to Reset_Handler
Scatter file, written in this way:

LR_IROM1 0x08000000 0x00010000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
   *.o (RESET, +First)   ; RESET is code section with I.V.T.
   * (InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00005000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

The problem is passing the entry point to the .c function. Reset_Handler, which needs .c entry point(starting adress) passed by __main, looks like this:

Reset_Handler PROC

    EXPORT Reset_Handler [WEAK]
    IMPORT __main
    LDR R0, =__main
    BX R0

    ENDP

bout entry point __main, as a answer for one assembly raleted question was written:

__main() is the compiler supplied entry point for your C code. It is not the main() function you write, but performs initialisation for the standard library, static data, the heap before calling your `main()' function.

So, how to get this entry point in my assembly file?

Edit>> If somebody is interested in solution for KEIL, here it is, its all that simple!

Simple assembly startup.s file:

        AREA STACK, NOINIT, READWRITE
        SPACE 0x400       
Stack_top                 

        AREA RESET, DATA, READONLY
        dcd Stack_top     
        dcd Reset_Handler



        EXPORT _InitMC
        IMPORT notmain

        AREA PROGRAM, CODE, READONLY

Reset_Handler PROC
        bl notmain
        ENDP

_InitMC   PROC          ;start of the assembly procedure
Loop
        b Loop          ;infinite loop
        ENDP

        END

Simple c file:

extern int _InitMC();
int notmain(void) {
    _InitMC();
    return 0;
}

Linker is the same as the one mentioned above. Project build was successful.

Using the gnu toolchain for example:

bootstrap:

.cpu cortex-m0
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word loop
.word loop
.word loop

.thumb_func
reset:
    bl notmain
    b loop
.thumb_func
loop:   b .

.align

.thumb_func
.globl fun
fun:
    bx lr

.end

C entry point (function name is not relevant, sometimes using main() adds garbage, depends on the compiler/toolchain)

void fun ( unsigned int );
int notmain ( void )
{
    unsigned int ra;
    for(ra=0;ra<1000;ra++) fun(ra);
    return(0);
}

linker script

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

build

arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m0 -march=armv6-m -c so.c -o so.thumb.o
arm-none-eabi-ld -o so.thumb.elf -T flash.ld flash.o so.thumb.o
arm-none-eabi-objdump -D so.thumb.elf > so.thumb.list
arm-none-eabi-objcopy so.thumb.elf so.thumb.bin -O binary
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m3 -march=armv7-m -c so.c -o so.thumb2.o
arm-none-eabi-ld -o so.thumb2.elf -T flash.ld flash.o so.thumb2.o
arm-none-eabi-objdump -D so.thumb2.elf > so.thumb2.list
arm-none-eabi-objcopy so.thumb2.elf so.thumb2.bin -O binary

result (all thumb versions)

Disassembly of section .text:

08000000 <_start>:
 8000000:   20001000
 8000004:   08000015
 8000008:   0800001b
 800000c:   0800001b
 8000010:   0800001b

08000014 <reset>:
 8000014:   f000 f804   bl  8000020 <notmain>
 8000018:   e7ff        b.n 800001a <loop>

0800001a <loop>:
 800001a:   e7fe        b.n 800001a <loop>

0800001c <fun>:
 800001c:   4770        bx  lr
 800001e:   46c0        nop         ; (mov r8, r8)

08000020 <notmain>:
 8000020:   b570        push    {r4, r5, r6, lr}
 8000022:   25fa        movs    r5, #250    ; 0xfa
 8000024:   2400        movs    r4, #0
 8000026:   00ad        lsls    r5, r5, #2
 8000028:   0020        movs    r0, r4
 800002a:   3401        adds    r4, #1
 800002c:   f7ff fff6   bl  800001c <fun>
 8000030:   42ac        cmp r4, r5
 8000032:   d1f9        bne.n   8000028 <notmain+0x8>
 8000034:   2000        movs    r0, #0
 8000036:   bd70        pop {r4, r5, r6, pc}

of course this has to be placed in flash at the right place with some tool.

the vector table is mapped by logic to 0x00000000 in the stm32 family.

08000000 <_start>:
 8000000:   20001000
 8000004:   08000015 <---- reset ORR 1

and in this minimal code the reset handler calls the C code the C code messes around and returns. Technically a fully functoinal program for most stm32s (change the stack init to a smaller value for those with less ram say 0x20000400 and it should work anywhere by using -mthumb by itself (armv4t) or adding the cortex-m0. well okay not the armv8ms they can technically not support all of armv6m but the one in the field I know about does.

I dont have Kiel so dont know how to translate to that, but it shouldnt be much of a stretch, just syntax.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM