裸机环境快速配置清单
开发板配置:烧写开发板提供的uboot到Norflash中
硬件准备:JLink, USB-serial线, JTAG转接口,
为什么要学习裸机?
裸机程序以前用于实模式的单片机?现在的裸机用在哪里呢?
现在裸机大部分用于bootloader设计,bootloader本身就是一个大型的裸机程序,
目前裸机还用于Linux驱动的设计与编写,Linux驱动由软件+硬件部分,其中硬件部分就涉及到裸机程序开发。
课程总体规划?
我们学习的裸机驱动在我们工作过程中并不是单个单个的裸机驱动程序,也就是说我们并不会在处理器上编写单一的裸机驱动程序。所以我们需要具备每个单个驱动设计编写能力,还应该具有这些设备联系的能力。在我们今后工作中,用的最多的裸机驱动就是uboot。
很多同学你让他去编写单个裸机驱动程序他没问题,
但让他去写一个完整的bootloader时,他就不知道该如何下手了。
所以我们新一季的裸机驱动就是围绕着bootloader的设计来学习裸机驱动的。
bootloader的参考(uboot),我们通过bootloader的行业老大uboot来学习bootloader的设计与编写。比如说第一步我们要做CPU的初始化,第二步做内存的初始化,第三步做串口初始化,第四部做网卡初始化…等等。
课程列表规划:(精通ARM裸机开发)
工欲善其事必先利其器:多交叉开发工具的掌握
我从内部看ARM:从硬件角度介绍ARM处理器特性
ARM汇编指令详解:必备的汇编指令掌握
uboot工作流程分析:分析并记录uboot工作流程
我是bootloader设计师:根据上面流程并做一定修改设计自己的bootloader
核心初始化:
LED初始化:
时钟初始化:
内存初始化:
MMU初始化:
中断初始化:
串口初始化:
网卡初始化:
移植tftp客户端:
移植bootm命令启动内核:
LCD初始化:
定时器初始化:
触摸屏初始化:
USB初始化:
裸机驱动学习方法?
五步学习法
第一步:我们要去了解硬件相关理论
第二步:导读芯片手册
第三步:设计流程图(思维导图)
第四步:代码编写
第五步:在线调试程序
裸机集成化开发环境 (ADS)
对于我们初学者来说,集成化开发环境会把很多事情都帮我们做了,所以我们很难去更透明的了解整个开发流程。
而且由于winXP和win7兼容性问题,所以我们今后的裸机开发都在Linux下完成。
裸机开发流程
硬件相关理论》芯片手册导读》思维导图设计》
编写裸机程序》调试裸机程序》
生成二进制映像(编译、链接、格式转换)》烧写/运行二进制映像。
交叉工具链安装
**解压ARM-tools.tar.gz(tar –xzf ARM-tools.tar.gz)
**进入工具链包
**安装arm-linux-gcc(tar –xvzf arm-linux-gcc –C /)
**安装arm-linux-gdb(解压之后buildall)
**配置环境变量(export PATH=
PATH:/opt/arm−linux−gdb/4.3.2/bin)∗∗配置环境变量(exportPATH=
PATH:/usr/local/arm/4.3.2/bin)
**生效环境变量(source ~/.bashrc)
**测试裸机程序
**编译裸机程序:arm-linux-gcc –g –c led.S
**链接器脚本链接:arm-linux-ld -Tled.lds led.o -o led.elf
**格式转换成二进制文件: arm-linux-objcopy –O binary led.elf led.bin
**把这个二进制映像烧写进开发板
**先把引导安装程序通过Jlink烧写进norflash/SD卡,
**然后通过norflash/SD内的程序+dnw下载二进制文件到开发板(nandflash)程序。
**(download vivi)(insmod dnw_usb.ko; dnw file addr)
**重新通过nand方式启动开发板观察二进制执行结果。
64位Ubuntu安装ARM交叉编译工具之后无法正常运行的处理
在Ubuntu64位操作系统上安装ARM交叉工具链之后使用arm-linux-gcc时会报如下错误:
/usr/local/arm/4.3.2/bin/arm-linux-gcc: line 3: /usr/local/arm/4.3.2/bin/arm-none-linux-gnueabi-gcc: No such file or directory
查了很多资料修改都不管用,可能是64位系统中没有安装兼容32位的一些支持库吧,执行下面操作可以解决上面的问题:
sudo apt-get install build-essential automake autoconf libtool
sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0
交叉工具链详解
**静态交叉编译:arm-linux-gcc -static hello.c –o hello.elf
**查看可执行程序属性: file hello.elf
**查找交叉编译工具的搜寻头文件路径:arm-linux-gcc -print-search-dir
**只交叉编译:arm-linux-gcc -g –c led.S
**链接器脚本方式交叉链接:arm-linux-ld -Tled.lds led.o –o led.elf
**地址传递方式交叉链接:arm-linux-ld -Ttext 0x30008000 led.o –o led.elf
**查看elf文件(all)信息:arm-linux-readelf -a led.elf
**查看程序大小端: arm-linux-readelf -a led.elf | grep “data”
**查看程序依赖的库: arm-linux-readelf -d hello.elf
**开发板上应用无法运行:检查平台,检查大小端,检查依赖的库。
**交叉反汇编: arm-linux-objdump -D –S hello.elf > hello.dump
**文件格式转换工具:arm-linux-objcopy -O binary led.elf led.bin
Makefile构成
Makefile构成-规则
目标文件:依赖文件
<tab> 命令
led.o:led.S
arm-linux-gcc -g -c $^ -o $@
all:led.o
arm-linux-ld -Tled.lds $^ -o led.elf
arm-linux-objcoy -O binary led.elf led.bin
.PHONY:clean
clean:
rm -rf *.o *.elf *.bin *.dump
Makefile构成-伪目标
Makefile中把那些只包含命令,没有任何依赖的目标成为伪目标(phony targets)
.PHONY:clean
clean:
rm –rf *.o *.bin *.elf
Makefile构成-最终目标
第1问:当一个Makefile中有多条规则时,如何单独执行某条规则?
答:通过make targetname来单独执行某条规则。
第2问:如果用户没有指定某条规则(make),make会默认执行Makefile中哪条规则?
答:会执行Makefile中第1条规则,该规则就称为最终目标。
Makefile规则-变量
obj=f1.o f2.o f3.o
all: ${obj}
gcc $^ -o app.elf
上面是用户自定义变量,下面是系统默认变量
**$^ 代表所有的依赖文件
**$@ 代表目标
**$< 代表第一个依赖文件
通用规则:目标和依赖仅仅是后缀不同
%.o:%.S
arm-linux-gcc -g -c $^ -o $@
%.o:%.c
arm-linux-gcc -g -c $^ -o $@
关于显示问题
取消回显:在命令前加个@符号
取消错误回显:在命令前加个-符号
指定Makefile文件名
指定文件名: make -f mymakefile
通用Makefile-生成可执行文件的makefile
######################################
#
######################################
#source file
#源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件
SOURCE := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
#target you can change test to what you want
#目标文件名,输入任意你想要的执行文件名
TARGET := test
#compile and lib parameter
#编译参数
CC := gcc
LIBS :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
#i think you should do anything here
#下面的基本上不需要做任何改动了
.PHONY : everything objs clean veryclean rebuild
everything : $(TARGET)
all : $(TARGET)
objs : $(OBJS)
rebuild: veryclean everything
clean :
rm -fr *.so
rm -fr *.o
veryclean : clean
rm -fr $(TARGET)
$(TARGET) : $(OBJS)
$(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
通用Makefile-生成静态链接库的makefile
######################################
#
#
######################################
#target you can change test to what you want
#共享库文件名,lib*.a
TARGET := libtest.a
#compile and lib parameter
#编译参数
CC := gcc
AR = ar
RANLIB = ranlib
LIBS :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
#i think you should do anything here
#下面的基本上不需要做任何改动了
#source file
#源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件
SOURCE := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
.PHONY : everything objs clean veryclean rebuild
everything : $(TARGET)
all : $(TARGET)
objs : $(OBJS)
rebuild: veryclean everything
clean :
rm -fr *.o
veryclean : clean
rm -fr $(TARGET)
$(TARGET) : $(OBJS)
$(AR) cru $(TARGET) $(OBJS)
$(RANLIB) $(TARGET)
通用Makefile-生成动态链接库的makefile
######################################
#
#
######################################
#target you can change test to what you want
#共享库文件名,lib*.so
TARGET := libtest.so
#compile and lib parameter
#编译参数
CC := gcc
LIBS :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
SHARE := -fPIC -shared -o
#i think you should do anything here
#下面的基本上不需要做任何改动了
#source file
#源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件
SOURCE := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
.PHONY : everything objs clean veryclean rebuild
everything : $(TARGET)
all : $(TARGET)
objs : $(OBJS)
rebuild: veryclean everything
clean :
rm -fr *.o
veryclean : clean
rm -fr $(TARGET)
$(TARGET) : $(OBJS)
$(CC) $(CXXFLAGS) $(SHARE) $@ $(OBJS) $(LDFLAGS) $(LIBS)
链接器脚本-LDS
链接器脚本
SECTIONS { //段包含关键字
. = 0x30000000; //起始地址:反汇编代码:_start首地址
. = ALIGN(4); //4字节对其
.text : //代码段定义
{
cpu_init.o(.text) //首先执行这个文件
*(.text) //所以文件的代码段
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
bss_start = . ; //通过变量保存bss地址
.bss :
{
*(.bss)
}
bss_end = . ; //通过end与start相减可得到bss段长度
}
eclipse集成开发环境
eclipse(gdb_server) -----Jlink-------jtag开发板
**安装arm-linux-gdb.tar.gz交叉调试工具
**环境变量配置:export PATH=${PATH}:/opt/arm-linux-gdb/bin
**************export PATH=${PATH}:/usr/local/arm/4.3.2/bin
**(source ~/.bashrc)
**安装gdbserver工具
**(cp libjlink*.so* /usr/lib –f) #移植库文件
**(cp 45-jlink.rules /etc/udev/rules.d/) #移植rules文件
**(./JLinkGDBServer来连接开发板Jlink连接并显示开发板信息)
**注意:JlinkGDBServer要一直运行着使用eclipse,且每次调试工程时都要进行调试配置
**安装eclipse工具
**(运行: ./eclipse)
**安装eclipse插件以支持开发板裸机调试
**help >>> install new software
work with: http://opensource.zylin.com/zylincdt>>> add
勾选:Zylin Embedded CDT >>> Next >>> 安装完成后 >>>
重启eclipse
**eclipse裸机调试环境配置
**建立工程 >>>
Project >>> 取消勾选Build Automatically
Debug(虫子) >>> Debug Configurations >>> 双击最下面产生默认的
Main:C/C++ Application: /home/xxx/led/led.elf
Debugger:arm-linux-gdb,取消勾选stop on startup at main
Commands:将初始化脚本内容粘贴至初始化命令框中
启动调试:
Debug(虫子) >>> led default
编辑模式/调试模式的切换(最右上角切换)