|
| 1 | +# Marvell ESPRESSObin |
| 2 | + |
| 3 | +<img src="espressobin.png" alt="The board" width=800 padding=10> |
| 4 | + |
| 5 | +The [ESPRESSObin][0] is a single-board computer based on the [Marvell Armada |
| 6 | +3720][1] (dual Cortex-A53, AArch64) SoC and the [Marvell 88E6341][2] (Topaz) |
| 7 | +switch, oriented toward networking applications. |
| 8 | + |
| 9 | +The board design is old but the switch offers full Linux support, including |
| 10 | +advanced TSN features for [IEEE 1588-2019][3] (PTP) and [IEEE 802.1AS-2020][4] |
| 11 | +(gPTP). |
| 12 | + |
| 13 | +## Board Variants |
| 14 | + |
| 15 | +The board has gone through several hardware revisions: |
| 16 | + |
| 17 | +| Revision | Storage | Notes | |
| 18 | +|------------|---------------------|--------------------------------| |
| 19 | +| v1, v3, v5 | SPI NOR only | Obsolete; U-Boot always in SPI | |
| 20 | +| v7 | SPI NOR + 4 GB eMMC | Current; SD and eMMC usable | |
| 21 | +| Ultra | SPI NOR + 4 GB eMMC | High-end variant | |
| 22 | + |
| 23 | +On **all revisions** the Boot ROM is hardwired to load U-Boot from SPI NOR |
| 24 | +flash. There is no strap or jumper to make the Boot ROM load directly from an |
| 25 | +SD card. The SD card (or eMMC on v7/Ultra) is used only for the operating |
| 26 | +system. |
| 27 | + |
| 28 | +## Building |
| 29 | + |
| 30 | +The ESPRESSObin uses ext4 for its rootfs partitions rather than the default |
| 31 | +squashfs, because the stock SPI U-Boot lacks squashfs and `blkmap` support. |
| 32 | +The `ext4` configuration snippet enables this. Apply it once after selecting |
| 33 | +the defconfig, then build and compose the SD card image: |
| 34 | + |
| 35 | +```sh |
| 36 | +make O=x-aarch64 aarch64_defconfig |
| 37 | +make O=x-aarch64 apply-ext4 |
| 38 | +make O=x-aarch64 |
| 39 | + |
| 40 | +utils/mkimage.sh -r x-aarch64 marvell-espressobin |
| 41 | +``` |
| 42 | + |
| 43 | +The resulting image (`x-aarch64/images/infix-espressobin-sdcard.img`) contains |
| 44 | +a GPT disk with the standard Infix partition layout, using ext4 instead of the |
| 45 | +read-only squashfs: |
| 46 | + |
| 47 | +| Partition | Label | Contents | |
| 48 | +|-----------|-----------|------------------------------| |
| 49 | +| 1 | aux | RAUC upgrade state (ext4) | |
| 50 | +| 2 | primary | Rootfs slot primary (ext4) | |
| 51 | +| 3 | secondary | Rootfs slot secondary (ext4) | |
| 52 | +| 4 | cfg | Persistent config (ext4) | |
| 53 | +| 5 | var | Runtime data (ext4) | |
| 54 | + |
| 55 | +## Writing to SD Card |
| 56 | + |
| 57 | +```sh |
| 58 | +dd if=infix-espressobin-sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync |
| 59 | +``` |
| 60 | + |
| 61 | +## Upgrading |
| 62 | + |
| 63 | +The build produces `x-aarch64/images/infix-aarch64-ext4.pkg`, a RAUC bundle |
| 64 | +containing the ext4 rootfs. Once the board is running Infix, upgrade over the |
| 65 | +network in the usual way: |
| 66 | + |
| 67 | +``` |
| 68 | +upgrade ftp://192.168.1.1/infix-aarch64-ext4.pkg |
| 69 | +``` |
| 70 | + |
| 71 | +RAUC writes the new rootfs to the inactive slot, updates `BOOT_ORDER` in |
| 72 | +`/mnt/aux/uboot.env`, and the next boot picks it up automatically. |
| 73 | + |
| 74 | +> [!NOTE] |
| 75 | +> Use `infix-aarch64-ext4.pkg`, not the standard `infix-aarch64.pkg`. The |
| 76 | +> standard bundle contains a squashfs rootfs which the stock U-Boot cannot |
| 77 | +> boot. |
| 78 | +
|
| 79 | +## Booting with the Stock SPI U-Boot |
| 80 | + |
| 81 | +The stock Marvell U-Boot has `ext4load` and the standard variables |
| 82 | +(`$kernel_addr`, `$fdt_addr`, `$loadaddr`, `$console`, `$image_name`, |
| 83 | +`$fdt_name`) already set sensibly. Connect to the board's console port, the |
| 84 | +micro USB connector, at 115200 8N1, interrupt autoboot, and paste the commands |
| 85 | +below. |
| 86 | + |
| 87 | +### Environment Variable Reference |
| 88 | + |
| 89 | +These variables are pre-set in the stock U-Boot environment. Restore them |
| 90 | +with these values if they are ever lost or corrupted: |
| 91 | + |
| 92 | +``` |
| 93 | +setenv kernel_addr 0x5000000 |
| 94 | +setenv fdt_addr 0x4f00000 |
| 95 | +setenv loadaddr 0x5000000 |
| 96 | +setenv console 'console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000' |
| 97 | +setenv image_name boot/Image |
| 98 | +setenv extra_params quiet |
| 99 | +``` |
| 100 | + |
| 101 | +`$fdt_name` selects the device tree for your specific board revision: |
| 102 | + |
| 103 | +| Board revision | `fdt_name` value | |
| 104 | +|----------------|-----------------------------------------------------| |
| 105 | +| v3 / v5 | `boot/marvell/armada-3720-espressobin.dtb` | |
| 106 | +| v7 | `boot/marvell/armada-3720-espressobin-v7.dtb` | |
| 107 | +| Ultra | `boot/marvell/armada-3720-espressobin-ultra.dtb` | |
| 108 | +| v3/v5 eMMC | `boot/marvell/armada-3720-espressobin-emmc.dtb` | |
| 109 | +| v7 eMMC | `boot/marvell/armada-3720-espressobin-v7-emmc.dtb` | |
| 110 | + |
| 111 | +``` |
| 112 | +setenv fdt_name boot/marvell/armada-3720-espressobin.dtb # adjust for your board |
| 113 | +``` |
| 114 | + |
| 115 | +### Simple Boot |
| 116 | + |
| 117 | +Fixed boot from the primary slot, useful for initial bring-up: |
| 118 | + |
| 119 | +``` |
| 120 | +setenv bootcmd 'mmc dev 0; \ |
| 121 | + ext4load mmc 0:2 $kernel_addr $image_name; \ |
| 122 | + ext4load mmc 0:2 $fdt_addr $fdt_name; \ |
| 123 | + setenv bootargs $console root=PARTLABEL=primary rw rootwait $extra_params rauc.slot=primary; \ |
| 124 | + booti $kernel_addr - $fdt_addr' |
| 125 | +saveenv |
| 126 | +``` |
| 127 | + |
| 128 | +### Automatic Slot Selection (RAUC Integration) |
| 129 | + |
| 130 | +The CLI `upgrade` command writes to the inactive slot and updates `uboot.env` |
| 131 | +on the `aux` partition with the new boot order. On the next boot U-Boot reads |
| 132 | +`BOOT_ORDER` from the aux partition and selects the appropriate slot. The |
| 133 | +setup below also defines `bootcmd_primary`, `bootcmd_secondary`, and |
| 134 | +`bootcmd_net` for manual use (see [Manual Slot Selection](#manual-slot-selection) |
| 135 | +and [Netbooting](#netbooting)): |
| 136 | + |
| 137 | +``` |
| 138 | +setenv bootcmd_boot \ |
| 139 | + 'mmc dev 0; \ |
| 140 | + ext4load mmc 0:$bootpart $kernel_addr $image_name; \ |
| 141 | + ext4load mmc 0:$bootpart $fdt_addr $fdt_name; \ |
| 142 | + setenv bootargs $console root=PARTLABEL=$bootslot rw rootwait $extra_params rauc.slot=$bootslot; \ |
| 143 | + booti $kernel_addr - $fdt_addr' |
| 144 | +
|
| 145 | +setenv bootcmd_primary 'setenv bootpart 2; setenv bootslot primary; run bootcmd_boot' |
| 146 | +setenv bootcmd_secondary 'setenv bootpart 3; setenv bootslot secondary; run bootcmd_boot' |
| 147 | +
|
| 148 | +setenv bootcmd_net \ |
| 149 | + 'dhcp $kernel_addr $image_name; \ |
| 150 | + tftpboot $fdt_addr $fdt_name; \ |
| 151 | + setenv bootargs $console root=PARTLABEL=primary rw rootwait $extra_params rauc.slot=primary; \ |
| 152 | + booti $kernel_addr - $fdt_addr' |
| 153 | +
|
| 154 | +setenv bootcmd \ |
| 155 | + 'setenv bootpart 2; setenv bootslot primary; setenv auxpart 1; \ |
| 156 | + if ext4load mmc 0:$auxpart $loadaddr /uboot.env; then \ |
| 157 | + env import -b $loadaddr $filesize BOOT_ORDER; \ |
| 158 | + fi; \ |
| 159 | + if test "$BOOT_ORDER" = "secondary primary" || \ |
| 160 | + test "$BOOT_ORDER" = "secondary primary net"; then \ |
| 161 | + setenv bootpart 3; setenv bootslot secondary; \ |
| 162 | + fi; \ |
| 163 | + if test "$BOOT_ORDER" = "net" || \ |
| 164 | + test "$BOOT_ORDER" = "net primary" || \ |
| 165 | + test "$BOOT_ORDER" = "net secondary primary"; then \ |
| 166 | + run bootcmd_net; \ |
| 167 | + fi; \ |
| 168 | + echo ">> Booting $bootslot from mmc 0:$bootpart ..."; \ |
| 169 | + run bootcmd_boot' |
| 170 | +
|
| 171 | +saveenv |
| 172 | +``` |
| 173 | + |
| 174 | +### Manual Slot Selection |
| 175 | + |
| 176 | +To boot a specific slot without waiting for the autoboot countdown, interrupt |
| 177 | +the bootloader (press any key) and run one of the convenience commands defined |
| 178 | +above: |
| 179 | + |
| 180 | +``` |
| 181 | +run bootcmd_primary # boot from primary (partition 2) |
| 182 | +run bootcmd_secondary # boot from secondary (partition 3) |
| 183 | +run bootcmd_net # netboot via DHCP/TFTP |
| 184 | +``` |
| 185 | + |
| 186 | +You can also force a permanent change to which slot boots next by setting |
| 187 | +`BOOT_ORDER` directly from Linux (the change persists across reboots): |
| 188 | + |
| 189 | +```sh |
| 190 | +fw_setenv BOOT_ORDER "secondary primary" # next boot: secondary |
| 191 | +fw_setenv BOOT_ORDER "primary secondary" # next boot: primary (default) |
| 192 | +``` |
| 193 | + |
| 194 | +### Netbooting |
| 195 | + |
| 196 | +The stock U-Boot supports TFTP. This is useful for testing a new kernel or |
| 197 | +device tree without reflashing the SD card. Set up a TFTP server with the |
| 198 | +contents of the Infix `boot/` directory (from the built rootfs at |
| 199 | +`x-aarch64/target/boot/`) and configure the variables: |
| 200 | + |
| 201 | +``` |
| 202 | +setenv serverip 192.168.1.1 # IP of your TFTP server |
| 203 | +setenv ipaddr 192.168.1.100 # board IP (omit if using dhcp) |
| 204 | +saveenv |
| 205 | +``` |
| 206 | + |
| 207 | +Then netboot manually: |
| 208 | + |
| 209 | +``` |
| 210 | +run bootcmd_net |
| 211 | +``` |
| 212 | + |
| 213 | +`bootcmd_net` uses `dhcp` to obtain an IP address and the `$serverip` from |
| 214 | +the DHCP server (option 66), then downloads `$image_name` and `$fdt_name` |
| 215 | +via TFTP. The kernel mounts the primary SD card slot as root, so the SD |
| 216 | +card must still be present. |
| 217 | + |
| 218 | +To make netbooting the default on next boot (e.g. for iterative kernel |
| 219 | +development), set `BOOT_ORDER` from Linux: |
| 220 | + |
| 221 | +```sh |
| 222 | +fw_setenv BOOT_ORDER "net primary secondary" |
| 223 | +``` |
| 224 | + |
| 225 | +This causes `bootcmd` to attempt netboot first; on failure it falls through |
| 226 | +to the primary slot on the SD card. |
| 227 | + |
| 228 | +[0]: https://wiki.espressobin.net/ |
| 229 | +[1]: https://www.marvell.com/content/dam/marvell/en/public-collateral/embedded-processors/marvell-embedded-processors-armada-37xx-hardware-specifications.pdf |
| 230 | +[2]: https://www.marvell.com/content/dam/marvell/en/public-collateral/switching/marvell-link-street-88E6341-product-brief.pdf |
| 231 | +[3]: https://standards.ieee.org/ieee/1588/6825/ |
| 232 | +[4]: https://standards.ieee.org/ieee/802.1AS/7121/ |
0 commit comments