簡體   English   中英

Keil stm32,使用匯編、分散文件和c。 如何將c代碼入口點導出到程序集?

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

為了結合 .c 和 assembly ,我想傳遞我的 .c 代碼的起始地址,並對微控制器進行編程以知道它的程序從該地址開始。 當我在匯編中編寫我的啟動文件時,我需要將 .c 代碼起始地址傳遞給匯編,然后將此地址寫入微控制器的特定內存區域(以便微控制器可以在RESET后在此地址上開始執行)

嘗試使用以下結構在 Keil 中為 stm32f103 創建一個項目:

一些 .c 文件,例如 main.c(用於程序的主要部分)。
匯編語言的啟動文件。 獲取寫入一些.c文件的函數的入口地址,傳遞給Reset_Handler
散點文件,這樣寫:

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)
  }
}

問題是將入口點傳遞給 .c 函數。 Reset_Handler 需要 __main 傳遞的 .c 入口點(起始地址),如下所示:

Reset_Handler PROC

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

    ENDP

關於入口點 __main,作為一個程序集相關問題的答案被寫成:

__main() 是編譯器提供的 C 代碼入口點。 它不是您編寫的 main() 函數,而是在調用您的 `main()' 函數之前對標准庫、靜態數據、堆執行初始化。

那么,如何在我的程序集文件中獲取這個入口點呢?

編輯>> 如果有人對 KEIL 的解決方案感興趣,就在這里,就這么簡單!

簡單組裝startup.s文件:

        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

簡單的c文件:

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

鏈接器與上面提到的相同。 項目構建成功。

例如使用 gnu 工具鏈:

引導程序:

.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 入口點(函數名稱不相關,有時使用 main() 會增加垃圾,取決於編譯器/工具鏈)

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

鏈接腳本

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

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

建造

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

結果(所有拇指版本)

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}

當然,這必須用一些工具放在閃存中的正確位置。

向量表通過邏輯映射到 stm32 系列中的 0x00000000。

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

在這個最小的代碼中,重置處理程序調用 C 代碼,C 代碼會弄亂並返回。 從技術上講,這是一個適用於大多數 stm32s 的全功能程序(對於那些 ram 較少的人來說,將堆棧 init 更改為較小的值,比如 0x20000400,它應該可以通過單獨使用 -mthumb(armv4t)或添加 cortex-m0 在任何地方工作。好吧,不是 armv8ms從技術上講,它們不能支持所有 armv6m,但我所知道的該領域的支持。

我沒有基爾,所以不知道如何翻譯成那個,但它不應該是一個延伸,只是語法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM