裸机开发(5)start.S imx6ul.lds Makefile文件(随着学习更新)

目录

  • 1. imx6ul.lds
    • imx6ul.lds 1.0
  • 2.start.S
    • start.S 1.0
  • 3.Makefile文件
    • Makefile 1.0(工程只有汇编文件)
    • Makefile 2.0 (汇编和c文件各一个)
    • Makefile 3.0 (使用变量和imx6ul.lds)
    • Makefile 4.0 (最终版)

1. imx6ul.lds

链接脚本文件的作用是:用于描述不同文件如何链接在一起形成最终的可执行文件,其主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布,比如编译生成的文件一般都包含text段,data段,rodata段,bss段等。我们在imx6ull中要设定将程序文件链接到DDR的0x87800000地址。
在使用链接脚本之前,使用arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^设置链接地址,再把编译后的文件链接为elf格式的文件。
使用lds链接脚本后,使用arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^,程序链接地址,代码段数据段等都在imx6ul.lds中设置好了。

imx6ul.lds 1.0

SECTIONS{
	. = 0X87800000;
	.text :
	{
		obj/start.o 
		*(.text)
	}
	.rodata ALIGN(4) : {*(.rodata*)}     
	.data ALIGN(4)   : { *(.data) }    
	__bss_start = .;    
	.bss ALIGN(4)  : { *(.bss)  *(COMMON) }    
	__bss_end = .;
}
  1. 第2行对特殊符号“.”进行赋值,“.”在链接脚本中叫做定位计数器,默认为 0。我们要求代码链接到0X87800000。
  2. 第3行的“.text”是段名,后面的冒号是语法要求,大括号里填上要链接到“.text”这个段里面的所有文件,start.o要放在起始位置,“* (.text)”中的“ * ”是通配符,表示剩余所有输入文件的.text段都放到“.text”中start的后面。
  3. 定义了一个“.bss”段并进行4字节对齐,“.bss”数据就是那些定义了但是没有被初始化的变量,“.data”是全局变量,“.rodata”是全局常量。
  4. “__bss_start”和“__bss_end”是符号,赋值为定位符“.”,这两个符号用来保存.bss段的起始地址和结束地址。前面说了.bss段是定义了但是没有被初始化的变量,我们需要手动对.bss段的变量清零,需要知道.bss段的起始和结束地址,这样直接对这段内存赋0即可完成清零。可以直接在汇编或者C文件里面使用这两个符号。

2.start.S

start.S 1.0

.global _start  		/* 全局标号 */
/*
 * 描述:	_start函数,程序从此函数开始执行,此函数主要功能是设置C
 *		 运行环境。
 */
_start:
	/* 进入SVC模式 */
	mrs r0, cpsr
	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/
	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式					*/
	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/
	/* 设置栈指针,
	 * 注意:IMX6UL的堆栈是向下增长的!
	 * 堆栈指针地址一定要是4字节地址对齐的!!!
	 * DDR范围:0X80000000~0X9FFFFFFF
	 */
	ldr sp,=0X80200000	/* 设置用户模式下的栈首地址为0X80200000,大小为2MB	  	  	*/
	b main				/* 跳转到main函数 										*/

3.Makefile文件

Makefile 1.0(工程只有汇编文件)

led.bin:led.s
	arm-linux-gnueabihf-gcc -g -c led.s -o led.o
	arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
	arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
	arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
	rm -rf *.o led.bin led.elf led.dis
  1. 第一行指目标是led.bin,依赖文件是led.s,若发现目录没有目标文件,则开始执行第二行。
  2. -Ttext可以指定程序链接地址,这一步需要制定程序的链接地址,并将.o格式文件存成elf格式。
  3. 使用arm-linux-gnueabihf-objcopy工具将elf格式文件转为bin格式。“-O”指定以什么格式输出,“binary”以二进制格式输出,“-S”表示不复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。
  4. 使用arm-linux-gnueabihf-objdump进行反汇编,将elf文件转换为可以查看汇编代码且包含链接地址的dis文件。

Makefile 2.0 (汇编和c文件各一个)

objs := start.o main.o
ledc.bin:$(objs)
	arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^
	arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
	arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis	
%.o:%.S
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<	
%.o:%.c
	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<	
clean:
	rm -rf *.o ledc.bin ledc.elf ledc.dis	
  1. 定义变量objs,里面包含生成ledc.bin所有的材料:start.o和main.o。
  2. 如果第二行发现.o材料不全,不如不存在start.o或者start.S经过了修改,就会执行第七行,编译相对应的.S文件,$ @是所有目标文件的集合,$<是所有.S格式依赖文件的集合。
  3. 若是main.o不存在或者main.c,情况和上一步类似,会执行第八、九行。

Makefile 3.0 (使用变量和imx6ul.lds)

CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME		  ?= ledc
CC 		:= $(CROSS_COMPILE)gcc
LD		:= $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
OBJS 	:= start.o main.o

$(NAME).bin:$(OBJS)
	$(LD) -Timx6ul.lds -o $(NAME).elf $^
	$(OBJCOPY) -O binary -S $(NAME).elf $@
	$(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis
%.o:%.S
	$(CC) -Wall -nostdlib -c -O2 -o $@ $<	
%.o:%.c
	$(CC) -Wall -nostdlib -c -O2 -o $@ $<
clean:
	rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis

Makefile 4.0 (最终版)

CROSS_COMPILE 	?= arm-linux-gnueabihf-
TARGET		  	?= bsp
CC 				:= $(CROSS_COMPILE)gcc
LD				:= $(CROSS_COMPILE)ld
OBJCOPY 		:= $(CROSS_COMPILE)objcopy
OBJDUMP 		:= $(CROSS_COMPILE)objdump

INCDIRS 		:= imx6ul \
				   bsp/clk \
				   bsp/led \
				   bsp/delay 				   			   
SRCDIRS			:= project \
				   bsp/clk \
				   bsp/led \
				   bsp/delay 
				   				   
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))
SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR		:= $(notdir  $(SFILES))
CFILENDIR		:= $(notdir  $(CFILES))
SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS			:= $(SOBJS) $(COBJS)
VPATH			:= $(SRCDIRS)
.PHONY: clean
	
$(TARGET).bin : $(OBJS)
	$(LD) -Timx6ul.lds -o $(TARGET).elf $^
	$(OBJCOPY) -O binary -S $(TARGET).elf $@
	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
$(SOBJS) : obj/%.o : %.S
	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -nostdlib -c -O2  $(INCLUDE) -o $@ $<	
clean:
	rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)
  1. 前六行定义变量,除第二行都与编译器相关;若想更换交叉编译器,修改第一行“arm-linux-gnueabihf-”就好了。

参考正点原子嵌入式linux开发指南

你可能感兴趣的:(I.MX6U学习笔记)