Linux系统移植:官板 uboot 修改(下)

举报
JeckXu666 发表于 2022/02/19 23:27:38 2022/02/19
【摘要】 文章目录 Linux系统移植:官板 uboot 修改(下)一、LCD 驱动修改二、网口驱动修改2.1 PHY 地址修改2.2 删除 uboot 中 74LV595 的驱动代码2.3 添加 I.MX...

Linux系统移植:官板 uboot 修改(下)

上一节我们将官板的 uboot 修改后适配正点原子开发板,可以编译成功下载运行,但其中还有不少驱动没有移植完成,本节完成部分驱动和环境变量配置,适配开发板

修改驱动主要在我们上一章移植的 mx6ull_alientek_emmc.hboard/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 变量查看到

20220218150452

所以我们主要修改软件参数,在文件 mx6ull_alientek_emmc.c 中找到如下所示内容:

20220218140931

这段代码定义了一个 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,也就是不使用隔行扫描

具体屏幕参数参考如下:

20220218164925

按照上面参数计算,时钟计算方式如下:

pixclock=(1/屏幕主频)*10^12

  
 
  • 1

屏幕移植后要将 mx6ull_alientek_emmc.h 中的 panel 参数名称和 fb_videomode 结构体的 name 相同,挂载成功后如下:

20220218165118

按道理屏幕会显示 NXP 的 LOGO 但是我移植完并没有显示,直接下载原子的代码也不能正常显示,原子提供代码和硬件肯定存在问题,查看的参考源码和我上面提供的参数,出处很大,后面需要再研究研究,但大致思路没有问题

二、网口驱动修改

IMX 有两个网口接口 ENET1 和 ENET2;

ENET1 的网络 PHY 芯片为 LAN8720A,通过 RMII 接口与 I.MX6ULL 相连,I.MX6U-ALPHA 开发板 ENET1 的网络原理图如图:

20220218173945

开发板的 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,看到如下宏定义:

20220218195055

宏 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,删除如下代码:

20220218200133

替换为如下:

#define ENET1_RESET IMX_GPIO_NR(5, 7)
#define ENET2_RESET IMX_GPIO_NR(5, 8)

  
 
  • 1
  • 2

ENET1 的复位引脚连接到 SNVS_TAMPER7 上,对应 GPIO5_IO07

ENET2 的复位引脚连接到 SNVS_TAMPER8 上,对应 GPIO5_IO08

然后 在 mx6ull_alientek_emmc.c 中找到如下 IO 配置代码结构体,然后删除掉:

20220218200257

然后找到 iox74lv_set 和 iox74lv_init 函数,将他们删除

20220218201411

找到 board_init 函数调用的 iox74lv_init 和 imx_iomux_v3_setup_multiple_pads,然后删除:

20220218201504

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),

  
 
  • 1
  • 2

添加后如下:

20220218202202

找到网口初始化函数 setup_iomux_fec:

20220218202332

添加网口芯片复位代码:

20220218202521

硬件复位很重要,必须添加

2.4 修改驱动函数

打开文件 drivers/net/phy/phy.c,找到函数 genphy_update_link,这是个通用 PHY 驱动函数此函数用于更
新 PHY 的连接状态和速度。使用 LAN8720A 的时候需要在此函数中添加一些代码,修改后的函数 genphy_update_link 如下

20220218211614

这段代码的宏,我们在一开始已经添加了,只有使用 SMSC 公司的 PHY 这段代码才会执行,读取LAN8720A 的 BMCR 寄存器,然后向寄存器 BMCR 寄存器写入 BMCR_RESET,软件复位 LAN8720A,然后等待 LAN8720A 软件复位完成,最后重新向 BMCR 寄存器写入以前的值

到此网口修改完成,编译下载,运行观察

20220218212102

检测 NET 使用 FEC1成功,下面我们把开发板连接到电脑,设置电脑的网口和开发板在同一个 IP 下,用开发板 Ping Windows 和 ubuntu 的 IP 地址,结果如下,网口 Ping 通

20220219140957

三、其他修改

修改 uboot 启动后的板子名称,打开文件 mx6ull_alientek_emmc.c,找到函数 checkboard:

20220219150940

修改名称:

puts("Board: MX6ULL ALIENTEK EMMC\n");

  
 
  • 1

编译下载,观察现象:

20220219153629

四、bootcmd 和 bootargs 修改

uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs,这两个变量采用类似 shell 脚本语言编写的,里面有很多的变量引用,这些变量都是环境变量,很多是 NXP 定义的,文 件 mx6ull_alientek_emmc.h 中的宏
CONFIG_EXTRA_ENV_SETTINGS 保存着这些环境变量的默认值

20220219153937

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 中代码如下:

20220219155654

可以看到 uchar default_environment[] 数组保存了环境变量,我们可以在这个位置设置 bootcmd 的默认值!

也有一些环境变量调用了其他宏定义,比如 CONFIG_BOOTCOMMAND 这个宏定义,在 mx6ull_alientek_emmc.h 文件中可以找到:

20220219155959

这段代码使用类似 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" \

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如果 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};

  
 
  • 1

其中 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

  
 
  • 1
  • 2

如果 loadbootscript 没有执行成功,就会运行环境变量 loadimage,内容如下:

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}

  
 
  • 1

其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,image = zImage,这段代码就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,当加载 linux 镜像文件 zImage 成功以后就运行环境变量 mmcboot,mmcboot 环境变量如下:

20220219161549

输出信息,然后运行环境变量 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}

  
 
  • 1

其中 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 内核了

文章来源: blog.csdn.net,作者:JeckXu666,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_45396672/article/details/123020270

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。