makefile是用来管理工程的。
示例1:
1 exe: a.c b.c
2 gcc a.c b.c -o exe
3
4 clean:
5 rm exe
基本概念:
目标:顶格写,在:前面
依赖: 在:后面,用来产生目标的原材料
命令:前面一定是table,不能是多个空格。命令是生成目标所做的动作
示例2:
1 led.bin: start.o
2 arm-linux-ld -Ttext 0x0 -o led.elf $^
3 arm-linux-objcopy -O binary led.elf led.bin
4 arm-linux-objdump -D led.elf > led_elf.dis
5 gcc mkv210_image.c -o mkx210 // 该处生成的mkx210是为了在Linux下执行的,这里的gcc和交叉编译工具链的gcc不相同
6 ./mkx210 led.bin 210.bin
7
8 %.o : %.S
9 arm-linux-gcc -o $@ $< -c
10
11 %.o : %.c
12 arm-linux-gcc -o $@ $< -c
13
14 clean:
15 rm *.o *.elf *.bin *.dis mkx210 -f
示例分析:
(1)Makefile有三个非常有用的变量。分别是$@,$^,$<代表的意义分别是:
$@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件
(2)交叉编译工具链工具及作用
先决条件:linux系统下面有一个环境变量叫PATH,必须把该工具链的地址导入到该环境变量下面,export PATH=工具链地址:$PATH
最好是该语句加到~/.bash文件中,这样每次启动终端都会执行该语句。
arm-linux-gcc:
用来编译源文件
arm-linux-ld:
用来链接,其中,-Ttest是用来指定链接地址的,在该处也可以使用链接脚本来去进行链接。在该处生成的elf文件还不能烧录执行。
objcopy:
作用以led.elf为源材料为源材料制作镜像的工具。
解释:led.elf已经是可执行程序,在操作系统下已经可以执行,裸机中需要的是可以烧录的二进制文件(镜像image)。
以led.elf为源材料为源材料制作镜像
objdump:
作用:反汇编,将elf格式的可执行程序反过来得到其汇编源代码。
mkx210(由mkv210_image.c得到):
作用:以led.bin为源材料得到210.bin(为BL1添加校验头)
解释:usb启动时不需要头校验,SD卡启动时需要,让led.bin加上header(校验头)成为210.bin。
附:mkv210_image.c源程序:
1 /*
2 * mkv210_image.c的主要作用就是由usb启动时使用的led.bin制作得到由sd卡启动的镜像210.bin
3 *
4 * 本文件来自于友善之臂的裸机教程,据友善之臂的文档中讲述,本文件是一个热心网友提供,在此表示感谢。
5 */
6 /* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容,
7 * 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。
8 */
9 #include 10 #include 11 #include 12 13 #define BUFSIZE (16*1024) 14 #define IMG_SIZE (16*1024) 15 #define SPL_HEADER_SIZE 16 16 //#define SPL_HEADER 'S5PC110 HEADER ' 17 #define SPL_HEADER '****************' 18 19 int main (int argc, char *argv[]) 20 { 21 FILE *fp; 22 char *Buf, *a; 23 int BufLen; 24 int nbytes, fileLen; 25 unsigned int checksum, count; 26 int i; 27 28 // 1. 3个参数 29 if (argc != 3) 30 { 31 printf('Usage: %s 32 return -1; 33 } 34 35 // 2. 分配16K的buffer,并且全部填充为0 36 BufLen = BUFSIZE; 37 Buf = (char *)malloc(BufLen); 38 if (!Buf) 39 { 40 printf('Alloc buffer failed!n'); 41 return -1; 42 } 43 44 memset(Buf, 0x00, BufLen); 45 46 // 3. 读源bin到buffer 47 // 3.1 打开源bin 48 fp = fopen(argv[1], 'rb'); 49 if( fp == NULL) 50 { 51 printf('source file open errorn'); 52 free(Buf); 53 return -1; 54 } 55 // 3.2 获取源bin长度 56 fseek(fp, 0L, SEEK_END); // 定位到文件尾 57 fileLen = ftell(fp); // 得到文件长度 58 fseek(fp, 0L, SEEK_SET); // 再次定位到文件头 59 // 3.3 源bin长度不得超过16K-16byte 60 count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE)) 61 ? fileLen : (IMG_SIZE - SPL_HEADER_SIZE); 62 // 3.4 buffer[0~15]存放'S5PC110 HEADER ' 63 memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE); 64 // 3.5 读源bin到buffer[16] 65 nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp); 66 if ( nbytes != count ) 67 { 68 printf('source file read errorn'); 69 free(Buf); 70 fclose(fp); 71 return -1; 72 } 73 fclose(fp); 74 75 // 4. 计算校验和 76 // 4.1 从第16byte开始统计buffer中共有几个1 77 // 4.1 从第16byte开始计算,把buffer中所有的字节数据加和起来得到的结果 78 a = Buf + SPL_HEADER_SIZE; 79 for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++) 80 checksum += (0x000000FF) & *a++; 81 // 4.2 将校验和保存在buffer[8~15] 82 a = Buf + 8; // Buf是210.bin的起始地址,+8表示向后位移2个字,也就是说写入到第3个字 83 *( (unsigned int *)a ) = checksum; 84 85 // 5. 拷贝buffer中的内容到目的bin 86 // 5.1 打开目的bin 87 fp = fopen(argv[2], 'wb'); 88 if (fp == NULL) 89 { 90 printf('destination file open errorn'); 91 free(Buf); 92 return -1; 93 } 94 // 5.2 将16k的buffer拷贝到目的bin中 95 a = Buf; 96 nbytes = fwrite( a, 1, BufLen, fp); 97 if ( nbytes != BufLen ) 98 { 99 printf('destination file write errorn'); 100 free(Buf); 101 fclose(fp); 102 return -1; 103 } 104 105 free(Buf); 106 fclose(fp); 107 108 return 0; 109 } (3)指令解释 -c: 只编译不链接 -o: 用来指定名字 -D: 表示反汇编(反汇编工具有多种用法,-D表示反汇编用法) -Ttext: 指定代码段的起始地址(链接地址) (4)其它 第8行到第12行叫做makefile的规则,当看到.S和.c文件会自动转化为.o文件。 printf移植中用到的makefile 1 CC = arm-linux-gcc 2 LD = arm-linux-ld 3 OBJCOPY = arm-linux-objcopy 4 OBJDUMP = arm-linux-objdump 5 AR = arm-linux-ar 6 7 INCDIR := $(shell pwd) 8 10 CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include 11 # C编译器的flag 12 CFLAGS := -Wall -O2 -fno-builtin 13 14 # 导出这些变量到全局,其实就是给子文件下面的makefile使用 15 export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS 16 17 18 objs := start.o led.o clock.o uart.o main.o 19 objs += lib/libc.a 20 21 uart.bin: $(objs) 22 $(LD) -Tlink.lds -o uart.elf $^ 23 $(OBJCOPY) -O binary uart.elf uart.bin 24 $(OBJDUMP) -D uart.elf > uart_elf.dis 25 gcc mkv210_image.c -o mkx210 26 ./mkx210 uart.bin 210.bin 27 28 lib/libc.a: 29 cd lib; make; cd .. 30 31 32 33 %.o : %.S 34 $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c 35 36 %.o : %.c 37 $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c 38 39 clean: 40 rm *.o *.elf *.bin *.dis mkx210 -f 41 cd lib; make clean; cd .. -nostdlib 不用标准库 -nostdinc 不用标准的头文件 -O2 编译器的优化等级 -Wall 显示所有警告 -I 用来表示寻找头文件的目录(一般用相对路径表示)
上一篇:C语言高级第一节杂谈
下一篇:[国嵌笔记][029][ARM处理器启动流程分析v2]
推荐阅读最新更新时间:2026-03-25 11:59
- 用于 7VIN 至 16VIN、1.5V 和 1.2V 输出的 LTM4628EV DC/DC 模块稳压器的典型应用电路
- 使用 Analog Devices 的 LTC3728LIGN 的参考设计
- DER-406 - 适用于 A19 灯的 5.76 W 高 PF 非隔离降压-升压型 TRIAC 调光 LED 驱动器
- ADR5045B 5V 输出精密微功率并联模式电压基准的典型应用
- LT3970EDDB-3.42 2.5V 降压转换器的典型应用
- MC78M08BDTG 8V 电流调节器的典型应用
- LT1021DCN8-5 精密电压基准的典型应用
- DER-282 - 100W, 扁平(11 mm), LLC DC-DC转换器
- REF193 低压差开尔文连接电压基准的典型应用电路
- LT3088EM 线性稳压器用于添加软启动的典型应用

MAX32625 PICO 嵌入式程序
AC Electric Motors Control Advanced Design Techniques And Applications By Fouad Giri
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号