写一个bare metal程序,使用uboot go执行:
start.S
1 2 3 4 5 6 | .text .global _start_start: b mainloop: b loop |
led.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | struct ipq_timer_platdata { unsigned int gcnt_cntcv_lo; unsigned int gcnt_cntcv_hi; unsigned int gpt_freq_hz; unsigned long long timer_load_val;} ipq_timer = {};#define readl(addr) *(volatile unsigned long *)(addr)#define writel(val, addr) *(volatile unsigned long *)(addr) = (val)unsigned usec2tick(unsigned usec){ return ipq_timer.gpt_freq_hz / 1000 / 1000 * usec;}static unsigned long long read_counter(void){ unsigned long vect_hi1, vect_hi2; unsigned long vect_low;repeat: vect_hi1 = readl(ipq_timer.gcnt_cntcv_hi); vect_low = readl(ipq_timer.gcnt_cntcv_lo); vect_hi2 = readl(ipq_timer.gcnt_cntcv_hi); if (vect_hi1 != vect_hi2) goto repeat; return ((unsigned long long)vect_hi1 << 32 | vect_low);}void timer_init(){ ipq_timer.gcnt_cntcv_lo = 0x4a2000; ipq_timer.gcnt_cntcv_hi = 0x4a2004; ipq_timer.gpt_freq_hz = 24000000; ipq_timer.timer_load_val = 0x00FFFFFFFFFFFFFF;}void udelay(unsigned usec){ unsigned long long val; unsigned long long now; unsigned long long last; unsigned long long runcount; val = usec2tick(usec); last = read_counter(); do { now = read_counter(); if (last > now) runcount = (ipq_timer.timer_load_val - last) + now; else runcount = now - last; } while (runcount < val);}#define TLMM_BASE 0x01000000#define GPIO_CONFIG_ADDR(x) (TLMM_BASE + (x)*0x1000)#define GPIO_IN_OUT_ADDR(x) (TLMM_BASE + 0x4 + (x)*0x1000)#define GPIO_INPUT 0#define GPIO_OUTPUT 1#define BUTTON_PRESSED 0#define BUTTON_RELEASED 1#define BUTTON_RESET 25#define BLUE_LED 19#define YELLOW_LED 17void gpio_set_value(unsigned int gpio, unsigned int out){ unsigned int *addr = (unsigned int *)GPIO_IN_OUT_ADDR(gpio); unsigned int val = 0; val = readl(addr); val &= ~(0x2); val |= out << 1; writel(val, addr);}int gpio_get_value(unsigned int gpio){ unsigned int *addr = (unsigned int *)GPIO_IN_OUT_ADDR(gpio); unsigned int val = readl(addr); return (val & 1);}void main(){ timer_init(); while (1) { udelay(1000*1000); gpio_set_value(BLUE_LED, 0); udelay(1000*1000); gpio_set_value(BLUE_LED, 1); }} |
链接脚本 led.lds
1 2 3 4 5 6 | SECTIONS{ . = 0x44000000; .text : { *(.text) } .data : { *(.data) }} |
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | CROSS_COMPILE := /work/ax3000/staging_dir/toolchain-arm_cortex-a7_gcc-5.5.0_musl_eabi/bin/arm-openwrt-linux-CC := $(CROSS_COMPILE)gccAS := $(CROSS_COMPILE)asLD := $(CROSS_COMPILE)ldOBJCOPY := $(CROSS_COMPILE)objcopyOBJDUMP := $(CROSS_COMPILE)objdumpall: $(AS) -o start.o start.S $(CC) -c -g -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=0x44000000 -m arm -D led.bin > led.bin.dis cp led.bin /work/tftproot/ |
将led.elf上传。使用go执行,可以看到可以闪灯。