Odroid-C2: Difference between revisions

From Alpine Linux
m (→‎Booting: typo)
(Alpine Linux now boot just fine for me :))
Line 1: Line 1:
==Introduction==
==Introduction==


The Odroid-C2 single board computer is not very well supported by Alpine/Linux. However the "Generic ARM (aarch64)" build contains almost everything we need !
The Odroid-C2 single board computer is now well supported by Alpine/Linux and the "Generic ARM (aarch64)" build contains everything we need !


What do we need ?
What about the hardware side ?
* kernel : provided kernel by the Alpine team does not boot
* u-boot : provided u-boot does not autoboot without serial
* system files : everything is okay
 
On the hardware side:
* [https://wiki.odroid.com/odroid-c2/odroid-c2 Odroid-C2]
* [https://wiki.odroid.com/odroid-c2/odroid-c2 Odroid-C2]
* Official PSU or just a micro-SD cable (notes : the barrel plug (inner(positive) diameter 0.8mm and outer(negative) diameter 2.5mm) is recommended, without the J1 jumper)
* Official PSU or just a micro-SD cable (notes : the barrel plug (inner(positive) diameter 0.8mm and outer(negative) diameter 2.5mm) is recommended, without the J1 jumper)
* micro-SD (or eMMC)
* micro-SD (or eMMC)
* USB to TTL ([https://wiki.odroid.com/accessory/development/usb_uart_kit official] or [https://duckduckgo.com/?q=CP2102+ttl&t=h_&iax=images&ia=images CP2102 chipset] or an old rpi)
* Debug only : USB to TTL ([https://wiki.odroid.com/accessory/development/usb_uart_kit official] or [https://duckduckgo.com/?q=CP2102+ttl&t=h_&iax=images&ia=images CP2102 chipset] or an old rpi)


==Prepare the micro-SD card==
With a blank SD card, we can now format-it using the vfat file system.


==Required environement and toolchain==
'''Warning''' : DOUBLE-CHECK /dev/sda1 is indeed your SD card ! Or you'll loose all your data ! You have been warned !
Using GNU/Linux is recommended and this guide and here are the required dependencies, for Debian (as example) :
For this, it's preferable to run <pre>dmesg -We</pre> to check for the name, for example:
<pre>
<pre>
apt install bc bison flex make gcc gcc-aarch64-linux-gnu libssl-dev libncurses-dev git squashfs-tools
[  +0,004725] ums-realtek 1-1:1.0: USB Mass Storage device detected
[  +0,002985] scsi host0: usb-storage 1-1:1.0
[  +1,020024] scsi 0:0:0:0: Direct-Access    Generic- SD/MMC/MS PRO    1.00 PQ: 0 ANSI: 4
[  +0,000591] sd 0:0:0:0: Attached scsi generic sg0 type 0
[  +1,314707] sd 0:0:0:0: [sda] 15269888 512-byte logical blocks: (7.82 GB/7.28 GiB)
[  +0,000352] sd 0:0:0:0: [sda] Write Protect is off
[  +0,000008] sd 0:0:0:0: [sda] Mode Sense: 2f 00 00 00
[  +0,000408] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[  +0,062938]  sda: sda1
[  +0,000238] sd 0:0:0:0: [sda] Attached SCSI removable disk
</pre>
</pre>
We need to set specific environment variables IF you are not using an arm64 machine. Usually, you should be running on a x64 architecture (Intel or AMD I guess), so you would like to cross-compile.
And also verify with <pre>fdisk -l</pre>
<pre>
<pre>
export ARCH=arm64
Disk /dev/sda: 7.28 GiB, 7818182656 bytes, 15269888 sectors
export CROSS_COMPILE=aarch64-linux-gnu
Disk model: SD/MMC/MS PRO 
</pre>
Units: sectors of 1 * 512 = 512 bytes
 
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000


==Build u-boot from source==
Device    Boot Start      End  Sectors  Size Id Type
We need to build uboot from source as the u-boot provided does not autoboot without UART connected.
/dev/sda1        2048 15269887 15267840  7.3G  b W95 FAT32
<pre>
git clone --depth 1 https://source.denx.de/u-boot/u-boot.git -b v2022.01 u-boot-denx.de
cd u-boot-denx.de
export ARCH=arm64 && export CROSS_COMPILE=aarch64-linux-gnu-
make mrproper && make odroid-c2_defconfig
</pre>
</pre>


We used the specific deconfig for the Odroid-C2 but, as mentionned before : we want to autoboot with or without UART connection.
Now we are sure that `/dev/sda` is really our SD card device and we can format our SD card:
You can still access the SPL prompt by pressing the 'Enter' key twice before the two seconds countdown.
<pre>mkfs.vfat /dev/sda1</pre>  
<pre>
sed -i -e 's/.*CONFIG_SD_BOOT.*/CONFIG_SD_BOOT=y/' .config
sed -i -e 's/.*CONFIG_AUTOBOOT_KEYED .*/CONFIG_AUTOBOOT_KEYED=y/' .config
echo "CONFIG_AUTOBOOT_FLUSH_STDIN=y" >> .config
echo "CONFIG_AUTOBOOT_PROMPT="Press quickly 'Enter' twice to stop autoboot: %d\n"" >> .config
echo "# CONFIG_AUTOBOOT_ENCRYPTION is not set" >> .config
echo "CONFIG_AUTOBOOT_DELAY_STR=""" >> .config
echo "CONFIG_AUTOBOOT_STOP_STR="\xd\xd"" >> .config
echo "CONFIG_AUTOBOOT_KEYED_CTRLC=y" >> .config
</pre>


Then, it's time to build :
==Extract Alpine Linux==
Then mount and extract the Alpine Linux archive, for example if you do everything as root:
<pre>
<pre>
export ARCH=arm64 && export CROSS_COMPILE=aarch64-linux-gnu-
# mount /dev/sda1 /mnt/sd
make odroidc2_defconfig
# tar xvzfp /home/user/Downloads/alpine-uboot-3.23.2-aarch64.tar.gz -C /mnt/sd
time make -j$(nproc)
</pre>
</pre>


Amlogic doesn’t provide sources for the firmware and for tools needed to create the bootloader image, so it is necessary to obtain them from the git tree published by the board vendor.
Then, don't forget to flush changes before unmounting the device. Note that it can be a little slow depending of the speed of your device.
 
So, you need to get Amlogic u-boot's fork to assemble the u-boot binary :
<pre>
<pre>
cd ..
sync && umount /mnt/sd
git clone --depth 1 https://github.com/hardkernel/u-boot.git -b odroidc2-v2015.01 u-boot
cd u-boot
</pre>
</pre>


Copy "u-boot.bin" from the previous git repository (source.denx.de) to the amlogic u-boot repository:
==Sign u-boot==
<pre>cp ../u-boot-denx.de/u-boot.bin .</pre>
We don't need to build u-boot from source as the version provided does autoboot properly:
<pre>git clone --depth 1 https://github.com/LibreELEC/amlogic-boot-fip.git</pre>


Then, generate u-boot using amlogic fip tools:
Copy the u-boot.bin from your sd card to the git repository, and sign Amlogic u-boot binaries:
<pre>
<pre>
./fip/fip_create --bl30  ./fip/gxb/bl30.bin --bl301 ./fip/gxb/bl301.bin --bl31 ./fip/gxb/bl31.bin --bl33  u-boot.bin ./fip.bin
cd amlogic-boot-fip/;
./fip/fip_create --dump ./fip.bin
/mnt/sd/u-boot/odroid-c2/u-boot.bin alpine.u-boot.bin;
cat ./fip/gxb/bl2.package ./fip.bin > ./boot_new.bin
./build-fip.sh odroid-c2 alpine.u-boot.bin my-output-dir
./fip/gxb/aml_encrypt_gxb --bootsig --input ./boot_new.bin --output ./u-boot.img
dd if=./u-boot.img of=./u-boot.gxbb bs=512 skip=96
</pre>
</pre>


 
==u-boot flashing==
==Build the latest LTS kernel from source==
Now, make sure your device is un-mouted <pre>umount /dev/sda1</pre>, then use dd to write u-boot.
<pre>
For example, using /dev/sda from previous commands and the signed u-boot (u-boot.bin.sd.bin) from amlogic-boot-fip tool.
git clone --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git -b linux-5.15.y linux-stable
cd linux-stable
export ARCH=arm64 && export CROSS_COMPILE=aarch64-linux-gnu-
make mrproper && make defconfig
</pre>
We need to adapt the default arm64 generated by defconfig. This configuration is required for Alpine/Linux and not enabled by default.
<pre>
<pre>
sed -i -e 's/.*CONFIG_SQUASHFS_XZ.*/CONFIG_SQUASHFS_XZ=y/' .config
dd if=./amlogic-boot-fip/my-output-dir/u-boot.bin.sd.bin of=/dev/sda conv=fsync,notrunc bs=512 skip=1 seek=1
sed -i -e 's/.*CONFIG_UEVENT_HELPER.*/CONFIG_UEVENT_HELPER=y/' .config
dd if=./amlogic-boot-fip/my-output-dir/u-boot.bin.sd.bin of=/dev/sda conv=fsync,notrunc bs=1 count=444
sed -i -e 's/.*CONFIG_BLK_DEV_RAM.*/CONFIG_BLK_DEV_RAM=y/' .config
echo CONFIG_UEVENT_HELPER_PATH=\"/sbin/hotplug\" >> .config
echo CONFIG_BLK_DEV_RAM_COUNT=16 >> .config
echo CONFIG_BLK_DEV_RAM_SIZE=4096 >> .config
</pre>
</pre>


We can also disable unrequired DRM modules. Hence you'll get les modules, vmlinux will be smaller and building kernel will be faster.
Note that you can also disable more modules or functionalities, by removing all DRM drivers or disable sound if you like it. It'll be perfect for a headless machine.
<pre>
sed -i -e 's/CONFIG_DRM_\(.*\)=.*/# CONFIG_DRM_\1 is not set/' .config
sed -i -e 's/.*CONFIG_DRM_LIMA.*/CONFIG_DRM_LIMA=m/' .config
sed -i -e 's/.*CONFIG_DRM_PANFROST.*/CONFIG_DRM_PANFROST=m/' .config
</pre>


If you want to enable DVFS for the s905 amlogic cpu :
==Booting==
<pre>
Connect at least your USB keyboard and your HDMI monitor to check the boot and all should work nicely :)
git apply --ignore-space-change --ignore-whitespace - << EOF
If not, check the Debugging part of this wiki.
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 201596247..027df3756 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -348,7 +348,8 @@ &saradc {
};
 
&scpi_clocks {
-      status = "disabled";
+      /* Works only with new blobs that have limited DVFS table */
+      status = "okay";
};


/* SD */
EOF
</pre>
The, build your kernel, associated modules and the [https://elinux.org/Device_Tree_Reference#What_Is_Device_Tree DTB] (Device Tree Blob) from the source :
<pre>
time make -j$(nproc) Image dtbs modules
</pre>
Create modloop:
<pre>
rm -rf installed-modules && mkdir installed-modules
INSTALL_MOD_PATH=installed-modules make modules_install
find installed-modules -type l -delete
rm -f modloop
mksquashfs installed-modules/lib/ modloop -b 1048576 -comp xz -Xdict-size 100% -all-root
rm -rf installed-modules
</pre>
==Assembly==
Kernel part:
<pre>
DST="/mnt/mmcblk0p1"
gzip -c arch/arm64/boot/Image > ${DST}/vmlinuz
cp .config ${DST}/config
cp modloop ${DST}/modloop
cp System.map ${DST}/System.map
</pre>
Copy dtb:
<pre>
mkdir ${DST}/boot/dtbs
cp arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts ${DST}/boot/dtbs
cp arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dtb ${DST}/boot/dtbs
</pre>
System part:
<pre>
tar -C $DST -xzf alpine-uboot-3.15.4-aarch64.tar.gz ./.alpine-release ./alpine.apkovl.tar.gz ./apks ./boot/initramfs-lts 2>/dev/null
</pre>
==U-Boot scripting==
Create boot.cmd file to /dev/mmcblk0:
<pre>
DST="/mnt/mmcblk0p1"
cat << EoF > boot.cmd
#------------------------------------------------------------------------------------------------------
#
# HELP:
# boot.cmd = source file for humans
# boot.scr = destination file needed for the board
# recompile-me with:
# mkimage -C none -A arm -T script -d boot.cmd boot.scr
#
#------------------------------------------------------------------------------------------------------
# init.
setenv modloop "/boot/modloop"
setenv console "tty1"
setenv condev "console=ttyAML0,115200n8"
setenv verbosity "7"
setenv display_autodetect "true"
# console arguments configuration
setenv consoleargs "modules=loop,squashfs,sd-mod,usb-storage modloop=\${modloop} \${condev} console=\${console} panic=10"
setenv bootargs "\${consoleargs} loglevel=\${verbosity}"
# load files
setenv devtype "mmc"
setenv devnum "0:1"
load \${devtype} \${devnum} \${kernel_addr_r} /boot/vmlinuz
load \${devtype} \${devnum} \${ramdisk_addr_r} /boot/initramfs-lts
load \${devtype} \${devnum} \${fdt_addr_r} /boot/dtbs/meson-gxbb-odroidc2.dtb
# boot
booti \$kernel_addr_r \$ramdisk_addr_r:3200000 \$fdt_addr_r
EoF
</pre>
Then, build this file for u-boot. The mkimage binary is available in the ./tools/ directory from the source.denx.de repository (see "Build u-boot from source" part).
<pre>
mkimage -C none -A arm -T script -d boot.cmd boot.scr
</pre>
Please note that those two files must be placed in the /boot/ directory.
==Booting==


==Debugging==
Connect your USB to TTL converter on your board : I noticed that you don't need to connect all wires, pin 1 don't seems to be is not mandatory at all.
Connect your USB to TTL converter on your board : I noticed that you don't need to connect all wires, pin 1 don't seems to be is not mandatory at all.
<pre>
<pre>
Line 222: Line 92:


All details are available on the odroid wiki : https://wiki.odroid.com/accessory/development/usb_uart_kit
All details are available on the odroid wiki : https://wiki.odroid.com/accessory/development/usb_uart_kit
I use minicom for this:
<pre>
TERM=linux minicom -b 115200 -D /dev/ttyUSB0
</pre>


[[Category:ARM]]
[[Category:ARM]]
[[Category:Hardware]]
[[Category:Hardware]]

Revision as of 10:21, 21 December 2025

Introduction

The Odroid-C2 single board computer is now well supported by Alpine/Linux and the "Generic ARM (aarch64)" build contains everything we need !

What about the hardware side ?

  • Odroid-C2
  • Official PSU or just a micro-SD cable (notes : the barrel plug (inner(positive) diameter 0.8mm and outer(negative) diameter 2.5mm) is recommended, without the J1 jumper)
  • micro-SD (or eMMC)
  • Debug only : USB to TTL (official or CP2102 chipset or an old rpi)

Prepare the micro-SD card

With a blank SD card, we can now format-it using the vfat file system.

Warning : DOUBLE-CHECK /dev/sda1 is indeed your SD card ! Or you'll loose all your data ! You have been warned !

For this, it's preferable to run

dmesg -We

to check for the name, for example:

[  +0,004725] ums-realtek 1-1:1.0: USB Mass Storage device detected
[  +0,002985] scsi host0: usb-storage 1-1:1.0
[  +1,020024] scsi 0:0:0:0: Direct-Access     Generic- SD/MMC/MS PRO    1.00 PQ: 0 ANSI: 4
[  +0,000591] sd 0:0:0:0: Attached scsi generic sg0 type 0
[  +1,314707] sd 0:0:0:0: [sda] 15269888 512-byte logical blocks: (7.82 GB/7.28 GiB)
[  +0,000352] sd 0:0:0:0: [sda] Write Protect is off
[  +0,000008] sd 0:0:0:0: [sda] Mode Sense: 2f 00 00 00
[  +0,000408] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[  +0,062938]  sda: sda1
[  +0,000238] sd 0:0:0:0: [sda] Attached SCSI removable disk

And also verify with

fdisk -l
Disk /dev/sda: 7.28 GiB, 7818182656 bytes, 15269888 sectors
Disk model: SD/MMC/MS PRO   
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device     Boot Start      End  Sectors  Size Id Type
/dev/sda1        2048 15269887 15267840  7.3G  b W95 FAT32

Now we are sure that `/dev/sda` is really our SD card device and we can format our SD card:

mkfs.vfat /dev/sda1

Extract Alpine Linux

Then mount and extract the Alpine Linux archive, for example if you do everything as root:

# mount /dev/sda1 /mnt/sd
# tar xvzfp /home/user/Downloads/alpine-uboot-3.23.2-aarch64.tar.gz -C /mnt/sd

Then, don't forget to flush changes before unmounting the device. Note that it can be a little slow depending of the speed of your device.

sync && umount /mnt/sd

Sign u-boot

We don't need to build u-boot from source as the version provided does autoboot properly:

git clone --depth 1 https://github.com/LibreELEC/amlogic-boot-fip.git

Copy the u-boot.bin from your sd card to the git repository, and sign Amlogic u-boot binaries:

cd amlogic-boot-fip/;
/mnt/sd/u-boot/odroid-c2/u-boot.bin alpine.u-boot.bin;
./build-fip.sh odroid-c2 alpine.u-boot.bin my-output-dir 

u-boot flashing

Now, make sure your device is un-mouted

umount /dev/sda1

, then use dd to write u-boot.

For example, using /dev/sda from previous commands and the signed u-boot (u-boot.bin.sd.bin) from amlogic-boot-fip tool.

dd if=./amlogic-boot-fip/my-output-dir/u-boot.bin.sd.bin of=/dev/sda conv=fsync,notrunc bs=512 skip=1 seek=1
dd if=./amlogic-boot-fip/my-output-dir/u-boot.bin.sd.bin of=/dev/sda conv=fsync,notrunc bs=1 count=444


Booting

Connect at least your USB keyboard and your HDMI monitor to check the boot and all should work nicely :) If not, check the Debugging part of this wiki.


Debugging

Connect your USB to TTL converter on your board : I noticed that you don't need to connect all wires, pin 1 don't seems to be is not mandatory at all.

_____UART____
|Pin 4 - GND|
|Pin 3 - RXD|
|Pin 2 - TXD|
|Pin 1 - VCC|
\___________|

All details are available on the odroid wiki : https://wiki.odroid.com/accessory/development/usb_uart_kit

I use minicom for this:

TERM=linux minicom -b 115200 -D /dev/ttyUSB0