はじめに
筆者は、次の記事で示すように https://www.denx.de/wiki/U-Boot が提供しているu-boot をカスタマイズして使っています。
- 「ZYBO用U-Bootを、ブート時にuEnv.txtを読むようにして、かつBOOT.binから起動できるようにする」 @Qiita
- 「ZYBO用U-Bootでブート時にメニューを表示させる」 @Qiita
https://www.denx.de/wiki/U-Boot が提供している ZYNQ 用の u-boot では、MAC アドレスは I2C ROM から読むか、環境変数 ethaddr に設定しておくかしか出来ません。もし設定されていなければ、乱数を使って MAC アドレスを設定します。
しかし、ZYBO-Z7 では SPI ROM (S25FL128S 4-bit Quad-SPI serial NOR flash) の OTP(One-Time-Programmable) 領域に MAC アドレスに格納されています。この記事では https://www.denx.de/wiki/U-Boot が提供している ZYNQ 用の u-boot を SPI ROM から MAC アドレスを読んで設定するようにソースコードを修正する方法を説明します。
なお、この修正を施した ZYBO-Z7 用の U-Boot のイメージを次の URL で公開しています。
U-Boot のビルドの手順
U-Boot のダウンロード
shell$ git clone git://git.denx.de/u-boot.git
shell$ cd u-boot
U-Boot v2017.11 をチェックアウトして作業用のブランチを作る
この記事では v2017.11 を元に変更します。ここでは ZYBO-Z7 用の U-Boot を作る場合の例を示します。
shell$ git checkout -b u-boot-2017.11-zynq-zybo-z7 refs/tags/v2017.11
board/xilinx/zynq/board.c を修正する
board/xilinx/zynq/board.c に spi 関連のヘッダファイルをインクルードするようにします。
#include <fdtdec.h>
#include <fpga.h>
#include <mmc.h>
#include <spi.h> // 追加
#include <spi_flash.h> // 追加
#include <zynqpl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
zynq_board_read_rom_ethaddr() に SPI から読むコードを追加します。具体的には、次の #if defined(CONFIG_ZYNQ_QSPI) && defined(CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET)
から #endif
までのコードを追加します。
int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
{
#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET)
if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
ethaddr, 6))
printf("I2C EEPROM MAC address read failed\n");
#endif
#if defined(CONFIG_ZYNQ_QSPI) && \
defined(CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET)
#define CMD_OTPREAD_ARRAY_FAST 0x4b
struct spi_flash *flash;
flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
CONFIG_SF_DEFAULT_CS,
CONFIG_SF_DEFAULT_SPEED,
CONFIG_SF_DEFAULT_MODE);
if (!flash) {
printf("SPI(bus:%u cs:%u) probe failed\n",
CONFIG_SF_DEFAULT_BUS,
CONFIG_SF_DEFAULT_CS);
return 0;
}
/* set the cmd to otp read */
flash->read_cmd = CMD_OTPREAD_ARRAY_FAST;
if (spi_flash_read(flash, CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET, 6, ethaddr))
printf("SPI MAC address read failed\n");
if (flash)
spi_flash_free(flash);
#endif
return 0;
}
include/configs/zynq_zybo_z7.h を修正する
ボード依存の設定用ヘッダファイルに CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET を設定します。
ZYBO-Z7 のリファレンスマニュアル( https://reference.digilentinc.com/reference/programmable-logic/zybo-z7/reference-manual )によれば、
On an Ethernet network each node needs a unique MAC address. To this end, the one-time-programmable (OTP) region of the Quad-SPI flash has been programmed at the factory with a 48-bit globally unique EUI-48/64™ compatible identifier. The OTP address range [0x20;0x25] contains the identifier with the first byte in transmission byte order being at the lowest address.
ということで、CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET に 0x20 を設定します。
/*
* (C) Copyright 2012 Xilinx
* (C) Copyright 2014 Digilent Inc.
*
* Configuration for Zynq Development Board - ZYBO
* See zynq-common.h for Zynq common configs
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_ZYNQ_ZYBO_Z7_H
#define __CONFIG_ZYNQ_ZYBO_Z7_H
#define CONFIG_ZYNQ_I2C0
#define CONFIG_ZYNQ_I2C1
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
#define CONFIG_DISPLAY
#define CONFIG_I2C_EDID
#define CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET 0x20
#include <configs/zynq-common.h>
#endif /* __CONFIG_ZYNQ_ZYBO_Z7_H */
scripts/config_whitelist.txt に CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET を追加する
v2017.11 では Kconfig に定義されていない CONFIG_XXX 定数(XXX は Kconfig の config 文で定義した名前) を使うと、make 時の最後の CFGCHK フェーズでエラーが出てビルドに失敗します。このエラーを回避するために scripts/config_whitelist.txt に CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET を追加しておきます。
:
(中略)
:
CONFIG_ZYNQ_EEPROM_BUS
CONFIG_ZYNQ_GEM_EEPROM_ADDR
CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET
CONFIG_ZYNQ_GEM_SPI_MAC_OFFSET
CONFIG_ZYNQ_HISPD_BROKEN
CONFIG_ZYNQ_I2C0
CONFIG_ZYNQ_I2C1
CONFIG_ZYNQ_SDHCI0
CONFIG_ZYNQ_SDHCI1
CONFIG_ZYNQ_SDHCI_MAX_FREQ
CONFIG_ZYNQ_SDHCI_MIN_FREQ
CONFIG_ZYNQ_SERIAL
CONFIG_eTSEC_MDIO_BUS
U-Boot をビルドする
次のように U-Boot をビルドします。
shell$ export ARCH=arm
shell$ export CROSS_COMPILE=arm-linux-gnueabihf-
shell$ make zynq_zybo_z7_defconfig
shell$ make
U-Boot の実行
ZYBO-Z7 で U-Boot を起動して次のようにメッセージが出れば成功です。
U-Boot SPL 2017.11 (Apr 19 2018 - 07:44:57)
mmc boot
Trying to boot from MMC1
spl_load_image_fat_os: error reading image system.dtb, err - -2
reading u-boot.img
reading u-boot.img
U-Boot 2017.11 (Apr 19 2018 - 07:44:57 +0900)
Model: Zynq ZYBO Z7 Development Board
Board: Xilinx Zynq
I2C: ready
DRAM: ECC disabled 1 GiB
MMC: sdhci@e0100000: 0
SF: Detected s25fl128s_64k with page size 256 Bytes, erase size 64 KiB, total 16 MiB
In: serial@e0001000
Out: serial@e0001000
Err: serial@e0001000
Model: Zynq ZYBO Z7 Development Board
Board: Xilinx Zynq
Net: ZYNQ GEM: e000b000, phyaddr 0, interface rgmii-id
SF: Detected s25fl128s_64k with page size 256 Bytes, erase size 64 KiB, total 16 MiB
Warning: ethernet@e000b000 using MAC address from ROM
eth0: ethernet@e000b000
reading uEnv.txt
510 bytes read in 10 ms (49.8 KiB/s)
Importing environment from mmc ...
MAC アドレスが設定されると 環境変数 ethaddr が設定されます。U-Boot console から 確認してみましょう。
Zynq> env print ethaddr
ethaddr=aa:bb:cc:dd:ee:ff
上の例では MAC アドレスは aa:bb:cc:dd:ee:ff
になっていますが、これはあくまでも参考で、実際はボードに設定されている MAC アドレスが設定されているはずです。ボードに設定されている MAC アドレスは、ボードに貼られているバーコード付きのシールで確認できます。シールは黒いヘッドホンジャックの上あたりにあります。
なお、u-boot で設定した MAC アドレスがどのようにして Linux に渡されるかは次のブログが参考になります。
- 「ZYNQ LinuxのGigabitEtherのMACアドレスはどのように設定されるのか(前編)」@なひたふJTAG日記
- 「ZYNQ LinuxのGigabitEtherのMACアドレスはどのように設定されるのか(後編)」@なひたふJTAG日記
参考
- https://www.denx.de/wiki/U-Boot/WebHome
- https://reference.digilentinc.com/reference/programmable-logic/zybo-z7/reference-manual
- https://github.com/ikwzm/FPGA-SoC-U-Boot-ZYBO-Z7
- 「ZYBO用U-Bootを、ブート時にuEnv.txtを読むようにして、かつBOOT.binから起動できるようにする」 @Qiita
- 「ZYBO用U-Bootでブート時にメニューを表示させる」 @Qiita
- 「ZYNQ LinuxのGigabitEtherのMACアドレスはどのように設定されるのか(前編)」@なひたふJTAG日記
- 「ZYNQ LinuxのGigabitEtherのMACアドレスはどのように設定されるのか(後編)」@なひたふJTAG日記