嵌入式Linux裸机开发笔记5(IMX6ULL)—BSP工程管理实验(2)

 引言

        上次笔记中已经完成了各种驱动程序的编写,接下来开始修改main函数已经编写makefile和链接脚本。

5.3.5 修改 main.c 文件

        在上次笔记中,led 驱动、延时驱动和时钟驱动相关的函数全部都写到了 main.c 中,本次我们在前几节已经将这些驱动根据功能模块放置到相应的地方,所以 main.c 里面的内容就得修改,将 main.c 里面的内容改为如下所示代码:

1 #include "bsp_clk.h"

2 #include "bsp_delay.h"

3 #include "bsp_led.h"

4

5 /*

6 * @description : main 函数

7 * @param : 无

8 * @return : 无

9 */

10 int main(void)

11 {

12 clk_enable(); /* 使能所有的时钟 */

13 led_init(); /* 初始化 led */

14

15

while(1)

16

{

17/* 打开 LED0 */

18 led_switch(LED0,ON);

19delay(500);

20

21/* 关闭 LED0 */

22led_switch(LED0,OFF);

23delay(500);

24}

25

26 return 0;

27 }

        在 main.c 中我们仅仅留下了 main 函数,至此,本例程跟程序相关的内容就全部编写好了。

5.4 编译下载验证

5.4.1 编写 Makefile 和链接脚本

        在工程根目录下新建 Makefile 和 imx6ul.lds 这两个文件,创建完成以后的工程如下图所示:

在文件 Makefile 中输入如下所示内容:

示例代码:

1 CROSS_COMPILE ?= arm-linux-gnueabihf-

2 TARGET ?= bsp

3

4 CC := $(CROSS_COMPILE)gcc

5 LD := $(CROSS_COMPILE)ld

6 OBJCOPY:= $(CROSS_COMPILE)objcopy

7 OBJDUMP:= $(CROSS_COMPILE)objdump

8

9 INCDIRS:= imx6ul \

10 bsp/clk \

11bsp/led \

12bsp/delay

13

14 SRCDIRS := project \

15bsp/clk \

16bsp/led \

17bsp/delay

18

19 INCLUDE := $(patsubst %, -I %, $(INCDIRS))

20

21 SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

22 CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

23

24 SFILENDIR := $(notdir $(SFILES))

25 CFILENDIR := $(notdir $(CFILES))

26

27 SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))

28 COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

29 OBJS:= $(SOBJS) $(COBJS)

30

31 VPATH := $(SRCDIRS)

32

33 .PHONY: clean

34

35 $(TARGET).bin : $(OBJS)

36$(LD) -Timx6ul.lds -o $(TARGET).elf $^

37$(OBJCOPY) -O binary -S $(TARGET).elf $@

38$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

39

40 $(SOBJS) : obj/%.o : %.S

41$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

42

43 $(COBJS) : obj/%.o : %.c

44$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

45

46 clean:

47 rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

        可以看出本章实验的 Makefile 文件要比前面的实验复杂很多,我们接下来详细分析一下示例代码中的 Makefile 源码:

        第 1~7 行定义了一些变量,除了第 2 行以外其它的都是跟编译器有关的,如果使用其它编译器的话只需要修改第 1 行即可。第 2 行的变量 TARGET 目标名字,不同的例程肯定名字不一样。

        第 9 行的变量 INCDIRS 包含整个工程的.h 头文件目录,文件中的所有头文件目录都要添

加到变量INCDIRS中。比如本例程中包含.h头文件的目录有imx6ul、bsp/clk、bsp/delay和bsp/led,所以就需要在变量 INCDIRS 中添加这些目录,即:

INCDIRS := imx6ul bsp/clk bsp/led bsp/delay

        仔细观察的话会发现第 9~11 行后面都会有一个符号“\”,这个相当于“换行符”,表示本行和下一行属于同一行,一般一行写不下的时候就用符号“\”来换行。在后面的裸机例程中我们会根据实际情况来在变量 INCDIRS 中添加头文件目录。

        第 14 行是变量 SRCDIRS,和变量 INCDIRS 一样,只是 SRCDIRS 包含的是整个工程的所

有.c 和.S 文件目录。比如本例程包含有.c 和.S 的目录有 bsp/clk、bsp/delay、bsp/led 和 project,

即:

SRCDIRS := project bsp/clk bsp/led bsp/delay

        同样的,后面的裸机例程中我们也要根据实际情况在变量 SRCDIRS 中添加相应的文件目录。

        第 19 行的变量 INCLUDE 使用到了函数 patsubst,通过函数 patsubst 给变量 INCDIRS 添加

一个“-I”,即:

INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay

加“-I”的目的是因为 Makefile 语法要求指明头文件目录的时候需要加上“-I”。

        第 21 行变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以我们只需要从里面挑出所有的.S 汇编文件即可,这里借助了函数 foreach 和函数 wildcard,最终 SFILES 如下:

SFILES := project/start.S

        第 22 行变量 CFILES 和变量 SFILES 一样,只是 CFILES 保存工程中所有的.c 文件(包含绝 对路径),最终 CFILES 如下:

CFILES = project/main.c bsp/clk/bsp_clk.c bsp/led/bsp_led.c bsp/delay/bsp_delay.c

        第 24 和 25 行的变量 SFILENDIR 和 CFILENDIR 包含所有的.S 汇编文件和.c 文件,相比变

量 SFILES 和 CFILES,SFILENDIR 和 CFILNDIR 只是文件名,不包含文件的绝对路径。使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉即可,SFILENDIR 和 CFILENDIR 如下:

SFILENDIR = start.S

CFILENDIR = main.c bsp_clk.c bsp_led.c bsp_delay.c

        第 27 和 28 行的变量 SOBJS 和 COBJS 是.S 和.c 文件编译以后对应的.o 文件目录,默认所 有的文件编译出来的.o 文件和源文件在同一个目录中,这里我们将所有的.o 文件都放到 obj 文件夹下,SOBJS 和 COBJS 内容如下:

SOBJS = obj/start.o

COBJS = obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

        第 29 行变量 OBJS 是变量 SOBJS 和 COBJS 的集合,如下:

OBJS = obj/start.o obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

        编译完成以后所有的.o 文件就全部存放到了 obj 目录下,如下图所示:

   第 31 行的 VPATH 是指定搜索目录的,这里指定的搜素目录就是变量 SRCDIRS 所保存的目录,这样当编译的时候所需的.S 和.c 文件就会在 SRCDIRS 中指定的目录中查找。

        第 33 行指定了一个伪目标 clean,伪目标前面讲解 Makefile 的时候已经讲解过了。

        第 35~47 行就很熟悉了,前几章都已经详细的讲解过了。

        “示例代码”中的 Makefile 文件内容重点工作是找到要编译哪些文件?编译的.o 文件存放到哪里?使用到的编译命令和前面实验使用的一样,其实 Makefile 的重点工作就是解决“从哪里来到哪里去的”问题,也就是找到要编译的源文件、编译结果存放到哪里?真正的编译命令很简洁。

        链接脚本 imx6ul.lds 的内容基本和上次笔记一样,主要是 start.o 文件路径不同,本章所使用的 imx6ul.lds 链接脚本内容如下所示:

1 SECTIONS{

2 . = 0X87800000;

3 .text :

4 {

5 obj/start.o

6 *(.text)

7 }

8 .rodata ALIGN(4) : {*(.rodata*)}

9 .data ALIGN(4) : { *(.data) }

10 __bss_start = .;

11 .bss ALIGN(4) : { *(.bss) *(COMMON) }

12 __bss_end = .;

13 }

        注意第 5 行设置的 start.o 文件路径,这里和上一章的链接脚本不同。

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值