🛠 Déplacer le rootfs sur un SSD NVMe via le port mini-PCIe
Objectives
The mini-PCIe port on the BPI-CM4IO is wired for PCIe Gen2 x1 + USB 2.0: with a mini-PCIe to NVMe adapter (the carrier board does not have an M.2 M-key connector), the vendor wiki measures 351 MB/s read speed and 101 k IOPS at 4k random. Absolute constraint: the A311D ROM and the u-boot BSP do not support booting over PCIe — the bootloader must remain on the SD card (or eMMC), and only the rootfs is moved to the SSD, via setenv rootfsdev in /boot/boot.ini.
Hardware
- BPI-CM4 + BPI-CM4IO, vendor image (procedure documented in the wiki) or Armbian
- Mini-PCIe to NVMe adapter + SSD (e.g., Samsung 970 EVO Plus to reproduce the wiki figures)
- 5 V / 3 A power supply (the SSD adds to the power consumption)
- A system that already boots from microSD
Complete code
# 1) Carrier éteint : visser l'adaptateur + SSD dans le port mini-PCIe, rallumer.
sudo apt install -y nvme-cli rsync
lsblk && sudo nvme list # le SSD apparaît comme /dev/nvme0n1
# 2) Partitionner (p1 boot, p2 racine ext4) et formater
sudo fdisk /dev/nvme0n1
sudo mkfs.ext4 /dev/nvme0n1p2
# 3) Copier le système en cours sur le SSD
sudo mkdir -p /mnt/nvme && sudo mount /dev/nvme0n1p2 /mnt/nvme
sudo rsync -aAXx --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/tmp / /mnt/nvme/
# 4) Forcer la racine sur le SSD (partition boot de la SD)
sudo mount /dev/mmcblk1p1 /mnt
sudo tee -a /mnt/boot.ini >/dev/null <<'EOF'
setenv rootfsdev "/dev/nvme0n1p2"
EOF
# Si la SD et le PCIe se marchent dessus : sortir la SD du mode UHS
sudo sed -i 's/^user_kernel_args=.*/user_kernel_args=pci=pcie_bus_safe disableuhs/' /mnt/env.txt
sudo umount /mnt /mnt/nvme && sudo reboot
# 5) Vérifier et benchmarker
findmnt -no SOURCE / # -> /dev/nvme0n1p2
sudo hdparm -Tt /dev/nvme0n1p2
Expected verification
findmnt / returns /dev/nvme0n1p2; hdparm approaches the 350 MB/s published by the wiki; the PiBenchmarks Storage score jumps (24550 versus 5446 on eMMC). The system must continue to request the SD card (or eMMC) at startup: this is normal, as it is the only boot path for the platform.
Common errors
- Removing the microSD card "since it boots from the SSD": without a bootloader on SD/eMMC, there is no boot at all.
- Looking for an M.2 port: it does not exist on either the module or the carrier board; only the mini-PCIe format is provided.
- Forgetting the
disableuhspatch and accumulating input/output errors on the SD card once the PCIe port is populated. - Leaving an
/etc/fstabwith inconsistent UUIDs after reformatting: checkblkidbefore rebooting. - Insufficient power supply: the SSD peak current added to the A311D causes a 5 V / 2 A charger to drop out.
Other tutorials for this board
- Monter le module BPI-CM4 sur son carrier et réussir le premier boot
- Apprivoiser les LED et la touche ADC du carrier CM4IO
- Mesurer le stockage du BPI-CM4 : eMMC, microSD et le palier NVMe
- Activer I2C, SPI et UART sur le BPI-CM4 : env.txt ou armbianEnv.txt
- Brancher un capteur BME280 sur l'I2C1 du carrier (GPIOX_17/18)
- Exploiter le NPU 5 TOPS de l'A311D pour l'inférence embarquée
Code examples for this board
clignotante.pyPythonbouton-gpio.pyPythoncapteur-i2c.shBashsurveillance-temperature.shBashcapteur-dht11.pyPythonservo-pwm-sysfs.shBash