2017-05-21 5 views
1

J'essaie de faire un système embarqué. J'ai du code C, cependant, avant que la fonction principale fonctionne, une pré-initialisation est nécessaire. Est-il possible de dire au compilateur gcc qu'une certaine fonction doit être placée dans la section .init plutôt que dans la section .text?Comment assigner explicitement une section en code C (comme .text, .init, .fini) (principalement pour le bras)?

Voici le 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: en utilisant __attribute __ (section ("init")) ne semble pas fonctionner

Répondre

2

ne comprends pas pourquoi vous pensez que vous avez besoin d'une section .init pour baremetal. Un exemple de travail complet pour une pi zéro (en utilisant .init)

de start.s

.section .init 

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

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

construction

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 

Notez que si vous le faites correctement, vous ne avez pas besoin init .bss dans le bootstrap (mis .data après .bss et assurez-vous qu'il ya au moins un élément dans .data)

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 

si vous voulez dans des endroits séparés alors oui votre script de linker devient instantanément plus compliqué ainsi que votre bootstrap (avec beaucoup de place pour l'erreur).

La seule chose que le travail supplémentaire que .init vous permet d'acheter ici est l'OMI que vous pouvez réarranger la ligne de commande de liaison

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

se débarrasser de .init tous ensemble

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 

Non questions, fonctionne bien. Il suffit de savoir que avec gnu ld (et probablement d'autres) si vous n'appelez pas quelque chose dans le script de l'éditeur de liens, alors il remplit les choses dans l'ordre présenté (sur la ligne de commande). Si un compilateur utilise des sections ou leur nom est spécifique au compilateur, vous devez donc creuser dans les options spécifiques du compilateur pour voir s'il y en a pour changer les valeurs par défaut. Utiliser C pour amorcer C est plus de travail que de valeur, gcc acceptera les fichiers d'assemblage si c'est un problème Makefile avec lequel vous rencontrez des problèmes, il y a très rarement une raison d'utiliser l'assemblage en ligne. fiable et maintenable. En réalité, ces choses sont triviales.

.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 
assemblage réel

est généralement utilisé pour bootstrapping, pas de jeux de compilateur requis, pas besoin de revenir en arrière et de maintenir le code si souvent à cause tous les jeux du compilateur, le portage est plus facile, etc.