写一个bare metal程序,点亮led灯,和输出串口,使用uboot go执行:
1 创建程序入口start.S,这个需要用汇编写,目的是跳转到main函数。
$ cat start.S
.text
.global _start
_start:
b main
2 创建led.c
这个是用c写的,里面有一个main函数。
3 创建链接脚本bare.lds
$ cat bare.lds
SECTIONS
{
. = 0x46000000;
.text : { *(.text) }
.data : { *(.data) }
}
4 创建Makefile
$ cat Makefile
CROSS_COMPILE := aarch64-openwrt-linux-
CC := $(CROSS_COMPILE)gcc
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
all:
$(AS) -o start.o start.S
$(CC) -c -g -nostdinc -o led.o led.c
$(LD) -o led.elf -T bare.lds start.o led.o
$(OBJCOPY) -O binary -S led.elf led.bin
$(OBJDUMP) -S led.elf > led.elf.dis
$(OBJDUMP) -b binary --adjust-vma=0x46000000 -m aarch64 -D led.bin > led.bin.dis
cp led.bin /work/tftproot/
直接展示代码如下:
DIR0_SET是设置GPIO为输出模式。为1的位将设置为输出模式,为0不变。
OUT0_CLR/OUT0_SET分别设置GPIO输出为0和1。为0不变,为1清除或设置。
GPIO 9/10/11/12是4个寄存器。
THR是输出寄存器。LSR是状态寄存器。
$ cat led.c
#define DIR0_SET (*(volatile unsigned int *)0X11D00004)
#define OUT0 (*(volatile unsigned int *)0X11D00100)
#define OUT0_SET (*(volatile unsigned int *)0X11D00104)
#define OUT0_CLR (*(volatile unsigned int *)0X11D00108)
#define THR (*(volatile unsigned int *)0x11002000)
#define LSR (*(volatile unsigned int *)0x11002014)
#define UART_LSR_THRE 0x20
void putc(int ch)
{
while (!(LSR & UART_LSR_THRE)) ;
THR = ch;
}
int main()
{
int i = 0;
DIR0_SET = (1 << 9)|(1 << 11)|(1 << 12);
OUT0_CLR = (1 << 9)|(1 << 11)|(1 << 12);
putc('a');
putc('b');
putc('c');
putc('\n');
return 1;
}
[1] ipq5018 bare metal 实现led灯闪烁
https://linuxdev.cc/article/a0d7uq.html
[2] MT7981B Wi-Fi 6 Generation Router Platform: Registers Part 2 Peripherals, Connectivity
https://mirror2.openwrt.org/docs/MT7981B_Wi-Fi6_Platform_Registers_Open_Part2_V1.0.pdf