2012-02-04 12 views
10

Sto cercando di ottenere un programma di tipo "Hello World" in esecuzione sul mio Beagleboard-xm rev. C, chiamando una funzione C puts dall'assemblaggio.Hello world, bare metal Beagleboard

Finora ho usato questo come un punto di riferimento: http://wiki.osdev.org/ARM_Beagleboard

Ecco quello che ho finora, ma non c'è uscita.

ciao.c

volatile unsigned int * const UART3DR = (unsigned int *)0x49020000; 

void puts(const char *s) { 
    while(*s != '\0') { 
    *UART3DR = (unsigned int)(*s); 
    s++; 
    } 
} 

void hello() { 
    puts("Hello, Beagleboard!\n"); 
} 

boot.asm

.global start 
start: 
    ldr sp, =stack_bottom 
    bl hello 
    b . 

linker.ld

ENTRY(start) 

MEMORY 
{ 
    ram : ORIGIN = 0x80200000, LENGTH = 0x10000 
} 

SECTIONS 
{ 
    .hello : { hello.o(.text) } > ram 
    .text : { *(.text) } > ram 
    .data : { *(.data) } > ram 
    .bss : { *(.bss) } > ram 
    . = . + 0x5000; /* 4kB of stack memory */ 
    stack_bottom = .; 

} 

Makefile

ARMGNU = arm-linux-gnueabi 

AOPS = --warn --fatal-warnings 
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding 

boot.bin: boot.asm 
    $(ARMGNU)-as boot.asm -o boot.o 
    $(ARMGNU)-gcc-4.6 -c $(COPS) hello.c -o hello.o 
    $(ARMGNU)-ld -T linker.ld hello.o boot.o -o boot.elf 
    $(ARMGNU)-objdump -D boot.elf > boot.list 
    $(ARMGNU)-objcopy boot.elf -O srec boot.srec 
    $(ARMGNU)-objcopy boot.elf -O binary boot.bin 

Utilizzando solo il file asm come questo funziona.

.equ UART3.BASE,  0x49020000 
start: 
    ldr r0,=UART3.BASE 
    mov r1,#'c' 

Ecco alcuni Beagleboard/Minicom informazioni correlate: http://paste.ubuntu.com/829072/

Tutti gli indicatori? :)


Ho anche provato

void hello() { 
    *UART3DR = 'c'; 
} 

sto usando minicom e inviare il file tramite Ymodem, poi cerco di eseguirlo con:

go 0x80200000 

hardware e software di controllo il flusso in minicom è spento.

risposta

3

che avrebbe dovuto lavorato per voi. Ecco il codice ho scavato dal via del ritorno quando, non provate su uno stasera BeagleBoard appena fatto che sia compilato, aveva lavorato in una sola volta ...

startup.s:

.code 32 

.globl _start 
_start: 

    bl main 
hang: b hang 

.globl PUT32 
PUT32: 
    str r1,[r0] 
    bx lr 

.globl GET32 
GET32: 
    ldr r0,[r0] 
    bx lr 

Ciao.c:

extern void PUT32 (unsigned int, unsigned int); 
extern unsigned int GET32 (unsigned int); 
void uart_send (unsigned char x) 
{ 
    while((GET32(0x49020014)&0x20)==0x00) continue; 
    PUT32(0x49020000,x); 
} 
void hexstring (unsigned int d) 
{ 
    //unsigned int ra; 
    unsigned int rb; 
    unsigned int rc; 

    rb=32; 
    while(1) 
    { 
     rb-=4; 
     rc=(d>>rb)&0xF; 
     if(rc>9) rc+=0x37; else rc+=0x30; 
     uart_send(rc); 
     if(rb==0) break; 
    } 
    uart_send(0x0D); 
    uart_send(0x0A); 
} 
int main (void) 
{ 
    hexstring(0x12345678); 
    return(0); 
} 

memmap (script del linker):

MEMORY 
{ 
    ram : ORIGIN = 0x82000000, LENGTH = 256K 
} 

SECTIONS 
{ 
    ROM : { startup.o } > ram 
} 

Makefile:

CROSS_COMPILE = arm-none-eabi 

AOPS = --warn --fatal-warnings 
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding 

all : hello.bin 

hello.bin : startup.o hello.o memmap 
    $(CROSS_COMPILE)-ld startup.o hello.o -T memmap -o hello.elf 
    $(CROSS_COMPILE)-objdump -D hello.elf > hello.list 
    $(CROSS_COMPILE)-objcopy hello.elf -O binary hello.bin 

startup.o : startup.s 
    $(CROSS_COMPILE)-as $(AOPS) startup.s -o startup.o 

hello.o : hello.c 
    $(CROSS_COMPILE)-gcc -c $(COPS) hello.c -o hello.o 

clean : 
    rm -f *.o 
    rm -f *.elf 
    rm -f *.bin 
    rm -f *.list 

sembra che ho appena lasciato lo stack pointer ovunque il bootloader aveva. Allo stesso modo, come voi, pensate che il bootloader abbia inizializzato la porta seriale.

presumo si ha accesso di lavoro porta seriale, si vede uboot e siete in grado di digitare i comandi per scaricare questo programma (xmodem, o qualsiasi altra cosa) nelle schede ram? Se non puoi farlo allora potrebbe essere che non sei connesso alla porta seriale a destra. la porta seriale di beagleboards è fasulla, potrebbe essere necessario creare il proprio cavo.

+0

Funziona, grazie. Ora ho bisogno di capire cosa sto facendo male. È il primo pezzo di codice! = ASM che effettivamente stampa qualcosa. – farnsworth

+0

Per ulteriori riferimenti se qualcuno ha problemi con questo. Ho modificato il Makefile CROSS_COMPILE = arm-none-linux-gnueabi mentre sto usando la toolchain di codesourcery per linux. Caricato il file con loady via ymodem, e mentre de memmap ha origine a 0x82000000 sono andato avanti e l'ho eseguito con 0x80200000 anche se si imposta l'origine su 0x82000000. – farnsworth

+0

sia arm-none-linux-gnueabi che arm-none-eabi provengono da codesourcery, se non fai nessuna chiamata di sistema allora funzionerà. Presumibilmente la versione non linux è migliore se usi le chiamate gcclib (usa divide o modulo o cose del genere). –

2

Non è possibile scrivere ciecamente una stringa di caratteri su un UART, è necessario controllare lo stato su ciascun carattere, funziona nell'esempio di un singolo carattere perché l'UART sarà sempre pronto per il primo carattere, ma per il secondo e i successivi caratteri è necessario eseguire il polling (o meglio ancora usare un ISR, ma camminiamo prima di correre).

C'è qualche buon esempio di codice qui: http://hardwarefreak.wordpress.com/2011/08/30/some-experience-with-the-beagleboard-xm-part-2/

+0

Scopri i LE. Ho anche provato a stampare un solo carattere e non ho avuto alcun risultato, il bell'articolo controllerà se risolve il problema, anche se mi piacerebbe davvero sapere cosa faccio di sbagliato e dove. – farnsworth

+0

Forse prova ad eseguire il codice dal link che ho dato sopra e vedere se funziona? Se funziona, puoi confrontare il tuo codice e vedere cosa c'è di diverso? –

+0

Provato, non funziona. – farnsworth

2

ho abbastanza repetation commentare .. Ma il mio answere a

Opere in entrambi i casi. Ora la cosa strana è che posso stampare singoli caratteri con uart_send ('c') per esempio, ma non posso stampare stringhe print_string (char * str) {while (* str! = '\ 0') uart_send (* str ++); } print_string ("Test"); . Qualche idea su questo?

è:

a scrivere più velocemente nel buffer di output, come UART è in grado di inviare .. così hai di controllare, se il buffer di output è vuoto, prima di inviare un nuovo personaggio.

ho fatto questo nel codice sul mio blog (http://hardwarefreak.wordpress.com/2011/08/30/some-experience-with-the-beagleboard-xm-part-2/)

+0

Lo sto facendo :), ho anche spostato rodata su .text eppure nulla sullo schermo tranne se faccio print_char ('c'); – farnsworth

+0

Mmh .. Gli interrupt sono abilitati? Posso vedere il tuo codice e confrontarlo con il mio? – Hardwarefreak

+0

scusate, ho incasinato l'indirizzo di partenza, grazie per il vostro tempo e il vostro ottimo esempio :) – farnsworth