Keil stm32, используя сборку, scatter-файл и c. Как экспортировать точку входа c кодом в сборку? - PullRequest
2 голосов
/ 18 марта 2019

Чтобы объединить .c и сборку , я хочу передать начальный адрес моего кода .c и программный микроконтроллер, чтобы узнать, что его программа запускается по этому адресу. Поскольку я записываю свой файл запуска в сборку , мне нужно передать начальный адрес кода .c в сборку, а затем записать этот адрес в определенную область памяти микроконтроллера (поэтому микроконтроллер может начать выполнение по этому адресу после RESET )

Попытка создать проект для stm32f103 в Keil с такой структурой:

Какой-то файл .c, например main.c (для основной части программы).
Файл запуска на ассемблере. Который получает адрес входа в функцию, записанную в каком-то файле .c, для передачи в Reset_Handler
Scatter-файл, записанный таким образом:

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, которому требуется точка входа .c (начальный адрес), переданная __main, выглядит следующим образом:

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

Линкер такой же, как упомянутый выше. Сборка проекта прошла успешно.

1 Ответ

2 голосов
/ 18 марта 2019

Используя цепочку инструментов 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
}

1012 * сборка *

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}

конечно, это должно быть помещено во вспышку в нужном месте с помощью какого-либо инструмента.

таблица векторов по логике отображается в 0x00000000 в семействе stm32.

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

и в этом минимальном коде обработчик сброса вызывает код C, который код C теряет и возвращает. Технически это полностью фунтокальная программа для большинства stm32 (измените init стека на меньшее значение для тех, у кого меньше оперативной памяти, скажем, 0x20000400, и она должна работать где угодно, используя -mthumb сама по себе (armv4t) или добавляя cortex-m0. Ну, ладно, не armv8ms технически они могут не поддерживать весь armv6m, но тот, о котором я знаю, делает.

У меня нет Киля, так что я не знаю, как это перевести, но это не должно быть слишком натянуто, просто синтаксис.

...