1. 概述
SDR-B1是正旗通信推出的基于Xilinx XC7Z045 + ADI AD9363/AD9361的软件无线电平台,在V1.0及V1.1的硬件设计中,均不支持EEPROM存储芯片。近期有客户提出需要在SDR-B1上增加EEPROM用于存储MAC地址、序列号等信息,本文档给出基于SDR-B1 V1.1版本增加EEPROM存储芯片的完整过程。文中所用的EEPROM芯片型号是AT24C02。
2. 修改Vivado工程
EEPROM存储芯片多为I2C接口,在原始的SDR-B1 Vivado工程中,并未将I2C接口引出,所以首先需要修改Vivado工程。
(1) 打开SDR-B1的Vivado工程,双击工程文件中的system.bd,然后双击右侧窗口中出现的ZYNQ,进入Re-customize IP界面,如下图
点击左侧的Peripheral I/O Pins,勾选右侧的I2C 0,由于I2C 0对应的MIO接口已被占用,所以Vivado自动将I2C 0分配到了EMIO,如下图
然后点击OK,关闭Re-customize IP界面。此时可以看到ZYNQ多出了I2C 0接口,在上面点击右键-->Make External,如下图
然后可以进行Regenerate Layout和Validate Design,确认无误后可进行下一步。
(3) 在左侧的源码结构中的system.bd上面点击右键重新Generate Output Products,如下图
然后再重新Create HDL Wrapper,如下图
并将新生成的system_wrapper.v的内容复制到原始的system_wrapper.v中,以便上层对其进行例化,如下图
然后将新生成的system_wrapper.v从工程中删除即可,如下图
(4) 修改system_top.v,在system_top模块中增加如下两行:
inout i2c0_sda,
inout i2c0_scl,
修改system_wrapper例化模块,增加如下两行:
.IIC_0_0_scl_io(i2c0_scl),
.IIC_0_0_sda_io(i2c0_sda),
修改sdr_b1.xdc,增加如下三行:
# I2C0 (just for test, pl_gpio_0 as i2c0_sda, pl_gpio_1 as i2c0_scl)
set_property -dict {PACKAGE_PIN AF17 IOSTANDARD LVCMOS33} [get_ports i2c0_sda]
set_property -dict {PACKAGE_PIN AG16 IOSTANDARD LVCMOS33} [get_ports i2c0_scl]
也就是采用PL_GPIO_0作为I2C 0的SDA引脚,PL_GPIO_1作为I2C 0 的SCL引脚。选择PL_GPIO_0与PL_GPIO_1作为SDA及SCL是因为这两个引脚本身已具备上拉电阻,只需将原有的接地电容取下即可。
(5) 在Vivado中进行Generate Bitstream,Viviado 重新生成system_top.bit及system_top.hdf文件后,将其复制到Linux下,供Petalinux工程使用。
3. 修改u-boot
(1) 新建Petalinux工程,此处与《SDR-B1软件无线电平台开发环境搭建》一文中的过程类似,但是可以省去其中的某些步骤。假定已将system_top.bit及system_top.hdf文件放置在/home/lics/data/share/sdr_b1_v12/目录,依次输入以下命令:
cd ~data/code/petalinux/
source /home/lics/data/code/petalinux/settings.sh
petalinux-create --type project --template zynq --name sdr_b1_v12
cd sdr_b1_v12
cp -a /home/lics/data/share/sdr_b1_v12/* .
petalinux-config --get-hw-description=/home/lics/data/code/petalinux/sdr_b1_v12
在出现的配置界面上选择Yocto Settings,敲击回车,然后在下一个配置界面上选择User Layers,敲击回车,在user layer 0中填入meta-adi-core的路径,即/home/lics/data/code/petalinux/meta-adi/meta-adi-core,在user layer 1中填入meta-adi-xilinx的路径即/home/lics/data/code/petalinux/meta-adi/meta-adi-xilinx,如下图
(2) 修改project-spec/meta-user/conf/petalinuxbsp.conf,增加以下内容:
KERNEL_DTB = "zynq-adrv9361-z7035-bob"
RM_WORK_EXCLUDE += "u-boot-xlnx"
RM_WORK_EXCLUDE += "linux-xlnx"
其中KERNEL_DTB用于指定dtb即设备树文件,RM_WORK_EXCLUDE的作用是编译后不删除源码(Petalinux在编译完成后会删除源代码,以节省硬盘空间),即保留u-boot-xlnx及linux-xlnx。
使用petalinux-build编译一遍,此步骤会耗费较多时间。
(3) 首次编译完成后,可以在build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/u-boot-xlnx/v2019.01-xilinx-v2019.1+git999-r0/git下可以找到u-boot源码,将其复制出去,例如放到components/ext_sources/uboot-source/中。
运行petalinux-config,进入Linux Components Selection ---> u-boot (u-boot-xlnx) --->,选择ext-local-src,然后exit回到上一步,进入External u-boot local source settings --->,将其设置为u-boot源码的目录,本文档中为/home/lics/data/code/petalinux/sdr_b1_v12/components/ext_sources/uboot-source/,然后保存,退出petalinux-config。
此后对u-boot源码进行修改,只需要修改uboot-source中的源码即可。
进入sdr_b1_v12/components/ext_sources/uboot-source目录,输入以下命令:
cp board/freescale/common/sys_eeprom.c board/xilinx/zynq/
cp board/varisys/common/eeprom.h board/xilinx/zynq/
vi board/xilinx/zynq/sys_eeprom.c
将
#include "../common/eeprom.h"
if (!env_get(enetvar))
改为
#include "eeprom.h"
//if (!env_get(enetvar))
输入以下命令:
vi board/xilinx/zynq/Makefile
增加以下内容:
obj-$(CONFIG_ID_EEPROM) += sys_eeprom.o
输入以下命令:
vi board/xilinx/zynq/Kconfig
增加以下内容:
config ID_EEPROM
bool "support ID eeprom"
default y
help
Say Y here to add support for Sample
at Reset Utility. You need this only if
you work on a Marvell development board.
If not, keep this off to reduce code size
config SYS_I2C_EEPROM_CCID
bool "support I2C_EEPROM_ID"
default y
help
Say Y here to add support for Sample
at Reset Utility. You need this only if
you work on a Marvell development board.
If not, keep this off to reduce code size
config SYS_I2C_EEPROM_NXID
bool "support I2C_EEPROM_NXID"
default n
help
Say Y here to add support for Sample
at Reset Utility. You need this only if
you work on a Marvell development board.
If not, keep this off to reduce code size
回到sdr_b1_v12目录,输入以下命令:
vi project-spec/meta-plnx-generated/recipes-bsp/u-boot/configs/config.cfg
增加以下内容:
CONFIG_ID_EEPROM=y
CONFIG_SYS_I2C_EEPROM_CCID=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_DM_I2C_COMPAT=y
CONFIG_I2C_EEPROM=y
CONFIG_SYS_I2C_EEPROM_ADDR=0x50
CONFIG_SYS_EEPROM_SIZE=256
CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=3
CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=10
CONFIG_SYS_I2C_EEPROM_ADDR_LEN=1
CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW=0x2
CONFIG_SPL_I2C_EEPROM=y
CONFIG_SYS_EEPROM_BUS_NUM=0
其中,CONFIG_SYS_I2C_EEPROM_ADDR用于指定EEPROM芯片的地址,本文中为0x50;CONFIG_SYS_I2C_EEPROM_ADDR_LEN用于设定地址长度,AT24C02的地址长度是1个字节,所以设置为0x1;CONFIG_SYS_EEPROM_BUS_NUM用于指定I2C Bus编号,本文中为0。此时,对于u-boot源码的修改已经完成。
4. Linux代码修改
(1) 对于Linux代码的修改,本文并未使用与u-boot相同的方式,而是采用了打补丁的方式。输入以下命令:
cd ~/data/code
git clone -b 2019_R2 https://github.com/analogdevicesinc/linux.git linux_adi_2019r2
cd linux_adi_2019r2
vi arch/arm/boot/dts/zynq-adrv9361-z7035-bob.dts
将axi_i2c0节点改为disabled,新增i2c0节点,如下
&axi_i2c0 {
status="disabled";
ad7291-bob@2f {
compatible = "adi,ad7291";
reg = <0x2f>;
};
eeprom@50 {
compatible = "at24,24c32";
reg = <0x50>;
};
};
&i2c0 {
status="okay";
eeprom@50 {
compatible = "at24,24c02";
reg = <0x50>;
};
};
然后输入以下命令:
git diff > 0001-dts-add-eeprom-for-i2c0-by-zencheer.patch
(2) 将得到的0001-dts-add-eeprom-for-i2c0-by-zencheer.patch复制到sdr_b1_v12/project-spec/meta-user/recipes-kernel/linux/linux-xlnx中,并在sdr_b1_v12/project-spec/meta-user/recipes-kernel/linux中创建linux-xlnx_%.bbappend文件,其内容如下:
SRC_URI_append += "file://0001-dts-add-eeprom-for-i2c0-by-zencheer.patch"
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
这样就可以在编译Linux的过程中打上0001-dts-add-eeprom-for-i2c0-by-zencheer.patch补丁。此时针对Linux的源码修改已经完成。
5. 验证
(1) 进入sdr_b1_v12目录,再次使用petalinux-build进行编译,待编译完成后,依次输入以下命令:
cd images/linux/
petalinux-package --boot --format BIN --fsbl zynq_fsbl.elf --fpga system.bit --u-boot --force
cd ../..
rm -rf /home/lics/data/share/linux
cp -a images/linux /home/lics/data/share/
此时就可以将编译得到的BOOT.bin及image.ub复制到TF卡中进行测试。
(2) 为SDR-B1加电,当串口中出现”Hit any key to stop autoboot:”时按下回车,依次输入以下命令:
mac id
mac num 00000011
mac errata ..
mac date 250427143600
mac 0 b8:8e:df:88:88:88
mac 1 b8:8e:df:88:88:89
mac save
当串口中出现“Programming passed.”则表明以上信息已正确写入。如下图
(3) 此时输入mac命令,即可显示写入的MAC地址、序列号等信息,如下图
输入printenv命令,可以看到ethaddr与ethaddr1也是正确的数值,如下图
(4) 重启板卡,待板卡启动完成后,输入用户名root及密码root进入Linux,使用ifconfig命令,可以看到eth0的mac地址正是此前在u-boot下写入的数值,如下图
eth1未显示是由于Linux代码尚不完善造成的,这不影响对EEPROM存储芯片的验证结果。