《正点原子嵌入式linux驱动开发指南V1.4》学习笔记


一、开发环境搭建

1.1 安装交叉编译工具链

见另一篇博客《Linux安装交叉编译工具链》

1.2 代码镜像烧写工具

imxdownload :注意需要将imxdownload工具拷贝到工程根目录下,否则会烧写失败

1.3 Ubuntu下所有的设备文件都在目录“/dev”里面

插上 SD 卡以后,SD设备卡会出现在“/dev”里面,其中存储设备都是以“/dev/sd”开头的。

1.4 Ubuntu 搭建TFTP服务器

见另一篇博客《Linux搭建NFS服务器》

1.5 Ubuntu搭建NFS服务器

见另一篇博客《Linux搭建TFTP服务器》

二、u-boot编译步骤

2.1 编译步骤

  1. 官网下载u-boot源码
  2. Linux安装必要库
  3. 进入源码顶层目录执行编译命令,可以写一个sh脚本
    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

2.2 问题

  1. 怎么确定u-boot编译命令该用什么命令?如上述3条命令。所有的芯片都是统一的吗?
    ​参数一:mx6ull_14x14_ddr512_emmc_defconfig
    ​ 来自u-boot源码中configs目录中的配置文件名。半导体厂商出场的时候为了简化开发人员的开发难度,会配置很多开发板的一套默认配置,在configs目录下,对应的芯片使用对应的配置文件即可。
    参数二:-j12
    ​ 表示12个线程都进行编译,一般系统支持几核几线程线程可以根据需要设置,满线程时,编译速度最快。
    参数三:V=1
    在终端中输出短命令虽然看起来很清爽,但是不利于分析uboot的编译过程。可以通过设置变量“V=1“来实现完整的命令输出

三、Makefile知识点

3.1 $(MAKE) -C

​ makefile中递归嵌套调用makefile。参数-C指定子目录。

3.2 变量传递

​ export VARIABLE …… //导出变量给子 make 。
​ unexport VARIABLE…… //不导出变量给子 make。
​ 备注:
​ 有两个特殊的变量:“SHELL”和“MAKEFLAGS”,这两个变量除非使用“unexport”声明,否则的话在整个make的执行过程中,它们的值始终自动的传递给子make。

3.3 命令含义解析

3.3.1 MAKEFLAGS += -rR --include-dir=$(CURDIR)

​ +=”来给变量 MAKEFLAGS 追加了一些值
​ “-rR”表示禁止使用内置的隐含规则和变量定义
​ “–include-dir”指明搜索路径
​ “$(CURDIR)”表示当前目录

3.3.2 $(origin V)

​ 函数origin,表示获取变量V的来源

3.3.3 ifeq ("$(origin V)", “command line”)

ifeq ("$(origin V)", "command line")
    KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
    KBUILD_VERBOSE = 0
endif

​ 函数origin,表示变量V的来源,此句话表示变量V是否来自command line。
​ 前面命令行输入的编译命令有V=1,所以这里KBUILD_VERBOSE = 1,如果命令行没有V=1,则KBUILD_VERBOSE = 0

3.3.4 @控制make中的命令会不会被输出在终端

​ make在执行的时候默认会在终端输出命令,但是在命令前面加上“@”就不会在终端输出命令了。

3.3.5 $(filter <pattern…>, <text>)

​ filter 函数表示以 pattern 模式过滤 text 字符串中的单词,仅保留符合模式 pattern 的单词

3.3.6 make参数

​ O 表示指定的make工具输出目录
​ C 表示检查代码,C=1表示检查需要重新编译的文件,C=2表示检查所有源码文件

3.3.7 模块编译

​ make M=dir或make SUBDIRS=dir进行模块编译

3.3.8 sed命令

​ sed -e 表示替换命令

3.3.9 编译命令

​ 每次编译uboot的时候都要在make命令后面设置ARCH和CROS_COMPILE,使用起来很麻烦,可以直接修改顶层Makefile,在里面加入ARCH和CROSS_COMPILE的定义。


四、U-Boot中添加自己的板卡型号

4.1 拷贝类似平台的配置文件,重命名为自己平台的名字

​ cd configs
​ cp xxxx_defconfig dest_defconfig
​ 修改里面内容为自己板卡的名字

4.2 拷贝类似平台头文件,重命名为自己平台的头文件

​ cd include/configs/
​ cp xxxx.h dest.h
​ 修改里面#ifdef后面的名字为自己板卡的名字

4.3 添加对应板级文件夹

​ cd board/freescale/
​ cp xxx/ dest_board_dir_name -rf
​ 修改原板卡.c文件为目标板卡.c文件
​ cd dest_board_dir_name
​ mv xxx.c dest_board_name.c

4.4 修改图形界面配置文件

​ 当make menuconfig时配置选项中的可选项

4.5 编译u-boot(推荐仍旧使用shell脚本写入命令)

4.6 网络驱动修改

4.6.1 基本概念

  1. 部分芯片内部有个mac外设,mac外设单独无法工作,需要外接PHY芯片。即:内部mac+外部PHY。(通信速度快)

    部分芯片内不没有mac外设,会采用DM9000网络连接。DM9000芯片相当于:外部MAC+外部PHY。(通信速度慢)

  2. imx6ul芯片手册 22章ENET章节,讲解MAC具体细节

4.6.2 LAN8720A芯片

  1. LAN8720A芯片有个管理接口MDIO,包含两根线:MDIO和MDC。一个MDIO接口可以管理32个PHY芯片。
  2. 芯片addr(即:芯片ID),在芯片手册中可以查到,PHYAD0引脚是否上拉决定地址。
  3. 每个芯片都有一个复位引脚。
  4. 所有PHY芯片,其前16个寄存器一模一样,所以u-boot中已经写好了通用PHY驱动,所一般代码无需修改,可以直接使用。
  5. 芯片操作方法:查手册,待补充

4.6.3 移植PHY芯片驱动,u-boot源码修改步骤

  1. 看电路图,查询PHY芯片地址:0x0/0x1等

  2. 看电路图,查询PHY芯片复位引脚接的ARM哪个GPIO引脚

  3. 打开u-boot中上面步骤复制的对应板卡的.h文件,找到NET相关的宏配置,主要修改两个宏:

    ​ CONFIG_FEC_ENET_DEV 表示使用哪一个LAN口设备

    ​ CONFIG_FEC_MXC_PHYADDR 表示PHY芯片的地址

  4. 打开u-boot中上面步骤复制的对应板卡的.c文件,删除原有网络芯片(74LV595 )的驱动代码。并且添加对应板卡的控制代码,包括:define宏定义RESET复位引脚对应GPIO口、引脚配置代码等。

  5. 仍旧是.c文件,找到结构体数组fec1_pads、fec2_pads为两个网口的IO配置参数,在数组末尾添加拉你个网口的复位IO配置参数

  6. 仍旧是.c文件,添加网络复位IO初始化代码

  7. 添加LAN芯片软复位代码,文件:drivers/net/phy/phy.c 中的函数genphy_update_link

4.7 bootcmd和bootargs环境变量

4.7.1 bootcmd

​ bootcmd 保存着 uboot 默认命令, uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。

​ 可以在 uboot 启动以后进入命令行设置 bootcmd 环境变量的值 ,命令如下:

setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;'

4.7.2 bootargs

​ bootargs 保存着 uboot 传递给 Linux 内核的参数。 bootargs设置命令如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'

​ bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使用到,常用的参数有:

​ 1. console

​ console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是串口还是 LCD 屏幕。

​ 2. root

​ root 用来设置根文件系统的位置, root=/dev/mmcblk1p2 用于指明根文件系统存放在mmcblk1 设备的分区 2 中。

​ 3. rootfstype

​ 此选项一般配置 root 一起使用, rootfstype 用于指定根文件系统类型

4.8 网络文件系统(网络挂载启动)

为了方便调试,可以使用网络挂载启动的方式,通过tftp或者nfs服务器进行系统启动,只需要如下几步即可:

  1. 配置tftp和nfs服务器
  2. 拷贝dtb文件和zImage文件到tftp服务器目录下
  3. 拷贝linux内核到nfs服务器目录下
  4. 设置环境变量bootargs和bootcmd为tftp模式下载设备树和zImage。

设置环境变量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

五、Linux内核

5.1 编译Linux内核步骤

  1. 下载Linux内核镜像

  2. 顶层目录Makefile中配置交叉编译工具链,或者直接编写编译sh脚本在命令中附上交叉编译工具链。

    make disclean 清理工程,如果有修改配置文件,慎用该命令

    make xxx_defconfig 配置工程

    make menuconfig 打开图形界面,配置Linux(如果不需要配置linux,可以删掉该命令)

    make 编译Linux源码

  3. arch/arm/boot 目录下 zImage为Linux镜像文件

  4. arch/arm/boo/dts 目录下 .dtb文件为设备树文件

5.2 Linux内核源码工程目录结构

  1. arch 架构相关目录
  2. drivers 驱动相关目录
  3. include 头文件相关目录
  4. kenel 内核相关目录
  5. lib 库相关目录
  6. .config Linux最终使用的配置文件
  7. Kconfig 图形化界面配置文件

5.3 顶层Makefile详解

​ 基本和 uboot 的顶层 Makefile 一样,重点在于vmlinux 的生成。最后将 vmlinux 压缩成我们最常用的 zImage 或 uImage 等文件。

5.4 Linux内核启动流程

  1. Linux内核链接脚本文件:arch/arm/kernel/vmlinux.lds ,该文件可以找到Linux内核第一行程序从哪里执行。

    脚本文件中493行ENTRY(stext) 代码指定内核入口为stext,stext 定义在文件arch/arm/kernel/head.S 中 。

  2. 函数__lookup_processor_type 检查当前系统是否支持此 CPU ,其中一个结构体proc_info_list 保存支持的CPU信息。proc_info_list 在文件 arch/arm/include/asm/procinfo.h 中

  3. Linux 内核最终是需要和根文件系统打交道的,需要挂载根文件系统,并且执行根文件系统中的 init 程序,以此来进去用户态

ps -A:列出当前所有运行的进程

5.5 Linux内核移植

5.5.1 移植步骤

  1. 顶层Makefile修改交叉编译工具链

  2. 配置内核、编译内核,生成zImage 、.dtb(设备树) 文件。

    zImage路径:arch/arm/boot
    .dtb  路径:arch/arm/boot/dts
    
  3. 将上述两个文件拷贝到tftp服务器目录下,后面u-boot下载要用

  4. 从tftp服务器下载镜像emmc中

    tftp 80800000 zImage
    tftp 83000000 xxx.dtb
    
  5. 启动内核

    bootz 80800000 - 83000000
    

5.5.2 内核移植:在 Linux 中 添加自己的开发板

  1. 拷贝类似平台配置文件为自己开发板的配置文件

    cd arch/arm/configs
    cp xxx_defconfig 自己开发板名字_defconfig
    
  2. 拷贝开发板对应设备树文件

    cd arch/arm/boot/dts
    cp xxx_dts 自己的开发板名字.dts
    
  3. 修改makefile

    vim arch/arm/boot/dts/Makefile
    

    在dtb-$(CONFIG_SOC_IMX6ULL) 配置项中加入自己的开发板对应的设备树名称

  4. 顶层目录下创建编译脚本

    #!/bin/sh
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
    
  5. 赋予可执行权限

    chmod 777 imx6ull_alientek_emmc.sh
    
  6. 编译

    ./imx6ull_alientek_emmc.sh
    
  7. 拷贝zImage 、.dtb(设备树) 文件到tftp服务器目录中,使用tftp工具下载zImage和dtb设备树文件

    tftp 80800000 zImage
    tftp 83000000 imx6ull-alientek-emmc.dtb
    bootz 8080000083000000
    
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页