写一个bare metal程序,使用uboot go执行:
start.S
1 2 3 4 5 6 | .text .global _start _start: b main loop: 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 17 void 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)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 -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执行,可以看到可以闪灯。