笔记目录
学习目标
学习linux开发
学习内容
一、VI 编辑器的设置
vi 打开文件/etc/vim/vimrc
1、设置 TAB 键为 4 字节
VI 编辑器默认 TAB 键为 8 空格,为了使代码更好看我们改成 4 空格。
在此文件最后面输入如下代码:set ts=4
2、VIM 编辑器显示行号
在此文件最后面输入如下代码:set nu
3.VI/VIM 编辑器使用空格代替了 TAB 键
在此文件最后面输入如下代码:set noexpandtab
二、存储
1、ROM
ROM是只读内存,其特性是一旦储存资料就无法再将之改变或删除,存储的资料不会因为电源关闭而消失。
2、RAM
RAM是随机存储,掉电不会保存数据。
SRAM(静态随机访问存储器)不需要刷新电路即能保存它内部存储的数据
DRAM (动态随机访问存储器)只能将数据保持很短的时间。为了保持数据,DRAM使用电容存储,所以 必须隔一段时间刷新(refresh)一次,如果存储单元没有被刷新,存储的信息就会丢失。
SDRAM(同步动态随机访问存储器)同步是指 Memory工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准。传统的DRAM在两个读周期之间需要等待一段时间,用于充电操作。而SDRAM一个模组有两个bank,在对一个bank充电时,可以操作另一个bank,实现流水线。SDRAM的发展已经经历了五代:分别是SDR SDRAM、 DDR SDRAM、 DDR2 SDRAM、 DDR3 SDRAM、 DDR4 SDRAM。
3、FLASH
FLASH 存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还不会断电丢失数据同时可以快速读取数据(NVRAM 的优势)。
NOR Flash和NAND Flash区别
NOR的读速度比NAND稍快一些。
NAND的写入速度比NOR快很多。
NAND的4ms擦除速度远比NOR的5s快。
大多数写入操作需要先进行擦除操作。
NAND的擦除单元更小,相应的擦除电路更少。
EMMC=NAND闪存+闪存控制芯片+标准接口封装(对厂家而言简化了电路设计,降低了成本。)
DDR属于SDRAM
NANO FLASH属于flash
使用emmc的好处是,除了得到大容量的空间(这一点,只用NAND FLASH多堆叠也可以做到),还有就是emmc可以管理NAND (坏块处理,ECC,FFS)等。
三、Makefile语法
重要提醒
Makefile 里面是由一系列的规则组成的。
Makefile在编写时不能使用空格只能用TAB键,否则会报错。
Makefile:12: *** 遗漏分隔符 (null)。 停止。
1、Makefile作用
make 的执行过程,make 工具就是在 Makefile 中一层一层的查找依赖关系,并执行
相应的命令。编译出最终的可执行文件。
Makefile 的好处就是“自动化编译”,一旦写好了 Makefile文件,以后只需要一个 make 命令即可完成整个工程的编译,极大的提高了开发效率。
2、Makefile 规则格式
目标… : 依赖文件集合…
命令 1
命令 2
…
3、gcc命令
gcc [选项] [文件名字]
主要选项如下:
-c:只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。
-o:<输出文件名> 用来指定编译结束以后的输出文件名,如果使用这个选项的话 GCC 默
认编译出来的可执行文件名字为 a.out。
-g:添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编
译的时候生成调试所需的符号信息。
-O:对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进
行优化,这样产生的可执行文件执行效率就高。
-O2:比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。
简单的例程:
main: main.o input.o calcu.o #需要main.o input.o等文件生成main
gcc -o main #编译的最终目标是生成一个可执行文件main
main.o: main.c #需要的main.o文件由main.c文件生成
gcc -c main.c #编译main.c生成main.o
input.o: input.c
gcc -c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean: #执行make clean清理文件
rm *.o
rm main
在第一次编译的时候由于 main 还不存在,因此第一条规则会执行,第一条规则依赖于文件 main.o、 input.o 和 calcu.o这个三个.o 文件,这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行。以 main.o 为例,发现更新 main.o 的是第二条规则,因此会执行第二条规则,第二条规则里面的命令为“gcc –c main.c”,这行命令很熟悉了吧,就是不链接编译 main.c,生成 main.o,其它两个.o 文件同理。最后一个规则目标是 clean,它没有依赖文件,因此会默认为依赖文件都是最新的,所以其对应的命令不会执行,当我们想要执行 clean 的话可以直接使用命令“make clean”,执行以后就会删除当前目录下所有的.o 文件以及 main。
4、Makefile 变量
Makefile 中变量的引用方法是"$(变量名)"
注释"#"
#Makefile 变量的使用
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)
赋值符 | “?=” |
---|---|
变量追加 | “+=” |
四、U-Boot
1、U-Boot 简介
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader 程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将 Linux 内核从 flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。
2、U-Boot编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格)
mx6ull_14x14_ddr512_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12
ARCH=arm 设置目标为 arm 架构,CROSS_COMPILE 指定所使用的交叉编译器。
第一条命令相当于“make distclean”,目的是清除工程,一般在第一次编译的时候最好清理一下工程。
第二条指令相当于“make mx6ull_14x14_ddr512_emmc_defconfig”,用于配置 uboot,配置文件为mx6ull_14x14_ddr512_emmc_defconfig。(14x14代表芯片的封装大小)
最后一条指令相当于 “make -j12”也就是使用 12 核来编译 uboot。
在顶层的makefile输入
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
可以make后面不用加
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
3、U-Boot 一些命令
uboot 命令中的数字都是十六进制的!不是十进制的!
进入 uboot 的命令行模式
命令 | 含义 | 备注 |
---|---|---|
help/? | 帮助 | help/?命令名 |
bdinfo | 查看板子信息 | DRAM 的起始地址和大小、启动参数保存起始地址、波特率、sp(堆栈指针)起始地址等信息 |
printenv | 输出环境变量信息 | |
version | 查看 uboot 的版本号 | |
setenv | 设置环境变量 | 字符串中有空格需要使用单引号‘’将其括起来 |
saveenv | 保存修改的环境变量 | 删除一个环境变量只要给这个环境变量赋空值 |
md | 显示内存值 | md[.b, .w, .l] address [# of objects]命令中的[.b .w .l]对应 byte、word 和 long,也就是分别以 1 个字节、2 个字节、4 个字节来显示内存值。address 就是要查看的内存起始地址,[# of objects]表示要查看的数据长度,这个数据长度单位不是字节,而是跟你所选择的显示格式有关。(md.b 80000000 14) |
nm | 修改指定地址的内存值 | nm [.b, .w, .l] address(nm.l 80000000) |
mm | 修改指定地址内存值的 | 使用 mm 修改内存值的时候地址会自增,而使用命令 nm 的话地址不会自增 |
mw | 用于使用一个指定的数据填充一段内存 | mw [.b, .w, .l] address value [count]mw 命令同样可以以.b、.w 和.l 来指定操作格式, address 表示要填充的内存起始地址, value为要填充的数据, count 是填充的长度。 |
cp | 数据拷贝命令 | cp [.b, .w, .l] source target count cp 命令同样可以以.b、.w 和.l 来指定操作格式,source 为源地址,target 为目的地址,count为拷贝的长度。 |
cmp | 比较两段内存的数据是否相等 | cmp [.b, .w, .l] addr1 addr2 count 其中cmp 命令同样可以以.b、.w 和.l 来指定操作格式,addr1 为第一段内存首地址,addr2 为第二段内存首地址, count 为要比较的长度。 |
ipaddr | 开发板 ip 地址 | 使用 dhcp 命令来从路由器获取 IP 地址 |
ethaddr | 开发板的 MAC 地址 | 一定要设置 |
gatewayip | 网关地址 | |
netmask | 子网掩码 | |
serverip | 服务器 IP 地址,也就是 Ubuntu 主机 IP 地址 | 用于调试代码 |
ping | 测试开发板的网络能否使用 | |
dhcp | 用于从路由器获取 IP 地址 | |
nfs | 计算机之间通过网络来分享资源 | nfs [loadAddress] [[hostIPaddr:]bootfilename]其中loadAddress 是要保存的 DRAM 地址,[[hostIPaddr:]bootfilename]是要下载的文件地址。分析 |
4、uboot启动linux测试
从emmc启动
emmc三个分区,第一个分区存放uboot,第二个分区格式化成FAT文件系统在里面存放.dtb和zimage文件,第三个分区放根文件系统。
首先查看emmc里面是否有系统,linux镜像zimage和.dtb文件。先将当前设备切换到emmc
mmc dev 1 //切换到EMMC
fatls mmc 1:1 //查看EMMC分区1里面的文件
fatload mmc 1:1 80800000 zImage //将zimage下载到DDR的0x80800000
fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb //将dtb下载到DDR的0x83000000
bootz 80800000 - 83000000 //启动内核
如果内核启动成功,说明uboot支持emmc启动,验证成功。
从网络启动
tftp服务器
需要确定ubuntu的~/linux/tftpboot文件夹下有.dtb和zimage文件
在ubuntu上搭建tftp服务器
tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议,Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器,需要安装 tftp-hpa 和 tftpd-hpa,命令如下:
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd
和 NFS 一样,TFTP 也需要一个文件夹来存放文件,在用户目录下新建一个目录,命令如下:
mkdir /home/wyd/linux/tftpboot
chmod 777 /home/wyd/linux/tftpboot
最后配置 tftp,安装完成以后新建文件/etc/xinetd.d/tftp,如果没有/etc/xinetd.d 目录的话自行创建sudo vi /etc/xinetd.d/tftp
,然后在里面输入如下内容:
service tftp
{
socket_type=dgram
protocol=udp
wait=yes
user=root
server=/usr/sbin/in.tftpd
server_args=-s /home/wyd/linux/tftpboot/
disable=no
per_source=11
cps=100 2
flags=IPv4
}
sudo vi /etc/default/tftpd-hpa
,然后在里面输入如下内容:
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/wyd/linux/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-1 -c -s"
最后输入如下命令, 重启 tftp 服务器:
sudo service tftpd-hpa restart
将 zImage 镜像等文件拷贝到 tftpboot 文件夹中,并且给予 zImage 相应的权限
cp zImage /home/wyd/linux/tftpboot/
cd /home/wyd/linux/tftpboot/
chmod 777 zImage
chmod 777 tftpboot
chmod 777 。。。。。
进入 uboot 的命令行模式
tftp 80800000 zImage //将 tftpboot 文件夹里面的 zImage 文件下载到开发板 DRAM 的 0X80800000 地址处
tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb //将 tftpboot 文件夹里面的 dtb 文件下载到开发板 DRAM 的 83000000 地址处
bootz 80800000 - 83000000 //启动内核
设置 bootargs 和 bootcmd 这两个环境变量,设置如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
saveenv
一开始是通过 tftp 下载 zImage 和 imx6ull-alientek-emmc.dtb 这两个文件
配置网络
setenv ipaddr 192.168.1.10 //开发板 IP 地址
setenv ethaddr 00:04:9f:04:d2:35 //开发板网卡 MAC 地址
setenv gatewayip 192.168.1.1 //开发板默认网关
setenv netmask 255.255.255.0//开发板子网掩码
setenv serverip 192.168.1.6 //服务器地址,也就是 Ubuntu 地址(如果不是静态地址可能需要长期更改)
saveenv //保存环境变量
ping测试
=> ping 192.168.1.6
Using FEC1 device
host 192.168.1.6 is alive
5、U-Boot 顶层makefile部分
#版本号
VERSION = 2016 #主版本号
PATCHLEVEL = 03 #修补版本号
SUBLEVEL = #次版本号
EXTRAVERSION = #附加信息
NAME = #名字
#隐含规则
#隐含规则则是内建在make 中,为make 提供了重建某一类目标文件(.o 等)的通用方法,同时这些隐含规则所用到的变量也就是所谓的隐含变量。
#隐含规则的好处是在Makefile 中不需要明确给出重建某一个目标的命令,甚至可以不需要规则。make会为你自动搜寻匹配的隐含规则链。
#隐含规则的代价之一就是低效,系统必须搜索可能的隐含规则链。同时隐含规则也有可能应用了不是你想要的规则而引入很难debug的错误。
#变量SHELL与MAKEFLAGS一样,默认情况(没有用“unexport”声明)下在整个make的执行过程中被自动的传递给所有的子make。
#“+=”来给变量 MAKEFLAGS 追加了一些值,“-rR”表示禁止使用内置的隐含规则和变量定义,“--include-dir”指明搜索路径,”$(CURDIR)”表示当前目录
MAKEFLAGS += -rR