APU / Linux

Building a PetaLinux Image for the APU

Our Linux software stack is based on the Yocto project.

In order to build it, we use kas, which fetches and builds bitbake based project. If you already know about Yocto, you don’t have to use kas. Our layer, meta-scobc, can be used as a regular yocto layer.

Setup the Build Environment

The meta-xilinx-tool layer depends on some packages that are not available in Ubuntu 24.04.

To install them, you need to add Ubuntu 22.04 (Jammy) repositories to your system.

$ sudo tee /etc/apt/sources.list.d/jammy.list << 'EOF'
deb http://archive.ubuntu.com/ubuntu jammy main universe
deb http://archive.ubuntu.com/ubuntu jammy-updates main universe
deb http://security.ubuntu.com/ubuntu jammy-security main universe
EOF
$ sudo tee /etc/apt/preferences.d/jammy-pin << 'EOF'
Package: *
Pin: release a=jammy
Pin-Priority: -1

Package: libncurses5 libtinfo5
Pin: release a=jammy
Pin-Priority: 990
EOF

Then, install the required packages.

$ sudo apt update
$ sudo apt install binutils chrpath cpio diffstat file g++ gawk gcc \
                   git git-lfs libncurses5 libtinfo5 lz4 make python3 \
                   rpcsvc-proto zstd

Next, install uv, which is a tool to manage Python virtual environments.

$ curl -LsSf https://astral.sh/uv/install.sh | sh

Clone the Repository

$ git clone https://github.com/spacecubics/meta-scobc
$ cd meta-scobc
meta-scobc uses Git Large File Storage (Git LFS). Make sure you install it.

Install and Enable the Required Python Packages

$ uv sync
$ source .venv/bin/activate

Build the Minimal Image

With kas, it’s easier than bitbake to build the whole system. Just let it do the work with the following command.

$ kas build kas/scobc-v1.yml

build/tmp/deploy/images/scobc-v1/ will contain the generated image files.

$ ls -l build/tmp/deploy/images/scobc-v1/*wic
build/tmp/deploy/images/scobc-v1/sc-image-minimal-scobc-v1-yyyyMMddHHmmss.wic
build/tmp/deploy/images/scobc-v1/sc-image-minimal-scobc-v1.wic@
sc-image-minimal-scobc-v1.wic is a symlink to the latest build.

Build with New XSA File

When you update Versal configuration or add FPGA logic, you must update the XSA file with your own. meta-scobc has a XSA file at the following path:

meta-scobc/meta-scobc-v1/recipes-bsp/hdf/files/sc_obc_v1_versal.xsa

You can also update HDF_URI variable to point to a new XSA file.

Boot from SD Card

Flashing the Image to an SD Card

$ sudo dd if=build/tmp/deploy/images/scobc-v1/sc-image-minimal-scobc-v1.wic \
          of=/dev/sdX \
          bs=4M \
          status=progress \
          conv=fsync

Boot

To boot the Linux from SD card, you have to set the boot MODE [3:0] pins to "SD0 v3.0" or "0011" by setting SW1 of V1 Carrier Board SC-MPN-0062A to "OFF OFF ON ON".

[0.012]****************************************
[0.045]Xilinx Versal Platform Loader and Manager
[0.080]Release 2025.1   Apr  5 2011  -  23:00:00
[0.116]Platform Version: v2.0 PMC: v2.0, PS: v2.0
[0.158]BOOTMODE: 0x3, MULTIBOOT: 0xF0000000
[0.192]****************************************
[0.399]Non Secure Boot
[3.386]PLM Initialization Time
[3.414]***********Boot PDI Load: Started***********
[3.472]Loading PDI from SD0
[3.499]Monolithic/Master Device
[200.133]196.672 ms: PDI initialization time
[200.175]+++Loading Image#: 0x1, Name: lpd, Id: 0x04210002
[200.224]---Loading Partition#: 0x1, Id: 0xC
[254.583] 54.312 ms for Partition#: 0x1, Size: 9968 Bytes
[259.574]---Loading Partition#: 0x2, Id: 0x0
[283.581] 20.059 ms for Partition#: 0x2, Size: 62480 Bytes
PSM Firmware version: 2025.1 [Build: Apr  5 2011 23:00:00 ]
[291.232]+++Loading Image#: 0x2, Name: pl_cfi, Id: 0x18700000
[296.603]---Loading Partition#: 0x3, Id: 0x3
[422.376] 121.824 ms for Partition#: 0x3, Size: 347952 Bytes
[424.864]---Loading Partition#: 0x4, Id: 0x5
[853.890] 425.080 ms for Partition#: 0x4, Size: 440064 Bytes
[856.390]+++Loading Image#: 0x3, Name: fpd, Id: 0x0420C003
[861.518]---Loading Partition#: 0x5, Id: 0x8
[867.101] 1.636 ms for Partition#: 0x5, Size: 4192 Bytes
[870.714]+++Loading Image#: 0x4, Name: apu_ss, Id: 0x1C000000
[875.828]---Loading Partition#: 0x6, Id: 0x0
[891.265] 11.489 ms for Partition#: 0x6, Size: 29168 Bytes
[893.582]---Loading Partition#: 0x7, Id: 0x0
[909.853] 12.323 ms for Partition#: 0x7, Size: 49152 Bytes
[912.170]---Loading Partition#: 0x8, Id: 0x0
[924.692] 8.575 ms for Partition#: 0x8, Size: 18512 Bytes
[926.923]---Loading Partition#: 0x9, Id: 0x0
[1272.021] 341.151 ms for Partition#: 0x9, Size: 1197760 Bytes
[1274.729]***********Boot PDI Load: Done***********
[1279.227]327.418 ms: ROM Time
[1281.960]Total PLM Boot Time
INFO:    BL31: Early console setup
INFO:    Successfully initialized runtime console
NOTICE:  TF-A running on SILICON 0
INFO:    BL31: GET_HANDOFF_PARAMS call success=0
INFO:    BL31: PLM to TF-A handover success 0
NOTICE:  BL31: Secure code at 0x0
NOTICE:  BL31: Non secure code at 0x8000000
NOTICE:  BL31: v2.12.0(debug):v1.1-15211-gdd3512287-dirty
NOTICE:  BL31: Built : 07:04:54, Apr 24 2025
INFO:    GICv3 with legacy support detected.
INFO:    ARM GICv3 driver initialized in EL3
INFO:    Maximum SPI INTID supported: 191
INFO:    BL31: Initializing runtime services
INFO:    BL31: cortex_a72: CPU workaround for erratum 859971 was applied
INFO:    BL31: cortex_a72: CPU workaround for erratum 1319367 was applied
INFO:    BL31: cortex_a72: CPU workaround for CVE 2017_5715 was applied
INFO:    BL31: cortex_a72: CPU workaround for CVE 2018_3639 was applied
INFO:    BL31: cortex_a72: CPU workaround for CVE 2022_23960 was applied
INFO:    BL31: Preparing for EL3 exit to normal world
INFO:    Entry point address = 0x8000000
INFO:    SPSR = 0x3c9


U-Boot 2025.01-g95ca2579c337 (Jul 25 2025 - 11:30:19 +0000)

CPU:   Versal
Silicon: v2
Chip:  v2
Model: Xilinx Versal
DRAM:  2 GiB (effective 4 GiB)
EL Level:	EL2
Multiboot:	0
Core:  39 devices, 21 uclasses, devicetree: board
MMC:   mmc@f1040000: 0, mmc@f1050000: 1
Loading Environment from FAT... *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment

In:    serial@ff000000
Out:   serial@ff000000
Err:   serial@ff000000
Bootmode: SD_MODE
Net:
ZYNQ GEM: ff0d0000, mdio bus ff0d0000, phyaddr 1, interface rgmii-id

Warning: ethernet@ff0d0000 (eth0) using random MAC address - 76:aa:39:97:fb:16
eth0: ethernet@ff0d0000
Hit any key to stop autoboot:  5  4  3  2  1  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
4777 bytes read in 16 ms (291 KiB/s)
## Executing script at 20000000
Trying to load boot images from mmc0
Checking for /image.ub
Checking for /Image
Loading Image at 0x00200000
26661376 bytes read in 1833 ms (13.9 MiB/s)
Checking for /system.dtb
Loading system.dtb at 0x00001000
29153 bytes read in 18 ms (1.5 MiB/s)
Checking for /devicetree/openamp.dtbo
Checking for /ramdisk.cpio.gz.u-boot
Checking for /rootfs.cpio.gz.u-boot
Working FDT set to 1000
## Flattened Device Tree blob at 00001000
   Booting using the fdt blob at 0x001000
Working FDT set to 1000
   Loading Device Tree to 0000000077e91000, end 0000000077e9b1e0 ... OK
Working FDT set to 77e91000
No RNG device

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
[    0.000000] Linux version 6.12.10-xilinx-g297834623cf6 (oe-user@oe-host) (aarch64-amd-linux-gcc (GCC) 13.3.0, GNU ld (GNU Binutils) 2.42.0.20240723) #1 SMP Mon Jul 21 10:14:27 UTC 2025
[    0.000000] KASLR disabled due to lack of seed
[    0.000000] Machine model: Xilinx Versal

...

********************************************************************************************
The PetaLinux source code and images provided/generated are for demonstration purposes only.
Please refer to https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/2741928025/Moving+from+PetaLinux+to+Production+Deployment
for more details.
********************************************************************************************
PetaLinux 2025.1+snapshot-90da27262fec73f66af71115afc7fa654e974815 scobc-v1 ttyAMA0

scobc-v1 login:

The default username is petalinux, and you need to set the password on the first login.

Accessing Peripherals

Build the dev image

To try out more peripherals, you can build the sc-image-dev image.

In kas, you can override the target image by creating a file(ex: override.local.yml).

header:
  version: 19

target:
  - sc-image-dev

Then, build the image with the override file.

$ kas build kas/scobc-v1.yml:override.local.yml
...
$ ls -l build/tmp/deploy/images/scobc-v1/*wic
build/tmp/deploy/images/scobc-v1/sc-image-dev-scobc-v1-yyyyMMddHHmmss.wic
build/tmp/deploy/images/scobc-v1/sc-image-dev-scobc-v1.wic@

Ethernet

You can use ip command to assign an IP address. Once the device is up, you can use any network applications.

# ip addr flush dev end0
# ip addr add 10.30.0.123/24 dev end0
# ip route add default via 10.30.0.1 dev end0
# ip link set dev end0 up

USB

If you have a USB memory, you can mount it like this:

# mount /dev/sda1 /mnt

GPIO

In sc-image-dev, you can use the gpiod tools to control GPIOs.

Set GPIO(PMC_MIO12)

# gpioset -c 1 12=1

Clear GPIO(PMC_MIO12)

# gpioset -c 1 12=0

Read GPIO(PMC_MIO12)

# gpioget -c 1 12
active

It also has libgpiod python3 bindings.

eMMC

If Linux detected the eMMC, you can see the device file:

# ls /dev/mmcblk1
/dev/mmcblk1

If you want to make partitions on the eMMC, you can use fdisk:

# fdisk /dev/mmcblk1

The number of cylinders for this disk is set to 1942528.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): n
Partition type
   p   primary partition (1-4)
   e   extended
p
Partition number (1-4): 1
First sector (16-124321791, default 16):
Using default value 16
Last sector or +size{,K,M,G,T} (16-124321791, default 124321791):
Using default value 124321791

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table
[  159.487171]  mmcblk1: p1

If you want to make a filesystem on the partition, you can use mkfs:

# mkfs.vfat /dev/mmcblk1p1

If the device is formatted with a supported filesystem, you can mount and use it.

# mount /dev/mmcblk1p1 /mnt
# df -h | grep mmcblk1
/dev/mmcblk1p1           59.3G     16.0K     59.3G   0% /mnt
# ls /mnt

microSD card

It’s the same as eMMC. If Linux detectec a SD card, you can see the device file:

# ls /dev/mmcblk0
/dev/mmcblk0
# mount /dev/mmcblk1 /mnt
# ls /mnt

SPI NOR Flash

Under Linux, SPI NOR Flash Memory is a MTD device. If Linux detected the device you can see the device like this:

# ls /dev/mtd0 /dev/mtd0ro /dev/mtdblock0
/dev/mtd0
/dev/mtd0ro
/dev/mtdblock0

/dev/mtd0 is a char device. Thus, you can read from and write to it. /dev/mtdblock0 is a block device. Thus, you can format it and write to it. Both points to the same device.

Write and read data

# echo "SPI NOR Flash 1" > /dev/mtd0
# hexdump -C /dev/mtd0

Erase all sectors

# flash_erase /dev/mtd0 0 0

Switch banks

SC-OBC Module V1 has two SPI NOR Flash banks. You can switch between them by controlling QSPI_MEM_SEL(PMC_MIO50) pin.

# gpioset -c 1 50=0
# echo "SPI NOR Flash 1" > /dev/mtd0
# hexdump -C /dev/mtd0
00000000  53 50 49 20 4e 4f 52 20  46 6c 61 73 68 20 31 0a  |SPI NOR Flash 1.|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
# gpioset -c 1 50=1
# hexdump -C /dev/mtd0
00000000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
# echo "SPI NOR Flash 2" > /dev/mtd0
# hexdump -C /dev/mtd0
00000000  53 50 49 20 4e 4f 52 20  46 6c 61 73 68 20 32 0a  |SPI NOR Flash 2.|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
# gpioset -c 1 50=0
# hexdump -C /dev/mtd0
00000000  53 50 49 20 4e 4f 52 20  46 6c 61 73 68 20 31 0a  |SPI NOR Flash 1.|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*

RTC

# hwclock -s
# cat /sys/class/rtc/rtc0/date
2025-11-17
# cat /sys/class/rtc/rtc0/time
12:34:56