uart
uart.h
c
#if !defined(_UART_H)
#define _UART_H
#include <stdint.h>
void uart_putc(const char c);
void uart_puthex(uint64_t n);
void uart_puts(const char *s);
#endif /* _UART_H */
uart.c
c
#include "uart.h"
volatile unsigned int * const UART0DR = (unsigned int *) 0x09000000;
volatile unsigned int * const UART0FR = (unsigned int *) 0x09000018;
void uart_putc(const char c)
{
// Wait for UART to become ready to transmit.
while ((*UART0FR) & (1 << 5)) { }
*UART0DR = c; /* Transmit char */
}
void uart_puthex(uint64_t n)
{
const char *hexdigits = "0123456789ABCDEF";
uart_putc('0');
uart_putc('x');
for (int i = 60; i >= 0; i -= 4){
uart_putc(hexdigits[(n >> i) & 0xf]);
if (i == 32)
uart_putc(' ');
}
}
void uart_puts(const char *s)
{
for (int i = 0; s[i] != '\0'; i ++)
uart_putc((unsigned char)s[i]);
}
测试uart打印
test.c
c
#include "uart.h"
void printf_hello_world()
{
uart_puts("hello world\n");
}
entry | 设置栈 && 调用打印
reset.S
c
.global reset
reset:
msr spsel, #0
ldr x0, =runtime_sp
mov sp, x0
bl printf_hello_world
b .
链接脚本
main.ld.S
c
ENTRY(reset)
MEMORY {
rom (rx) : org = 0x0, len = 16M
runtime_ram (rwx) : org = 0x60000000, len = 512M
}
SECTIONS {
.text : {
reset.o (.text);
uart.o (.text);
test.o (.text);
} > rom
runtime_sp = ORIGIN(runtime_ram) + LENGTH(runtime_ram);
}
Makefile
makefile
AS=aarch64-linux-gnu-as
LD=aarch64-linux-gnu-ld
CC=aarch64-linux-gnu-gcc
OBJCOPY=aarch64-linux-gnu-objcopy
DD=dd
AS_SOURCES=reset.S
AS_OBJS=$(subst .S,.o,$(AS_SOURCES))
LD_SCRIPT=main.ld.S
C_SOURCES=$(wildcard *.c)
C_OBJS=$(subst .c,.o,$(C_SOURCES))
ELF=test.elf
BIN=test.bin
FLASH=flash.bin
$(BIN): $(ELF)
$(OBJCOPY) -O binary $< $@
$(ELF): $(AS_OBJS) $(C_OBJS)
$(LD) -T $(LD_SCRIPT) $^ -o $@ -N
$(AS_OBJS):%.o:%.S
$(CC) -o $@ -c $< -DDEBUG
$(C_OBJS):%.o:%.c
$(CC) -o $@ -c $<
flash: $(BIN)
rm -rf $(FLASH)
dd if=/dev/zero of=$(FLASH) bs=16M count=1
dd if=$< of=$(FLASH) conv=notrunc
run: flash
qemu-system-aarch64 -machine virt,secure=on -cpu cortex-a53 -bios flash.bin -m 1024 -nographic
clean:
rm -rf $(AS_OBJS) $(ELF) $(BIN) $(C_OBJS)
.PHONY: flash run clean
测试
bash
$ make flash
aarch64-linux-gnu-gcc -o reset.o -c reset.S -DDEBUG
aarch64-linux-gnu-gcc -o test.o -c test.c
aarch64-linux-gnu-gcc -o uart.o -c uart.c
aarch64-linux-gnu-ld -T main.ld.S reset.o test.o uart.o -o test.elf -N
aarch64-linux-gnu-objcopy -O binary test.elf test.bin
rm -rf flash.bin
dd if=/dev/zero of=flash.bin bs=16M count=1
1+0 records in
1+0 records out
16777216 bytes (17 MB, 16 MiB) copied, 0.0141096 s, 1.2 GB/s
dd if=test.bin of=flash.bin conv=notrunc
1+1 records in
1+1 records out
560 bytes copied, 0.000171749 s, 3.3 MB/s