1.2 uboot移植过程

本博客主要对学习嵌入式Linux进行总结,学习视频参考正点原子。开发板使用Imx6ull芯片。

Uboot移植

使用的是SOC芯片厂家提供的评估板Uboot,在此基础上进行修改以适合自己的板子
对于uboot移植,一般分为三部分
第一部分:添加编译器编译uboot,下载验证
第二部分:添加板子默认配置文件defconfig(基于厂商uboot修改)
第三部分:修改SD卡\EMMC驱动或Nand,LCD显示驱动,网络驱动

1 第一部分:添加编译器编译uboot及下载验证

# 为了不用一行行输入编译指令,创建mx6ull_mynand.sh脚本,进行编译,并给脚本权限运行./ mx6ull_mynand.sh
# ARCH=arm指定所构建的软件的目标架构,CROSS_COMPILE=arm-linux-gnueabihf- 指定编译器工具链
# 可以查到后面命令分别为distclean,mx6ull_mynand_defconfig,-j4。
# 其中distclean是清除工程中的一些文件,mx6ull_mynand_defconfig为创建的配置信息文件(稍后讲解),-j4为4个线程进行编译。
# 使用sudo chmod 777 mx6ull_mynand.sh赋予权限,使用./mx6ull_mynand.sh运行脚本
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_mynand_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- V=1 -j4
# 修改Uboot的架构和编译器工具链
# 在顶层Makefile文件中找到ARCH和CROSS_COMPILE添加架构和编译器
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
# 运行mx6ull_mynand.sh脚本进行编译,编译完成产生u-boot.bin。
# 此文件不能直接下载进开发板,需要用nxp官方提供的imxdownload向该文件中添加头部信息
# 插入sd卡,在根目录下输入./imxdownload u-boot.bin /dev/sdb -256m
# /dev/sdb为SD卡设备文件 ,-256m是对应256M的ddr内存
# 注意:如果不成功试一试将SD卡进行格式化。
./imxdownload u-boot.bin /dev/sdb -256m

2 第二部分:添加板子配置信息(defconfig文件)

# 对于defconfig文件是基于nxp官方评估板进行修改
# 将根目录下configs文件夹下的mx6ull_14x14_evk_nand_defconfig复制并改名为mx6ull_mynand_defconfig

在这里插入图片描述

# 1.确定mx6ull_mynand.sh脚本中的make编译配置文件名称与创建的mx6ull_mynand_defconfig文件名一致

在这里插入图片描述

# 2.修改mx6ull_mynand_defconfig文件中的1和4行添加自己修改的名字,注意第1行修改的名字要和第5步骤的板级文件夹名称对应上

在这里插入图片描述

# 3.添加开发板对应的头文件,这里直接拷贝使用nxp官方评估板的头文件,位置在include/configs/mx6ullevk.h将其改名为mx6ull_mynand.h

在这里插入图片描述

# 4. 修改mx6ull_mynand.h中的宏定义,在8和9行位置

在这里插入图片描述

# 5.添加板子对应的板级文件夹,每个板子都有特有的文件,将mx6ull的拷贝,在board/freescale/mx6ullevk文件夹并改名为mx6ull_mynand
# 注意:该文件夹名称必须与步骤2中修改的第一行名称一致

在这里插入图片描述

# 6.修改mx6ull_mynand目录下的mx6ullevk.c名字改为mx6ull_mynand.c

在这里插入图片描述

# 7.修改mx6ull_mynand目录下的Makefile文件使其能够编译输出.o

在这里插入图片描述

# 8.修改mx6ull_mynand目录下的imximage.cfg文件,此目录要与板级支持包对应上,里存放DCD数据,以及DDR的寄存器配置信息

在这里插入图片描述

# 9.修改mx6ull_mynand目录下的Kconfig文件,修改板级信息

在这里插入图片描述

# 10.修改mx6ull_mynand目录下的MAINTAINERS文件 ,路径要对应上

在这里插入图片描述

# 11.修改图形化界面的Kconfig文件,在my_uboot/arch/arm/cpu/armv7/mx6/Kconfig添加配置信息
# 注意:287行路径要对应上

在这里插入图片描述
在这里插入图片描述

# 进行编译./ mx6ull_mynand.sh
# 在board/freescale/mx6ull_mynand目录下出现mx6ull_mynand.o文件表示成功
# 或者搜索mx6ull_mynand.h文件是否被多个文件引用判断(grep -nR "mx6ull_mynand.h"),若有则表示成功

在这里插入图片描述
在这里插入图片描述

3 第三部分:修改SD卡\EMMC驱动或Nand,LCD显示驱动,网络驱动(主要修改mx6ull_mynand.c和mx6ull_mynand.h文件)

# 经过第二部分,此时DDR和存储器EMMC(Nand)已经正常即最小系统,对于自己开发板和NXP官方开发板使用的LCD显示器和网络芯片会有所不同,需要修改uboot进行适配。
# 对于DDR、EMMC/SD卡和NAND存储驱动一般SOC厂家评估板是适配好的。需要修改LCD和网络驱动
# 修改LCD显示驱动适配自己的LCD显示器,能够通过显示器查看uboot输出信息。
# 修改网络驱动,能够实现从网络启动linux

3.1 mx6ull_mynand.h文件详解

# 对于uboot裁剪主要是使用mx6ull_mynand.h该文件
# 若需要某个功能的话就在里面添加这个功能对应的 CONFIG_XXX 宏,若不需要某个功能的话就删除掉对应的宏
14行:include "mx6_common.h",整个mx6的通用头文件,定义了mx6相关的通用宏定义,在使用过程中,若某些宏定义在mx6ull_mynand.h中没有找到,但又定义了可在mx6_common.h中查找
第23行:CONFIG_SECURE_BOOT,安全启动宏定义
第30行:is_mx6ull_9x9_evk(),判断是不是9x9evk的开发板,使用的不是9x9evk开发板,不用管
第35行:PHYS_SDRAM_SIZE,DDR内存大小,根据自己的板子设置,我使用的是DDR内存256m
第48行:CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG,在mx6ullevk.c文件中1192行使用了该宏定义,确定了board_name和board_rev
第50行:CONFIG_DISPLAY_CPUINFO,uboot启动的时候可以输出CPU信息
第51行:CONFIG_DISPLAY_BOARDINFO,uboot启动的时候可以输出板子信息,在board_f.c中924行使用,调用checkboard函数
第54行:CONFIG_SYS_MALLOC_LEN,malloc内存池的长度,16M
第56行:CONFIG_BOARD_EARLY_INIT_F,会在board_init_f使用,即在common/board_f.c的855行中调用,初始化串口的IO配置
第57行:CONFIG_BOARD_LATE_INIT,会在board_init_r使用,即在common/board_r.c的956行调用,开发板级别的一些晚期初始化。此时说明开发板级别的硬件软件初始化结束了。
第59-60行:CONFIG_MXC_UART,CONFIG_MXC_UART_BASE,使能I.MX6ULL的串口,宏 CONFIG_MXC_UART_BASE串口寄存器基地址,使用串口1,基地址为UART1_BASE,UART1_BASE定义在文件,arch/arm/include/asm/arch-mx6/imx-regs.h中,imx-regs.h是I.MX6ULL寄存器描述文件,由imx-regs.h得UART1_BASE的值UART1_BASE= (ATZ1_BASE_ADDR+0x20000)=AIPS1_ARB_BASE_ADDR+0x20000=0x02000000+0x2000063-64行:CONFIG_FSL_USDHC,CONFIG_SYS_FSL_ESDHC_ADDR,MMC的配置,EMMC接在I.MX6ULL的USDHC2上,宏CONFIG_SYS_FSL_ESDHC_ADDR为EMMC所使用接口的寄存器基地址,也就是USDHC2的基地址。
第67-70行:CONFIG_SYS_USE_NAND,CONFIG_SYS_FSL_USDHC_NUM,判断MMC的设备数,若使用Nand则MMC设备数为1,若没有使用则MMC设备数为2(EMMC和SD卡)
第75-81:CONFIG_CMD_I2C,I2C配置,定义了IIC接口相关配置,使用的总线以及速度
第84-87行:CONFIG_POWER,PMIC配置,这个只和9x9evk开发板有关,不用管
第90行:CONFIG_SYS_MMC_IMG_LOAD_PART,EMMC设备分区
第92-96行:CONFIG_MFG_NAND_PARTITION,Nand分区设置,若使用Nand设备,则默认的NAND分区为:"mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "98-111行:CONFIG_MFG_ENV_SETTINGS,定义了一些环境变量,使用MfgTool烧写系统时候会用到这里面的环境变量
第113-127行:CONFIG_EXTRA_ENV_SETTINGS,烧写到Nand里面的环境变量,此宏会设置bootargs这个环境变量
第129-201行:CONFIG_EXTRA_ENV_SETTINGS,烧写到EMMC里面的环境变量,定义了使用Emmc时的环境变量,此宏会设置bootargs这个环境变量
第205-218行:CONFIG_BOOTCOMMAND,设置bootcmd环境变量
第221行:CONFIG_CMD_MEMTEST,使能内存测试命令
第222-223行:CONFIG_SYS_MEMTEST_START,CONFIG_SYS_MEMTEST_END,测试的内存起始地址和内存大小
第225行:CONFIG_SYS_LOAD_ADDR,linux内核的起始地址,宏CONFIG_SYS_LOAD_ADDR表示linux kernel在DRAM 中的加载地址,也就是linux kernel在DRAM中的存储首地址,CONFIG_LOADADDR=0X80800000226行:CONFIG_SYS_HZ,系统时钟频率,这里为 1000Hz
第228行:CONFIG_STACKSIZE,宏CONFIG_STACKSIZE为栈大小,这里为128KB
第230行:CONFIG_NR_DRAM_BANKS,ddr的banks,宏CONFIG_NR_DRAM_BANKS为DRAM BANK的数量,I.MX6ULL只有一个DRAM BANK,我们也只用到了一个 BANK,所以为 1。
第231行:PHYS_SDRAM,ddr的外设寄存器地址,宏PHYS_SDRAM为I.MX6ULL的DRAM控制器MMDC0所管辖的 DRAM范围起始地址,也就是0X80000000。
第233行:CONFIG_SYS_SDRAM_BASE,宏CONFIG_SYS_SDRAM_BASE为DRAM的起始地址
第234行:CONFIG_SYS_INIT_RAM_ADDR,宏CONFIG_SYS_INIT_RAM_ADDR为I.MX6ULL内部IRAM的起始地址(也就是OCRAM的起始地址),为 0X00900000。
第235行:CONFIG_SYS_INIT_RAM_SIZE,宏CONFIG_SYS_INIT_RAM_SIZE为I.MX6ULL内部IRAM的大小(OCRAM的大小),为 0X00040000=128KB。
第237-240行:CONFIG_SYS_INIT_SP_OFFSET,CONFIG_SYS_INIT_SP_ADDR,宏 CONFIG_SYS_INIT_SP_OFFSET 和 CONFIG_SYS_INIT_SP_ADDR 与初始 SP 有关,第一个为初始 SP 偏移,第二个为初始 SP 地址。
第245-247:CONFIG_SYS_BOOT_QSPI,QSPI启动相应宏定义
第248-250:CONFIG_SYS_BOOT_NAND,Nand启动相应宏定义
第256行:CONFIG_SYS_MMC_ENV_DEV,宏CONFIG_SYS_MMC_ENV_DEV为默认的MMC设备,这里默认为USDHC2,也就是EMMC
第257行:CONFIG_MMCROOT,宏CONFIG_MMCROOT设置进入linux系统的根文件系统所在的分区,这里设置为"/dev/mmcblk1p2",也就是EMMC设备的第2个分区。第0个分区保存 uboot,第1个分区保存linux 镜像和设备树,第2个分区为Linux系统的根文件系统
第262-274行:CONFIG_FSL_QSPI,从QSPI启动,相应地址偏移
第278-286行:CONFIG_SYS_USE_NAND,从NAND启动,相应地址偏移
第294行:CONFIG_ENV_SIZE,宏CONFIG_ENV_SIZE为环境变量大小,默认为8KB
第296行:CONFIG_ENV_OFFSET,宏CONFIG_ENV_OFFSET为环境变量偏移地址,这里的偏移地址是相对于存储器的首地址。如果环境变量保存在EMMC中的话,环境变量偏移地址为12*64KB。如果环境变量保存在 SPI FLASH 中的话,偏移地址为768*1024。如果环境变量保存在NAND中的话,偏移地址为 60<<20(60MB),并且重新设置环境变量的大小为 128KB。
第297-303行:CONFIG_ENV_IS_IN_SPI_FLASH,QSPI启动,进行相应配置
第304-309行:CONFIG_ENV_IS_IN_NAND,从NAND Flash启动进行相应配置
第314-325行:CONFIG_CMD_USB,USB 配置,与 USB 相关的宏定义。
第328-333行:CONFIG_CMD_NET,网络配置,与网络相关的宏定义,比如使能 dhcp、ping 等命令
第334行:CONFIG_FEC_ENET_DEV,宏CONFIG_FEC_ENET_DEV指定uboot所使用的网口,I.MX6ULL有两个网口,为0的时候使用ENET1,为1的时候使用ENET2。
第336行:IMX_FEC_BASE,宏IMX_FEC_BASE为ENET接口的寄存器首地址
第337行:CONFIG_FEC_MXC_PHYADDR,宏CONFIG_FEC_MXC_PHYADDR为网口PHY芯片的地址
第338行:CONFIG_FEC_XCV_TYPE,为PHY 芯片所使用的接口类型,I.MX6U-ALPHA开发板的两个PHY 都使用的RMII接口
第353-356行:CONFIG_VIDEO,宏用于开启 LCD
第357-362行:CONFIG_VIDEO_LOGO,使能LOGO显示
第363-366行:CONFIG_CMD_BMP,使能BMP图片显示指令

3.2 mx6ull_mynand.c文件详解

mx6ull_mynand.c文件主要进行串口,I2C,MMC,QSPI,NAND,USB,LCD等引脚配置
第231-328行:CONFIG_SYS_I2C_MXC,I2C引脚等相关配置
第330-335行:dram_init(void),DRAM初始化函数
第337-340行:uart1_pads[],串口引脚配置数组,里面定义了寄存器地址和数值
第342-354行:usdhc1_pads[],要使用EMMC或NAND,需要进行相应配置,默认配置是SD卡,EMMC的配置重新工作,里面定义了寄存器地址和数值
第362-379行:usdhc2_emmc_pads[],要使用EMMC或NAND,需要进行相应配置,默认配置是SD卡,NAND的配置重新工作,里面定义了寄存器地址和数值。
第381-402行:usdhc2_pads[],NAND的引脚配置数组,里面定义了寄存器地址和数值
第404-407行:setup_iomux_uart,配置串口,会使用到uart1_pads数组
第409-434行:CONFIG_FSL_QSPI,配置quadspi_pads数组引脚和初始化QSPI
第436-558行:CONFIG_FSL_ESDHC,配置MMC和SD驱动器
第560-598行:CONFIG_USB_EHCI_MX6,配置USB—OTG相关参数和引脚
第600-634行:CONFIG_NAND_MXS,配置NAND引脚,nand_pads及初始化
第636-738行:CONFIG_FEC_MXC,配置以太网引脚网口1 fec1_pads,网口2 fec2_pads和初始化
第740-930行:CONFIG_VIDEO_MXS,LCD显示屏引脚lcd_pads配置和显示参数displays
第935-937行:lcd_backlight_pads[],LCD背光引脚配置。
第939-946行:board_early_init_f,板子早期初始化,主要开启LCD背光及进行第404-407行串口初始化
第948-953行:lcd_id_pads,主要是正点原子的LCD显示屏根据引脚不同使用的开发板尺寸不同,因此正点原子加入了该引脚
第955-1098行:select_display_dev函数,根据引脚不同的设置选择不同的LCD显示,设置相应的环境变量并判断是写入NAND还是EMMC/SD卡中,进行不同的驱动,有1280x800屏幕,1024x600屏幕,800x480屏幕。
第1101-1125行:FDT_PATH_ENET1,以太网某些设置(暂不清楚)
第1127-1140行:LED等显示配置leds_pads引脚配置数组,imx6_light_up_led配置函数
第1142-1174行:board_init()函数,根据不同宏定义进行初始化,含有I2C,以太网,USB,QSPI,NAND等
第1176-1184行:board_boot_modes函数,配置总线模式,sd1,sd2,qspi1
第1186-1199行:board_late_init函数,最后进行初始化
第1212-1220行:checkboard()函数,判断使用的开发板
第1222-1259行:CONFIG_FSL_FASTBOOT,获取boot启动方式以及相应环境变量
****************************************************************************************************1310行:CONFIG_SPL_BUILD,判断是否定义宏,uboot源码可以重写board_init_f()函数,不使用common/board_f.c中的board_init_f函数,对于Freescale的imx6ull则重写了该函数,以下代码均是重写的board_init_f里的内容
第1331-1433行:与9x9evk开发板有关,不用管
第1435-1447行:ccgr_init(),寄存器初始化,关闭看门狗
第1449-1453行:spl_dram_init(),进行DDR初始化
第1455-1480行:重写board_init_f()函数,进行各种初始化,即设置AIPS关闭看门狗(arch_cpu_init,ccgr_init)、早期初始化LCD背光串口初始化(board_early_init_f)、定时器设置(timer_init)、串口时钟和GD有效(preloader_console_init)、DDR初始化(spl_dram_init)、清BSS段、最后调用board_init_r函数初始化,该board_init_r函数是common/board_r.c里面的。
			   注意:重写board_init_f函数最后要回到调用board_init_r函数

3.3 DDR、I2C、以太网ETH、USB、QSPI、EMMC、NAND驱动分析

a. 对于DDR的驱动在mx6ull_mynand.c文件重写board_init_f函数中的spl_dram_init函数
b. 对于I2C、以太网、USB、QSPI、EMMC、NAND这些驱动,主要是在mx6ull_mynand.c文件中board_init函数(mx6ull_mynand.c的1142行)完成初始化。
c. board_init函数被board_init_r函数的数组init_sequence_r中调用(在common/board_r.c文件的814行)

# DDR初始化在重写board_init_f函数中,使用spl_dram_init()函数,引脚定义在mx6_ddr_ioregs数组中
# I2C初始化宏定义CONFIG_SYS_I2C_MXC,使用setup_i2c()函数,引脚定义在i2c_pad_info1数组中
# USB初始化宏定义CONFIG_USB_EHCI_MX6,引脚定义在usb_otg_pads数组中,使用setup_usb()函数,在mx6ull_mynand.c文件中创建使用
# QSPI初始化宏定义CONFIG_FSL_QSPI,引脚定义在quadspi_pads数组中,使用board_qspi_init()函数,在mx6ull_mynand.c文件中创建使用
# EMMC初始化宏定义CONFIG_FSL_ESDHC,引脚定义在usdhc2_pads数组中,使用board_mmc_init()函数,在mx6ull_mynand.c文件中创建使用
# NAND初始化宏定义CONFIG_NAND_MXS,引脚定义在nand_pads数组中,使用setup_gpmi_nand()函数,在mx6ull_mynand.c文件中创建使用
总结:board_init_f函数主要完成CPU、定时器、串口和DDR等初始化
	  board_init_r函数主要完成I2C、以太网、USB、QSPI、EMMC、NAND等初始化

3.4 LCD显示驱动修改

# LCD驱动与mx6ull_mynand.c和mx6ull_mynand.h两个文件有关,其中驱动在board_init_r函数中完成。
# mx6ull_mynand.c文件在board/freescale/mx6ull_mynand/mx6ull_mynand.c路径
# mx6ull_mynand.h文件在include/configs/mx6ull_mynand.h路径

a、首先要修改LCD相关驱动需要知道LCD是如何驱动显示的,以下将介绍uboot如何驱动LCD显示,(参考该博客

# 1.首先从mx6ull_mynand.h的头文件定义开始,定义使能宏CONFIG_VIDEO,CONFIG_CFB_CONSOLE,CONFIG_VIDEO_MXS三个。
# 2.其次在mx6ull_mynand.c文件中判断CONFIG_VIDEO_MXS是否使能来配置驱动LCD,配置各个引脚参数使用lcd_pads(要配置的寄存器地址和值)数组,以及LCD显示器的参数使用displays(LCD不同分辨率尺寸)数组。
# 3.对于各个引脚参数cd_pads的配置,使用mx6ull_mynand.c文件中的do_enable_parallel_lcd函数里的imx_iomux_v3_setup_multiple_pads函数进行驱动各个引脚寄存器。
# 4.对于LCD显示器的参数displays配置,
	往上查找:board_video_skip(在arch/arm/imx-common/video.c的13行)函数大量调用displays数组。
	往上查找:drv_video_init(在drivers/video/cfb_console.c文件的2228行)函数调用board_video_skip函数,同时drv_video_init函数调用video_init(在drivers/video/cfb_console.c文件的2112行)函数。
	往上查找:stdio_add_devices(在common/stdio.c文件的249行)函数调用了drv_video_init函数。
	往上查找:init_sequence_r数组(在common/board_r.c文件的776行)调用了stdio_add_devices函数
	往上查找:board_init_r(在common/board_r.c文件的1030行)函数调用了init_sequence_r数组
	
	分析board_video_skip函数:
		上半部分:判断LCD显示屏名字是不是uboot环境变量中的名字,若两者匹配则可以满足驱动条件,若不匹配无法驱动。
		下半部分:调用mxs_lcd_panel_setup(在drivers/video/mxsfb.c文件的52行)函数			
	
	分析video_init函数:
		video_init函数调用了 video_hw_init (在drivers/video/mxsfb.c文件的190行)这个函数,同时video_hw_init 函数调用同一个文件中的mxs_lcd_init进一步进行初始化参数。video_hw_init 函数是最重要的函数,负责了LCD的硬件初始化,这是许多半导体芯片的配置LCD硬件初始化的函数。
	
	分析mxs_lcd_panel_setup函数:
		该函数进一步调用LCD参数

b、LCD驱动流程图
在这里插入图片描述
c、修改LCD参数适配开发板

# 对于uboot的LCD驱动修改主要更改两部分,
	1.引脚修改,即lcd_pads数组参数
	2.LCD显示屏分辨率等参数的修改,即displays数组参数
	3.修改环境变量中LCD的panel字符(在mx6ull_mynand.h)文件中使其与LCD的displays数组中的名字一致

1.更改引脚配置
lcd_pads数组参数(在mx6ull_mynand.c文件中),对于正点原子LCD屏幕来说,没有复位引脚,取消复位引脚。
注释掉:MX6_PAD_SNVS_TAMPER9__GPIO5_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL)
在这里插入图片描述

2.修改LCD显示屏参数
displays数组参数(在mx6ull_mynand.c文件中),本次使用800x480分辨率参数的LCD显示屏(具体的要根据自己使用的LCD进行配置),具体参数:
在这里插入图片描述

对于displays数组中的参数分析:
.bus=MX6UL_LCDIF1_BASE_ADDR,LCD外设寄存器配置首地址(0x21c8000.addr = 0,
.pixfmt = 24,像素格式,采用RGB888
.enable = do_enable_parallel_lcd,调用do_enable_parallel_lcd函数进行lcd_pads引脚参数配置
.mode	= {
		.name			= "ATK7084",使用的屏幕名称,要和环境变量中的panel相等
		.xres           = 800,水平X轴显示区域
		.yres           = 480,垂直y轴显示区域
		.pixclock       = 30030,像素时钟,计算方法为时钟=(VSPW+VBP+LINE+VFP)*(HSPW+HBP+HOZVAL+HFP)=(800+1+46+210)*(480+1+23+22)=555982,显示一幅图像需要555982数,若一帧60fps则时钟555982*60=3335892033.3Mhz,故pixclock=(1/33300000)*10^12=30030
		.left_margin    = 46,水平同步后肩
		.right_margin   = 210,水平同步前肩
		.upper_margin   = 23,垂直同步后肩
		.lower_margin   =22,垂直同步前肩
		.hsync_len      = 1,行同步脉宽
		.vsync_len      = 1,场同步脉宽
		.sync           = 0,
		.vmode          = FB_VMODE_NONINTERLACED,不使用隔行扫描
}

在这里插入图片描述
3.修改环境变量中LCD的panel字符,与displays数组中的name一致
具体更改在mx6ull_mynand.h文件中的环境变量中,具体是panel的字符。
在这里插入图片描述
至此LCD的驱动更改完成

3.5 网络驱动修改

要修改网络驱动,首先需要知道uboot是如何驱动网络芯片的。
对于网络驱动主要在board_init_r函数(common/board_r.c文件中)中的init_sequence_r函数数组的board_init函数
board_init函数在mx6ull_mynand.c文件中重新编写。
故主要驱动在mx6ull_mynand.c文件的board_init函数中

分析网络芯片引脚驱动配置

1.首先对于芯片引脚定义主要在mx6ull_mynand.c文件中fec1_pads和fec2_pads数组中,该数组定义了网口1和网口2的引脚定义
2.fec1_pads和fec2_pads引脚数组被该文件中的setup_iomux_fec函数调用,而该函数又被该文件中的board_eth_init函数调用
3.那么board_eth_init函数又被谁调用呢?经查找该函数被(\net\eth_legacy.c)eth_initialize函数调用
4.eth_initialize函数又被(\common\board_r.c)initr_net函数调用。
5.initr_net函数最终位于init_sequence_r函数数组中,由此被board_init_r函数调用
故网络驱动最终均由该一系列函数配置完成,之后将逐一介绍函数具体功能

以太网芯片驱动流程图
请添加图片描述
启动流程(参考该博客)

board_init_r
--》init_sequence_r
		--》initr_net
				--》eth_initialize:该函数位于(\net\eth_legacy.c文件中)完成整个以太网驱动硬件底层初始化
					--》eth_common_init:该函数位于(\net\eth_common.c)中,主要进行MII和PHY芯片初始化
						--》miiphy_init:该函数位于common\miiphyutil.c文件中
										 初始化链表:mii_devs
										 初始化全局参数:current_mii
						--》phy_init:该函数位于\drivers\net\phy\phy.c文件中,使用宏定义根据不同厂家芯片对应不同的驱动
									 由于板子上使用的是SMSC厂家的芯片,故此处是开启了CONFIG_PHY_SMSC,调用phy_smsc_init函数
									 --》phy_smsc_init;该函数位于\drivers\net\phy\smsc.c文件中,该函数注册了4个phy驱动等待进行匹配(LAN8710芯片,LAN911X芯片,LAN8700芯片,LAN8740芯片)
									 	---》使用phy_register进行配置lan8710_driver数组,该数组定义了芯片的配置信息(.name、.uid等)
					--》board_eth_init:该函数在mx6ull_mynand.c文件中被重新定义,主要是对以太网芯片的引脚进行定义配置以及初始化网络设备
						--》setup_iomux_fec:mx6ull_mynand.c文件中,芯片IO复用的配置,主要配置fec1_pads数组,里面包含了各个引脚
						--》fecmxc_initialize_multi:该函数位于\drivers\net\fec_mxc.c中,进行初始化网络设置
								参数1:bd_t:board info数据结构定义,保存板子参数。
								参数2:CONFIG_FEC_ENET_DEV,选择使用的网络设备。
								参数3:CONFIG_FEC_MXC_PHYADDR,此网络设备链接的phy地址。
								参数4:IMX_FEC_BASE,此网络设备的寄存器地址。
								分析该函数
								---》1.mx6_enet_fused:空函数
								---》2.fec_get_miibus:该函数在drivers\net\fec_mxc.c中
													mdio_alloc:申请mii_dev的内存-bus
													fec_phy_read、fec_phy_write:注册bus.read,bus.write函数
													fec_set_dev_name:设置名称为FEC%i-bus->name
													mdio_register:将bus注册到mii_devs列表中
													fec_mii_setspeed:设置MII_SPEED 
								---》3.phy_find_by_mask:该函数在\drivers\net\phy\phy.c文件中
													bus->reset:跳过,没有注册
													---》get_phy_device_by_mask:
															先查找自己有没有这个设备,没有则开始创建一个phy设备
															---》create_phy_by_mask:读取phyId,若读取到,则使用phy_device_create函数创建phy设备,phy_device_create调用get_phy_driver函数
																---》phy_device_create:创建phy设备
																	---》get_phy_driver:绑定phy驱动,根据读到的phy_id和drv->uid比较(加mark),读取到的phy_id & drv->mask为7c0f0,则绑定的驱动为之前注册的lan8710_driver
																	---》phy_probe(dev):如果驱动有probe,会调用此函数
								---》4.fec_probe:该函数在drivers\net\fec_mxc.c文件中
												1.创建一个网络设备edev,私有内容为fec_priv
													---》fec_alloc_descs
															申请对齐的内存为tbd_base,rbd_base描述符
															申请RX buffer,最多FEC_RBD_NUM,与rbd_base联动
												2.注册网络设备的调用函数
													---》fec_init
														---》fec_set_hwaddr:设置mac地址,iaddr对应寄存器ENETx_IAUR,用于接收带有单播地址的帧的地址识别过程,gaddr对应寄存器ENETx_GAUR,用于接收带有多播地址的帧的地址识别过程,paddr对应寄存器ENETx_PAUR,在暂停帧中精确匹配和源地址字段
														---》fec_tbd_init:初始化传输任务的缓冲区描述符
														---》fec_rbd_init:初始化接收任务的缓冲区描述符
														---》fec_reg_setup:通过配置ENETx_EIMR,用于屏蔽中断,通过配置ENETx_EIR,用于清除事件,通过配置ENETx_RCR,用于设置最大帧长度,和FEC_RCNTRL_RGMII,通过配置ENETx_OPD ,用于配置暂停帧的操作码和暂停时间,通过配置ENETx_TFWR  ,用于传输FIFO写步长,通过配置ENETx_RMON_T_DROP ,用于清空保留寄存器,通过配置eth->r_fstart ,用于注册接受fifo,通过配置ENETx_MRBR,用于设置有效的最大接收缓冲区大小,通过配置ENETx_TDSR,用于指向传输缓冲区描述符队列开头的指针指向tbd_base,通过配置ENETx_RDSR,用于指向接受缓冲区描述符队列开头的指针指向rbd_base
														---》miiphy_restart_aneg:复位phy,设置自协商位
														---》fec_open:启动FEC引擎,通过配置ENETx_TCR,用于设置全双工,通过fec_rbd_clean初始化rbd_base,通过flush_dcache_range刷新描述符在RAM中,通过配置ENETx_ECR,用于HW endian SWAP,通过配置ENETx_TFWR  ,用于store and forward mode,Enable FEC-Lite controller,disable the gasket | wait for the gasket to be disabled ,configure gasket for RMII, 50 MHz, no loopback, and no echo,re-enable the gasket | wait until MII gasket is ready ,Start up the PHY,Enable SmartDMA receive task
													---》fec_send:
																  发送一帧
																  检查帧大小,需要大于0小于1500
																  设置传输缓冲区。总是使用第一个缓冲区进行传输,第二个缓冲区将为空,只用于停止DMA引擎。还将包刷新到RAM中以避免缓存问题。
																  现在更新BD的状态
																  刷新数据缓存。这段代码将两个TX描述符都刷新到RAM。
																  读取DMA描述符的最后四个字节DRAM
																  开启SmartDMA传输任务功能 | 等待直到帧被发送。
													 ---》fec_recv:
													 			  读出一帧
													 			  检查是否发生了任何关键事件 | 并处理
													 			  在读取状态之前,必须使数据缓存失效,因为RAM中的数据可能已经被DMA更改了。
													 			  获取缓冲区地址和大小
													 			  在缓冲区上使数据缓存失效
													 			  填充缓冲区并将其传递给上层
													 			  释放当前缓冲区,重新启动引擎并向前移动到下一个缓冲区
													 ---》fec_halt:
																  停止FEC引擎
												   	 ---》fec_set_hwaddr	  
												   	 			  见fec_init的第一个函数
												3.Reset chip
												4.对FEC寄存器进行初始配置
												5.绑定phy设备,并调用phy驱动的config和函数配置
												6.检查mac地址是否有效
												
				--》reset_phy:对PHY芯片进行复位

修改以太网驱动,主要修改mx6ull_mynand.c和mx6ull_mynand.h文件

# PHY芯片是LAN8720A,LAN8720A有一个管理接口,叫做MDIO,两根线,MDIO和MDC,一个MDIO可以管理32个PHY芯片。
# MDIO通过PHY ADDR来确定访问哪个PHY芯片,PHY的第10脚,每个PHY芯片都有一个复位引脚,根据所使用的开发板配置
# LAN8720驱动,所有的PHY芯片的前16个寄存器一致,uboot里面已经写好了通用PHY驱动。
# 需要修改mx6ull_mynand.c和mx6ull_mynand.h文件

1. 修改mx6ull_mynand.h文件

该开发板使用的是ENT1网口,CONFIG_FEC_ENET_DEV定义为0使用ENET1网口,定义为1使用ENET2网口。

在这里插入图片描述

修改PHY地址,因使用的是ENET1网口,改ENET1对应的PHY地址,由原理图的第10脚可知地址为0x0

在这里插入图片描述
2. 修改mx6ull_mynand.c文件

删除原有的74lv595的驱动代码,增加复位引脚,该开发板PHY芯片复位引脚是SNVS_TAMPER9即GPIO5_IO09。

请添加图片描述

删除以下部分

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

请添加图片描述

添加网络复位引脚驱动,找到fec1_pads[],添加复位引脚电气属性变量

在这里插入图片描述

配置复位引脚电气属性

请添加图片描述
3. 修改phy.c文件在drivers/net/phy/phy.c,添加以下代码
请添加图片描述
至此以太网驱动修改完成

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值