Linux系统移植:官板 uboot 修改(下)
文章目录
- Linux系统移植:官板 uboot 修改(下)
- 一、LCD 驱动修改
- 二、网口驱动修改
- 2.1 PHY 地址修改
- 2.2 删除 uboot 中 74LV595 的驱动代码
- 2.3 添加 I.MX6U-ALPHA 开发板网络复位引脚驱动
- 2.4 修改驱动函数
- 三、其他修改
- 四、bootcmd 和 bootargs 修改
- 4.1 bootcmd 修改
- 4.2 bootargs 修改
Linux系统移植:官板 uboot 修改(下)
上一节我们将官板的 uboot 修改后适配正点原子开发板,可以编译成功下载运行,但其中还有不少驱动没有移植完成,本节完成部分驱动和环境变量配置,适配开发板
修改驱动主要在我们上一章移植的 mx6ull_alientek_emmc.h 和 board/freescake/mx6ull_alientek_emmc/mx6ull_alientek_emmc.c 文件中进行修改
一、LCD 驱动修改
修改 LCD 驱动重点注意以下几点:
- LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确
- LCD 背光引脚 GPIO 的配置
- LCD 配置参数是否正确
原子的开发板和官板的 LCD 接口一致,所以不用修改,IO参数可以在 mx6ull_alientek_emmc.c 中的 lcd_pads 变量查看到
所以我们主要修改软件参数,在文件 mx6ull_alientek_emmc.c 中找到如下所示内容:
这段代码定义了一个 display_info_t 结构体,包含了 LCD 的分辨率,像素格式以及其他参数信息
display_info_t 定义在文件 arch/arm/include/asm/imx-common/video.h 中,详细可以去看一看
其中参数如下:
bus:LCD 寄存器基地址
pixfmt:像素格式,此处使用 RGB888 就是 24 位
mode 是 fb_videomode 结构体 :成员变量为 LCD 的参数
name:LCD 名字,要和环境变量中的 panel 相等
xres、yres:LCD X 轴和 Y 轴像素数量
pixclock:像素时钟,每个像素时钟周期的长度,单位为皮秒
left_margin:HBP,水平同步后肩
right_margin:HFP,水平同步前肩
upper_margin:VBP,垂直同步后肩
lower_margin:VFP,垂直同步前肩
hsync_len:HSPW,行同步脉宽
vsync_len:VSPW,垂直同步脉宽
vmode:扫描模式一般为 FB_VMODE_NONINTERLACED,也就是不使用隔行扫描
具体屏幕参数参考如下:
按照上面参数计算,时钟计算方式如下:
pixclock=(1/屏幕主频)*10^12
屏幕移植后要将 mx6ull_alientek_emmc.h 中的 panel 参数名称和 fb_videomode 结构体的 name 相同,挂载成功后如下:
按道理屏幕会显示 NXP 的 LOGO 但是我移植完并没有显示,直接下载原子的代码也不能正常显示,原子提供代码和硬件肯定存在问题,查看的参考源码和我上面提供的参数,出处很大,后面需要再研究研究,但大致思路没有问题
二、网口驱动修改
IMX 有两个网口接口 ENET1 和 ENET2;
ENET1 的网络 PHY 芯片为 LAN8720A,通过 RMII 接口与 I.MX6ULL 相连,I.MX6U-ALPHA 开发板 ENET1 的网络原理图如图:
开发板的 ENET1 引脚与 NXP 官方的 I.MX6ULL EVK 开发板基本一样,只有复位引脚不同
I.MX6ULL 通过 MDIO接口来读取 PHY 芯片的内部寄存器,来判断当前的物理链接状态、连接速度 (10M 还是 100M) 和双工状态 (半双工还是全双工)
MDIO 接口有两个引脚,ENET_MDC 和 ENET_MDIO,ENET_MDC 提供时钟,ENET_MDIO 进行数据传输。一个 MDIO 接口可以管理 32 个 PHY 芯片,同一个 MDIO 接口下的这些 PHY 使用不同的器件地址来做区分,MIDO 接口通过不同的器件地址即可访问到相应的 PHY 芯片
ENET1 上连接的 LAN8720A器件地址为 0X0,要修改 ENET1 网络驱动的话重点就三点:
- ENET1 复位引脚初始化
- LAN8720A 的器件 ID
- LAN8720 驱动
ENET2 驱动和 1 基本相同,但 ENET2 的复位引脚 ENET2_RST 接到了 I.MX6ULL 的 SNVS_TAMPER8 上,ENET2 所使用的 PHY 芯片器件地址为 0X1,所以修改 uboot 驱动分为以下的步骤:
2.1 PHY 地址修改
打开 mx6ull_alientek_emmc.h,看到如下宏定义:
宏 CONFIG_FEC_ENET_DEV 用于选择使用哪个网口,默认为 1,也就是选择 ENET2
CONFIG_FEC_MXC_PHYADDR 为 PHY 地址
宏 CONFIG_PHY_MICREL 用于使能 uboot 中的 PHY 驱动,修改为 CONFIG_PHY_SMSC
2.2 删除 uboot 中 74LV595 的驱动代码
芯片地址修改完成以后就是网络复位引脚的驱动修改,NXP 官方 I.MX6ULL EVK 开发板使用 74LV595 来扩展 IO,两个网络的复位引脚就是由 74LV595 来控制的。正点原子的 I.MX6U-ALPHA 开发板并没有使用 74LV595,因此打开 mx6ull_alientek_emmc.c,删除如下代码:
替换为如下:
#define ENET1_RESET IMX_GPIO_NR(5, 7)
#define ENET2_RESET IMX_GPIO_NR(5, 8)
ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07
ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08
然后 在 mx6ull_alientek_emmc.c 中找到如下 IO 配置代码结构体,然后删除掉:
然后找到 iox74lv_set 和 iox74lv_init 函数,将他们删除
找到 board_init 函数调用的 iox74lv_init 和 imx_iomux_v3_setup_multiple_pads,然后删除:
2.3 添加 I.MX6U-ALPHA 开发板网络复位引脚驱动
2.2 中我们删除了引脚的初始化代码,2.3 小节需要添加初始化代码:
找到 iomux_v3_cfg_t const fec1_pads[] 和 iomux_v3_cfg_t const fec2_pads[],这两个结构体数组 fec1_pads 和 fec2_pads 是 ENET1 和 ENET2 这两个网口的 IO 配置参数,我么添加两个网口的复位 IO 配置参数
MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),
MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),
添加后如下:
找到网口初始化函数 setup_iomux_fec:
添加网口芯片复位代码:
硬件复位很重要,必须添加
2.4 修改驱动函数
打开文件 drivers/net/phy/phy.c,找到函数 genphy_update_link,这是个通用 PHY 驱动函数此函数用于更
新 PHY 的连接状态和速度。使用 LAN8720A 的时候需要在此函数中添加一些代码,修改后的函数 genphy_update_link 如下
这段代码的宏,我们在一开始已经添加了,只有使用 SMSC 公司的 PHY 这段代码才会执行,读取LAN8720A 的 BMCR 寄存器,然后向寄存器 BMCR 寄存器写入 BMCR_RESET,软件复位 LAN8720A,然后等待 LAN8720A 软件复位完成,最后重新向 BMCR 寄存器写入以前的值
到此网口修改完成,编译下载,运行观察
检测 NET 使用 FEC1成功,下面我们把开发板连接到电脑,设置电脑的网口和开发板在同一个 IP 下,用开发板 Ping Windows 和 ubuntu 的 IP 地址,结果如下,网口 Ping 通
三、其他修改
修改 uboot 启动后的板子名称,打开文件 mx6ull_alientek_emmc.c,找到函数 checkboard:
修改名称:
puts("Board: MX6ULL ALIENTEK EMMC\n");
编译下载,观察现象:
四、bootcmd 和 bootargs 修改
uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs,这两个变量采用类似 shell 脚本语言编写的,里面有很多的变量引用,这些变量都是环境变量,很多是 NXP 定义的,文 件 mx6ull_alientek_emmc.h 中的宏
CONFIG_EXTRA_ENV_SETTINGS 保存着这些环境变量的默认值
CONFIG_EXTRA_ENV_SETTINGS 是个条件编译语句,通过宏定义在使用 NAND 和 EMMC 的时候宏CONFIG_EXTRA_ENV_SETTINGS 的值是不同
4.1 bootcmd 修改
bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令,这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核,板子第一次运行 uboot 的时候都会使用默认值来设置 bootcmd 环境变量,在文件 include/env_default.h 中代码如下:
可以看到 uchar default_environment[] 数组保存了环境变量,我们可以在这个位置设置 bootcmd 的默认值!
也有一些环境变量调用了其他宏定义,比如 CONFIG_BOOTCOMMAND 这个宏定义,在 mx6ull_alientek_emmc.h 文件中可以找到:
这段代码使用类似 shell 语言代码编写:
- run findfdt:使用的是 uboot 的 run 命令来运行 findfdt,用来查找开发板对应的设备树文件(.dtb)
findfdt 内容如下:
"findfdt="\
"if test $fdt_file = undefined; then " \
"if test $board_name = EVK && test $board_rev = 9X9; then " \
"setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \
"if test $board_name = EVK && test $board_rev = 14X14; then " \
"setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \
"if test $fdt_file = undefined; then " \
"echo WARNING: Could not determine dtb to use; fi; " \
"fi;\0" \
如果 fdt_file 为 undefined 的话,那 uboot 就会根据板子信息得出所需的.dtb 文件名
- mmc dev ${mmcdev} 用于切换 mmc 设备,mmcdev 为 1,因此这行代码就是:mmcdev 1,也就是切换到 EMMC 上
- 后面的代码先执行 mmc dev ${mmcdev}切换到 EMMC 上,然后使用命令 mmc rescan 扫描看有没有 SD 卡或者 EMMC 存在,若没有执行 run netboot,netboot 是一个自定义的环境变量,从网络启动 Linux
- 如果有 EMMC 存在,先运行 loadbootscript 环境变量,该变量如下:
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,script= boot.scr,这段代码 loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src 到 DRAM 的 0X80800000 处
如果加载 boot.src 文件成功就运行 bootscript 环境变量,变量如下:
bootscript=echo Running bootscript from mmc ...;
source
如果 loadbootscript 没有执行成功,就会运行环境变量 loadimage,内容如下:
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,image = zImage,这段代码就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,当加载 linux 镜像文件 zImage 成功以后就运行环境变量 mmcboot,mmcboot 环境变量如下:
输出信息,然后运行环境变量 mmcargs(mmcargs 用来设置 bootargs),然后判断boot_fdt是否为yes或者try,进而是否加载设备树,如果读取.dtb 文件成功的话那就调用命令 bootz 启动 linux,然后 Linux 内核启动
总结一下该命令执行过程:
- 切换到 EMMC
- 读取 zImage 镜像文件到 0x80800000
- 读取设备树文件到 0x83000000
- 启动 Linux
4.2 bootargs 修改
bootargs 保存着 uboot 传递给 Linux 内核的参数,bootargs 环境变量是由 mmcargs 设置的,mmcargs 环境变量如下:
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中 console=ttymxc0,baudrate=115200,mmcroot=/dev/mmcblk1p2 rootwait rw,所以 mmcargs 就是设置 bootargs 的值为 “console= ttymxc0, 115200 root=/dev/mmcblk1p2 rootwait rw”,bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使用到,主要用到的参数如下:
4.2.1 console
console 用来设置 linux 终端(或者叫控制台),一般设置串口作为 Linux 终端,I.MX6ULL 的串口 1 在 linux 下的设备文件就是/dev/ttymxc0,刚刚代码中的 console= ttymxc0, 115200 就是设置串口波特率
4.2.2 root
root 用来设置根文件系统的位置,root=/dev/mmcblk1p2 用于指明根文件系统存放在 mmcblk1 设备的分区 2 中
/dev/mmcblkx(x=0~n)表示 mmc 设备
而/dev/mmcblkxpy(x=0n,y=1n)表示 mmc 设备 x 的分区 y
在 I.MX6U-ALPHA 开发板中 /dev/mmcblk1 表示 EMMC,而 /dev/mmcblk1p2 表示 EMMC 的分区 2
4.2.3 rootfstype
此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为 ext 格式保持默认就行,如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此项
到此 uboot 的修改基本完成,下一节就是启动 Linux 内核了
Linux系统移植:官板 uboot 修改(下)相关推荐
- 嵌入式Linux(5):驱动开发网络调试驱动设备的Linux系统移植
驱动开发之网络调试驱动设备的Linux系统移植 1.Uboot移植到开发板 uboot移植 2.开发板网络通讯 nfs命令 tftp命令 3.Linux移植到开发板 4.BusyBox 构建根文件系统 ...
- Linux系统移植:NXP 官板 uboot 移植
文章目录 Linux系统移植:NXP 官板 uboot 移植 一.获取官板 U-Boot 二.编译下载 U-Boot 源码 三.官方驱动验证 Linux系统移植:NXP 官板 uboot 移植 移植 ...
- linux系统移植篇(二)—— Uboot使用介绍
linux系列目录: linux基础篇(一)--GCC和Makefile编译过程 linux基础篇(二)--静态和动态链接 ARM裸机篇(一)--i.MX6ULL介绍 ARM裸机篇(二)--i.MX6 ...
- 基于全志A33开发板linux系统移植学习记录(Boot0)
基于全志A33开发板linux系统移植学习记录 第一章 Boot0基于ARMGCC的编译与修改 文章目录 基于全志A33开发板linux系统移植学习记录 前言 一.全志A33简介以及上电引导流程 二. ...
- STM32MP157 Linux系统移植开发篇4: BootLoader(Uboot)移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- Linux系统移植:原厂 Kernel 移植到开发板
文章目录 Linux系统移植:原厂 Kernel 移植到开发板 一.获取原厂内核并编译 二.内核启动测试 三.添加自己板子文件 3.1 板子配置文件 3.2 板子设备树 3.3 编译 四.重要配置修改 ...
- Linux系统移植:图形化配置 U-Boot
文章目录 Linux系统移植:图形化配置 U-Boot 一.打开图形化配置 二.图形化配置操作 三.编译配置结果 Linux系统移植:图形化配置 U-Boot 较新的 uboot 支持图形化配置,本小 ...
- zynq linux环境移植,ZYNQ 7030 Linux 系统移植
ZYNQ 7030 Linux系统移植 手上有一块 ZYNQ-7030的演示板,是仿照Xilinx Zedboard设计的,但是与Zedboard又有所不同,因此花时间移植一下Linux系统.记录下这 ...
- 嵌入式Linux系统移植的四大步骤
最近在学习系统移植的相关知识,在学习和调试过程中,发现了很多问题,也解决了很多问题,但总是对于我们的开发结果有一种莫名其妙的感觉,纠其原因,主要对于我们的开发环境没有一个深刻的认识,有时候几个简单的命 ...
最新文章
- 豪赌 ARM 梦碎:63 岁孙正义的「花甲历险记」
- ubuntu软件安装(个人PC)
- shop++商品搜索出现乱码的解决方法
- 【Java源码分析】Android-LruCache源码分析
- 利用反射动态调用类成员C#
- 刚从阿里面试回来已拿到offer想和大家分享一下(阿里面试经验)
- 第十届蓝桥杯java B组—试题F 特别数的和
- python中协程与函数的区别_深入浅析python 协程与go协程的区别
- oracle遇null赋默认值,使用hibernate annotation 为非空列加上默认值
- 【机器学习】漫谈特征缩放
- linux gradle解压后, 执行gradle error13: Permission denied
- ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)
- python Chrome + selenium自动化测试与python爬虫获取网页数据
- 计算机网络四个阶段的发展特点,计算机网络的发展分哪四个阶段,特点?
- 05 - @property 后面所加的关键词
- 基于JAVA+SpringBoot+Vue+Mybatis+MYSQL的图书馆管理系统
- Python学习之==接口开发
- java集合框架小结
- linux维文字体如何下载,uyghurfont
- Linux 安装 RMVB,rm,ape文件 解码器
热门文章
- gcc 4.9.4 编译
- antdv 日期选择框date-picker中英文混显问题解决
- MySQL query rewrite插件简单测试
- 如何学好Java,掌握三大点
- shell数组和变量的应用
- C#——String.IndexOf方法与Array.IndexOf方法的异同
- matlab数字时钟作业,Matlab动态时钟范例.docx
- 达梦数据库关键字屏蔽
- Luogu 3645 [APIO 2015] 雅加达的摩天楼
- python 字符串string 开头r b u f 含义 str bytes 转换 format