Linux--uboot移植(三)新uboot驱动修改

10 篇文章 0 订阅

一、LCD驱动修改

一般uboot中修改驱动都是在对应板子c文件和h文件,即board/freescale/mx6ull_myboard/mx6ull_myboard.c和 include/configs/mx6ull_myboard.h

这两个文件。

一般修改 LCD 驱动重点注意以下几点:

  • LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确
  • LCD 背光引脚 GPIO 的配置
  • LCD 配置参数是否正确

1.1 修改c文件配置

打开文件 mx6ull_myboard.c,需要修改下面这段内容:

struct display_info_t const displays[] = {{
    .bus = MX6UL_LCDIF1_BASE_ADDR,
    .addr = 0,
    .pixfmt = 24,
    .detect = NULL,
    .enable = do_enable_parallel_lcd,
    .mode   = {
        .name           = "TFT43AB",
        .xres           = 480,
        .yres           = 272,
        .pixclock       = 108695,
        .left_margin    = 8,
        .right_margin   = 4,
        .upper_margin   = 2,
        .lower_margin   = 4,
        .hsync_len      = 41,
        .vsync_len      = 10,
        .sync           = 0,
        .vmode          = FB_VMODE_NONINTERLACED
} } };

先来分析一下这段代码,该代码定义了一个变量displays,类型为display_info_t,这个结构体是LCD信息结构体,其中包括了LCD的分辨率,像素格式,LCD的各个参数等。

display_info_t 定义在文件 arch/arm/include/asm/imx-common/video.h 中,定义如下:

struct display_info_t {
    int bus;
    int addr;
    int pixfmt;
    int (*detect)(struct display_info_t const *dev);
    void (*enable)(struct display_info_t const *dev);
    struct  fb_videomode mode;
};

这里的pixfmt是像素格式,也就是一个像素点是多少位,如果是RGB565的话就是16位,如果是RGB888的话就是24位,一般使用 RGB888。

结构体display_info_t还有个mode成员变量,此成员变量也是个结构体,为fb_videomode,定义在文件 include/linux/fb.h 中,定义如下:

struct fb_videomode {
    const char *name;   /* optional */
    u32 refresh;        /* optional */
    u32 xres;
    u32 yres;
    u32 pixclock;
    u32 left_margin;
    u32 right_margin;
    u32 upper_margin;
    u32 lower_margin;
    u32 hsync_len;
    u32 vsync_len;
    u32 sync;
    u32 vmode;
    u32 flag;
};

结构体b_videomode里面的成员变量为LCD的参数,这些成员变量函数如下:

  • name :LCD 名字,要和环境变量中的 panel 相等
  • xres 、yres :LCD X 轴和 Y 轴像素数量
  • pixclock:像素时钟,每个像素时钟周期的长度,单位为皮秒
  • left_margin :HBP(horizontal back porch),水平同步后肩
  • right_margin :HFP(horizontal front porch),水平同步前肩
  • upper_margin:VBP(vertical back porch),垂直同步后肩
  • lower_margin:VFP(vertical front porch),垂直同步前肩
  • hsync_len :HSPW(horizontal sync pulse width),行同步脉宽
  • vsync_len:VSPW(vertical sync pulse width),垂直同步脉宽
  • vmode :大多数使用 FB_VMODE_NONINTERLACED,也就是不使用隔行扫描。

这些参数需要与实用的LCDd的参数一致。

野火的7寸RGB屏幕(GT911,800x480)的一些参数如下:

参数
width800
height480
HBP46
HFP22
VBP23
VFP22
HSW1
VSW1

注意像素时钟pixclock的计算方法:以野火的 7 寸RGB屏为例,屏幕要求的像素时钟为27.4MHz,因此:pixclock=(1/27400000)*10^12=36496

像素时钟就是 RGB LCD 的时钟信号,以 GT911这款屏幕为例,显示一帧图像所需要的时钟数就是: (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP) = (1 + 23 + 480+ 22) * (1+ 46+ 800+ 22) = 526* 869 = 457094。 显示一帧图像需要457094个时钟数, 那么显示60帧就是: 457094* 60 = 27425640≈27.4M,所以像素时钟就是27.4MHz

由以上的屏幕参数,可以得出GT911屏幕的配置参数如下:

struct display_info_t const displays[] = {{
	.bus = MX6UL_LCDIF1_BASE_ADDR,
	.addr = 0,
	.pixfmt = 24,
	.detect = NULL,
	.enable	= do_enable_parallel_lcd,
	.mode	= {
		.name			= "GT911",
		.xres           = 800,
		.yres           = 480,
		.pixclock       = 36496,
		.left_margin    = 46,  //HBPD
		.right_margin   = 22,  //HFPD
		.upper_margin   = 23,  //VBPD
		.lower_margin   = 22,  //VFPD
		.hsync_len      = 1,   //HSPW
		.vsync_len      = 1,   //VSPW
		.sync           = 0,
		.vmode          = FB_VMODE_NONINTERLACED
} } };

1.2 修改h文件配置

另外还要修改include/configs/路径下的mx6ull_myboard.h,找到所有如下语句:

panel=TFT43AB 

修改为:

panel=GT911 //与mx6ull_myboard.c中修改的名称保持一致

修改完成以后重新编译一遍 uboot 并烧写到 SD 中启动。

1.3 编译测试

将修改后的uboot编译下载以后,LCD 驱动一般就会工作正常了,LCD 上会显示 NXP 的 logo。

但某些情况有可能还会遇到LCD 并没有工作,还是黑屏,这是什么原因呢?

在 uboot 命令模式输入“print”来查看环境变量 panel 的值,会发现panel的值要是TFT43AB(或其他的,反正不是GT911):

panel=TFT43AB
script=boot.scr

Environment size: 2431/8188 bytes
=>

这是因为之前有将环境变量保存到EMMC中,uboot启动以后会先从EMMC中读取环境变量,如果EMMC中没有环境变量的话才会使用 mx6ull_alientek_emmc.h 中的默认环境变量。

如果EMMC中的环境变量panel不等于GT911,那么LCD显示肯定不正常,我们只需要在uboot中修改panel的值为GT911即可,在uboot的命令模式下输入如下命令:

setenv panel GT911 
saveenv 

上述命令修改环境变量panel为GT911并保存后,按下复位键重启uboot,此时 LCD 驱动就工作正常了。

二、网络驱动修改

I.MX6UL/ULL 内部有个以太网 MAC 外设,也就是 ENET ,需要外接一个 PHY 芯片来实现网络通信功能,也就是内部 MAC+ 外部 PHY 芯片的方案。
与nxp原厂的PHY芯片对比,如果自己的板子芯片与其不一致,那引脚设置、芯片地址(板子头文件中)也就要改。
因为所有的PHY,前16个寄存器一模一样,因此uboot里面已经写好了通用PHY驱动,理论上不需要修改,但具体的还是因板子芯片而异。

U-Boot(Universal Boot Loader)需要网络驱动程序的原因有几个:

  1. 远程启动和更新镜像: U-Boot 可以通过网络从远程服务器下载启动镜像,从而支持远程启动系统。这在嵌入式系统中很常见,特别是在网络启动时,网络驱动程序是必不可少的。

  2. 网络调试和测试: 在开发过程中,网络驱动程序使得开发人员可以通过网络与设备进行交互、调试和测试,而无需依赖本地存储介质。在调试过程中免去了繁琐的重复烧写。

  3. 网络引导设备: 一些嵌入式系统可能没有本地存储设备,或者希望通过网络引导操作系统。在这种情况下,U-Boot 需要能够通过网络访问启动镜像

三、设置环境变量bootcmd bootargs

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

环境变量 bootcmd

bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。可以在 uboot 启动以后进入命令行设置 bootcmd 环境变量的值。如果 EMMC 或者 NAND 中没有保存 bootcmd 的值,那么 uboot 就会使用默认的值,板子第一次运行 uboot 的时候都会使用默认值来设置 bootcmd 环境变量。
我们可以在mx6ull_myboard_emmc.h 文件中通过设置宏 CONFIG_BOOTCOMMAND 来设置 bootcmd 的默认值
 NXP 官方将 CONFIG_BOOTCOMMAND 写的复杂只有一个目的:为了兼容多个板子,所以写了个很复杂的脚本。当我们明确知道我们所使用的板子的时候就可以大幅简化宏 CONFIG_BOOTCOMMAND 的 设 置 , 比 如 我 们 要 从 EMMC 启动,那么宏
CONFIG_BOOTCOMMAND 就可简化为:
#define CONFIG_BOOTCOMMAND \
mmc dev 1 //切换到 EMMC
fatload mmc 1:1 0x80800000 zImage //读取 zImage 到 0x80800000 处
fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb //读取设备树到 0x83000000 处
bootz 0x80800000 - 0x83000000 //启动 Linux
或者可以直接在 uboot 中设置 bootcmd 的值,这个值就是保存到 EMMC 中的,命令如下:
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;

环境变量 bootargs

bootargs 保存着 uboot 传递给 Linux 内核的参数。bootargs 环境变量是由 mmcargs 设置的, mmcargs 环境变量如下:
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
可以看出环境变量 mmcargs 就是设置 bootargs 的值为“ console= ttymxc0, 115200 root=
/dev/mmcblk1p2 rootwait rw ”, bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使
用到,常用的参数有:
1 console
console 用来设置 linux 终端 ( 或者叫控制台 ) ,也就是通过什么设备来和 Linux 进行交互,是
串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样
我们就可以在电脑上通过 SecureCRT 来和 linux 交互了。这里设置 console ttymxc0 ,因为 linux启动以后 I.MX6ULL 的串口 1 linux 下的设备文件就是 /dev/ttymxc0 ,在 Linux 下,一切皆文件。
ttymxc0 后面有个“ ,115200 ”,这是设置串口的波特率, console=ttymxc0,115200 综合起来就是设
ttymxc0 (也就是串口 1 )作为 Linux 的终端,并且串口波特率设置为 115200
2 root
root 用来设置根文件系统的位置, root=/dev/mmcblk1p2 用于指明根文件系统存放在mmcblk1 设备的分区 2 中。 EMMC 版本的核心板启动 linux 以后会存在 /dev/mmcblk0 、/dev/mmcblk1、 /dev/mmcblk0p1 /dev/mmcblk0p2 /dev/mmcblk1p1 /dev/mmcblk1p2 这样的文件,其中/dev/mmcblkx(x=0~n) 表示 mmc 设备,而 /dev/mmcblkxpy(x=0~n,y=1~n) 表示 mmc 设备x 的分区 y 。在 I.MX6U-ALPHA 开发板中 /dev/mmcblk1 表示 EMMC ,而 /dev/mmcblk1p2 表示EMMC 的分区 2
root 后面有“ rootwait rw ”, rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话
mmc 设备还没初始化完成就挂载根文件系统会出错的。 rw 表示根文件系统是可以读写的,不加
rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
3 rootfstype
此选项一般配置 root 一起使用, rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs jffs ubifs 的话就需要设置此选项,指定根文件系统的类型。
bootargs 常设置的选项就这三个

四、uboot启动Linux测试

五、总结

uboot 移植到此结束,简单总结一下 uboot 移植的过程:
①、不管是购买的开发板还是自己做的开发板,基本都是参考半导体厂商的 dmeo 板,而半导体厂商会在他们自己的开发板上移植好 uboot linux kernel rootfs 等,最终制作好 BSP 包提供给用户。我们可以在官方提供的 BSP 包的基础上添加我们的板子,也就是俗称的移植。
②、我们购买的开发板或者自己做的板子一般都不会原封不动的照抄半导体厂商的 demo
板,都会根据实际的情况来做修改,既然有修改就必然涉及到 uboot 下驱动的移植。
③、一般 uboot 中需要解决串口、 NAND EMMC SD 卡、网络和 LCD 驱动,因为 uboot
的主要目的就是启动 Linux 内核,所以不需要考虑太多的外设驱动。
④、在 uboot 中添加自己的板子信息,根据自己板子的实际情况来修改 uboot 中的驱动。

资料来源:i.MX6ULL嵌入式Linux开发2-uboot移植实践 - 知乎

  • 32
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值