2017-05-21 1 views
1

Ich versuche ein Embedded System zu machen. Ich habe einige C-Code, aber bevor die Hauptfunktion ausgeführt wird, ist einige Vor-Initialisierung erforderlich. Gibt es eine Möglichkeit, dem GCC-Compiler mitzuteilen, dass eine bestimmte Funktion in den .init-Abschnitt und nicht in den .text-Abschnitt eingefügt werden soll?Wie man explizit einen Abschnitt im C-Code (wie .text, .init, .fini) (hauptsächlich für Arm) zuweist?

Dies ist der Code:

#include <stdint.h> 

#define REGISTERS_BASE 0x3F000000 
#define MAIL_BASE 0xB880 // Base address for the mailbox registers 
// This bit is set in the status register if there is no space to write into the mailbox 
#define MAIL_FULL 0x80000000 
// This bit is set in the status register if there is nothing to read from the mailbox 
#define MAIL_EMPTY 0x40000000 

struct Message 
{ 
    uint32_t messageSize; 
    uint32_t requestCode; 
    uint32_t tagID; 
    uint32_t bufferSize; 
    uint32_t requestSize; 
    uint32_t pinNum; 
    uint32_t on_off_switch; 
    uint32_t end; 
}; 

struct Message m = 
{ 
    .messageSize = sizeof(struct Message), 
    .requestCode =0, 
    .tagID = 0x00038041, 
    .bufferSize = 8, 
    .requestSize =0, 
    .pinNum = 130, 
    .on_off_switch = 1, 
    .end = 0, 
}; 

void _start() 
{ 
    __asm__ 
    (
    "mov sp, #0x8000 \n" 
    "b main" 
); 
} 

/** Main function - we'll never return from here */ 
int main(void) 
{ 
    uint32_t mailbox = MAIL_BASE + REGISTERS_BASE + 0x18; 
    volatile uint32_t status; 

    do 
    { 
    status = *(volatile uint32_t *)(mailbox); 
    } 
    while((status & 0x80000000)); 

    *(volatile uint32_t *)(MAIL_BASE + REGISTERS_BASE + 0x20) = ((uint32_t)(&m) & 0xfffffff0) | (uint32_t)(8); 

    while(1); 
} 

EDIT: __attribute __ mit (Abschnitt ("init")) scheint nicht zu arbeiten verstehen

Antwort

2

Dont, warum Sie einen .init Abschnitt benötigen für Barmetal. Ein vollständiges Arbeitsbeispiel für einen PI-Null (unter Verwendung von .init)

start.s

.section .init 

.globl _start 
_start: 
    mov sp,#0x8000 
    bl centry 
    b . 

so.c

unsigned int data=5; 
unsigned int bss; 

unsigned int centry (void) 
{ 
    return(0); 
} 

so.ld

MEMORY 
{ 
    ram : ORIGIN = 0x8000, LENGTH = 0x1000 
} 

SECTIONS 
{ 
    .init : { *(.init*) } > ram 
    .text : { *(.text*) } > ram 
    .bss : { *(.bss*) } > ram 
    .data : { *(.data*) } > ram 
} 

build

arm-none-eabi-as start.s -o start.o 
arm-none-eabi-gcc -O2 -c so.c -o so.o 
arm-none-eabi-ld -T so.ld start.o so.o -o so.elf 
arm-none-eabi-objdump -D so.elf 

Disassembly of section .init: 

00008000 <_start>: 
    8000: e3a0d902 mov sp, #32768 ; 0x8000 
    8004: eb000000 bl 800c <centry> 
    8008: eafffffe b 8008 <_start+0x8> 

Disassembly of section .text: 

0000800c <centry>: 
    800c: e3a00000 mov r0, #0 
    8010: e12fff1e bx lr 

Disassembly of section .bss: 

00008014 <bss>: 
    8014: 00000000 andeq r0, r0, r0 

Disassembly of section .data: 

00008018 <data>: 
    8018: 00000005 andeq r0, r0, r5 

Hinweis, wenn man es richtig macht Sie in der Bootstrap init .bss müssen nicht (Put .data nach .bss und stellen Sie sicher, dass es mindestens einen Artikel in .data ist)

hexdump -C so.bin 
00000000 02 d9 a0 e3 00 00 00 eb fe ff ff ea 00 00 a0 e3 |................| 
00000010 1e ff 2f e1 00 00 00 00 05 00 00 00    |../.........| 
0000001c 

wenn Sie wollen, an getrennten Stellen dann ja wird dein Linker Skript sofort komplizierter sowie dein Bootstrap (mit viel Platz für Fehler).

Das einzige, was die zusätzliche Arbeit, die .init Sie hier IMO kauft, ist, dass Sie die Linker-Befehlszeile

arm-none-eabi-ld -T so.ld so.o start.o -o so.elf 

alle zusammen von .init loszuwerden neu ordnen, können

Disassembly of section .text: 

00008000 <_start>: 
    8000: e3a0d902 mov sp, #32768 ; 0x8000 
    8004: eb000000 bl 800c <centry> 
    8008: eafffffe b 8008 <_start+0x8> 

0000800c <centry>: 
    800c: e3a00000 mov r0, #0 
    8010: e12fff1e bx lr 

Disassembly of section .bss: 

00008014 <bss>: 
    8014: 00000000 andeq r0, r0, r0 

Disassembly of section .data: 

00008018 <data>: 
    8018: 00000005 andeq r0, r0, r5 

Nein Probleme, funktioniert gut. Ich muss nur wissen, dass mit gnu ld (und wahrscheinlich anderen), wenn Sie nicht etwas im Linker-Skript aufrufen, es Dinge in der angegebenen Reihenfolge (in der Befehlszeile) füllt.

Ob ein Compiler Abschnitte verwendet oder wie sie benannt sind, ist compilerspezifisch. Sie müssen also in die Compiler-spezifischen Optionen einsteigen, um zu sehen, ob es irgendwelche gibt, um die Standardwerte zu ändern. Die Verwendung von C zum Booten von C ist mehr Arbeit, als es wert ist, gcc akzeptiert Assemblydateien, wenn es ein Makefile-Problem ist, mit dem Sie Probleme haben. In seltenen Fällen gibt es einen Grund, Inline-Assembly zu verwenden, wenn Sie echte Assembly verwenden können zuverlässig und wartbar. In der realen Versammlung sind diese Dinge trivial. jeder so oft den Code zurück zu gehen und zu warten, weil der Compiler Spiele

.section .helloworld 

.globl _start 
_start: 
    mov sp,#0x8000 
    bl centry 
    b . 


Disassembly of section .helloworld: 

00008000 <_start>: 
    8000: e3a0d902 mov sp, #32768 ; 0x8000 
    8004: ebfffffd bl 8000 <_start> 
    8008: eafffffe b 8008 <bss> 

Disassembly of section .text: 

00008000 <centry>: 
    8000: e3a00000 mov r0, #0 
    8004: e12fff1e bx lr 

Disassembly of section .bss: 

00008008 <bss>: 
    8008: 00000000 andeq r0, r0, r0 

Disassembly of section .data: 

0000800c <data>: 
    800c: 00000005 andeq r0, r0, r5 

reale Montage ist für Bootstrapping, keine Compiler Spiele benötigt im Allgemeinen verwendet, keine benötigen, Portierung ist einfacher, usw.

Verwandte Themen