ILD

ipq5018 bare metal 实现led灯闪烁
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2022-5-20 站点:Inside Linux Development

写一个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执行,可以看到可以闪灯。


Copyright © insidelinuxdev.net 2017-2021. Some Rights Reserved.