问题
I'm trying to get a 'hello world' type program running on my Beagleboard-xm rev. C, by calling a C puts
function from assembly.
So far I've been using this as a reference: http://wiki.osdev.org/ARM_Beagleboard
Here's what I have so far, but there's no output.
hello.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
Using just the asm file like this works.
.equ UART3.BASE, 0x49020000
start:
ldr r0,=UART3.BASE
mov r1,#'c'
Here are some Beagleboard/minicom related info: http://paste.ubuntu.com/829072/
Any pointers? :)
I also tried
void hello() {
*UART3DR = 'c';
}
I'm using minicom and send the file via ymodem, then I try to run it with:
go 0x80200000
Hardware and software control flow in minicom are off.
回答1:
that should have worked for you. Here is some code I dug up from way back when, did not try it on a beagleboard tonight just made sure it compiled, it had worked at one time...
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
hello.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 (linker script):
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
Looks like I just left the stack pointer wherever the bootloader had it. Likewise, as you, assumed the bootloader had initialized the serial port.
I assume you have serial port access working, you see uboot and you are able to type commands in order to download this program (xmodem, or whatever) into the boards ram? If you cant do that then it may be you are not connected to the serial port right. the beagleboards serial port is screwy, might need to make your own cable.
回答2:
You can't just blindly write a string of characters to a UART - you need to check status on each character - it works in the single character example because the UART is always going to be ready for the first character, but for the second and subsequent characters you need to poll (or better yet use an ISR, but let's walk before we run).
There's some good example code here: http://hardwarefreak.wordpress.com/2011/08/30/some-experience-with-the-beagleboard-xm-part-2/
回答3:
I've not enough repetation to comment.. But my answere to
Works either way. Now the weird thing is that I can print individual characters with with uart_send('c') for example, but cannot print strings print_string(char *str){ while (*str != '\0') uart_send (*str++); } print_string("Test"); . Any thoughts on this?
is:
You write faster in the output buffer, as UART is able to send.. So you've to check, if the output buffer is empty, before you send a new character.
I've done this in the code on my blog (http://hardwarefreak.wordpress.com/2011/08/30/some-experience-with-the-beagleboard-xm-part-2/)
来源:https://stackoverflow.com/questions/9142951/hello-world-bare-metal-beagleboard