SC-OBC Module V1 Software Manual

1. Overview

1.1. What is SC-OBC Module V1

scobc v1

The SC-OBC Module V1 is a modular onboard computer for space missions that need reliable real-time control and edge processing. It is built around an AMD Versal Adaptive SoC and a Microchip IGLOO2 FPGA, and is designed for harsh environments such as Earth orbit and lunar missions.

On the Versal side, the SC-OBC V1 leverages the device’s heterogeneous architecture, combining dual-core Arm Cortex-A72 application processors and dual-core Arm Cortex-R5F real-time processors with programmable logic, AI Engines, and DSP engines. This enables on-orbit workloads such as object detection, image compression and segmentation, and high-speed signal processing, while keeping flight-critical tasks on the real-time processors with a predictable scheduling model.

On the IGLOO2 side, the SC-OBC V1 uses the device as the board’s safety processor, supervising the main system, providing independent watchdog and fault-management paths, and coordinating safe-mode transitions to improve fault tolerance.

1.2. Evaluation Board

Because SC-OBC Module V1 is a modular OBC, users must at least have some kind of carrier board to power the OBC. In this document we assume that you have V1 Carrier Board SC-MPN-0062A.

1.3. About This Document

This document describes the software for the SC-OBC Module V1 and how it is organized across the device’s heterogeneous compute resources. Because the module includes multiple processor classes, each has its own section and build, boot, and validation guidance.

The first section covers setup and preparation. In addition to the SC-OBC Module V1, you will need a few items to use the OBC. You will also set up your development environment.

The section on the AMD Versal application processors (dual Arm Cortex-A72) explains how to build U-Boot and Linux with the Yocto Project or AMD PetaLinux, and how to boot from an SD card. It outlines the standard Versal boot flow where PLM hands off to TF-A, then U-Boot loads Linux, and it notes that SD boot is a supported sequence.

The section on the AMD Versal real-time processors (dual Arm Cortex-R5F) focuses on Zephyr RTOS for flight-critical workloads that require deterministic behavior and predictable scheduling. It covers building and running Zephyr on the R5F cores in lockstep mode.

2. Setup the Development Environment

2.1. Requirements

  • Ubuntu 24.04 LTS (newer versions may work, but are untested)

  • At least 100 GB of free disk space

2.2. Consoles

Versal has two UART port. UART0 and UART1. Our software by default assign UART0 to APU and UART1 to RPU.

This means that, on SC-OBC Module V1 Development Board, CON6 USB Type 3 carries these UART lines. CON6 is connected to FT4232H, which bundles 4 ports.

This means that on your Linux development PC, you usually see:

  • USB-Serial PORT 1: /dev/ttyUSB0: JTAG

  • USB-Serial PORT 2: /dev/ttyUSB1: Versal UART0 (U-Boot and Linux Console)

  • USB-Serial PORT 3: /dev/ttyUSB2: Versal UART1 (Zephyr Console)

  • USB-Serial PORT 4: /dev/ttyUSB3: IGLOO2 UART

3. APU / Linux

3.1. 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.

3.1.1. 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

3.1.2. 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.

3.1.3. Install and Enable the Required Python Packages

$ uv sync
$ source .venv/bin/activate

3.1.4. 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.

3.1.5. 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.

3.2. Boot from SD Card

3.2.1. 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

3.2.2. 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.

3.3. Accessing Peripherals

3.3.1. 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@

3.3.2. 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

3.3.3. USB

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

# mount /dev/sda1 /mnt

3.3.4. 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.

3.3.5. 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

3.3.6. 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

3.3.7. 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  |................|
*

3.3.8. RTC

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

4. RPU / Zephyr RTOS

In this section we show you how to run Zephyr RTOS on RPU in lock-step mode.

4.1. Setup the Development Environment

This section is mostly the same as the "Getting Started Guide" from the Zephyr official documentation. If you are already familiar with Zephyr development environment, you can safely skip this section.

4.1.1. Install Required Dependencies

$ sudo apt update && sudo apt upgrade
$ sudo apt install --no-install-recommends git cmake ninja-build gperf \
    ccache dfu-util device-tree-compiler wget \
    python3-dev python3-venv python3-pip python3-setuptools python3-tk \
    python3-wheel xz-utils file \
    make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1

4.1.2. Setup a Workspace

Create your working directory and a new virtual environment.

$ mkdir -p ~/myproject && cd ~/myproject
$ python3 -m venv .venv
$ source .venv/bin/activate

4.1.3. Install the West

Once venv is activated, we can install West locally.

$ pip install west

4.1.4. Clone Zephyr Repository

From here, we can use west to do most of the works.

$ west init -m https://github.com/zephyrproject-rtos/zephyr
$ west update
$ west zephyr-export

4.1.5. Install the Python Requirements

$ west packages pip --install

4.1.6. Install the Zephyr SDK

$ west sdk install

4.1.7. Install Udev Rules

Install the udev rules, which allow you to flash most Zephyr boards as a regular user.

sudo cp ~/zephyr-sdk-[VERSION]/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules \
        /etc/udev/rules.d
sudo udevadm control --reload

4.1.8. Install the tio Package

Although there are several tools available for working with a serial console, this document uses tio, a serial device I/O tool.

sudo apt install tio

4.2. Building and Running Zephyr RTOS for SC-OBC Module V1

4.2.1. Building Zephyr RTOS for SC-OBC Module V1

To build Zephyr RTOS for SC-OBC Module V1 is the same as any other board. All you have to do is to specify SC-OBC Module V1 (scobc_v1) with the -b option to west build.

$ cd ~/myproject/zephyr
$ west build -b scobc_v1 samples/hello_world

4.2.2. Running Zephyr RTOS on SC-OBC Module V1

To run Zephyr RTOS, you can use west flash.

For this step, we assume assume that the boot MODE is set to JTAG, which means that SW1 is set to all ON. See SC-OBC Module V1 Product Manual for more details.

Currently, for any AMD Versal based board including SC-OBC Module V1, west flash requires you to have a valid PDI.

$ source /path/to/xilinx/2025.1/Vivado/settings64.sh
$ west flash --pdi /path/to/your.pdi

The command first load the specified PDI file, then load Zephyr RTOS ELF file, and run it.

west flash for Versal-based board uses xsdb, instead of popular OpenOCD, for it’s backend. This means that you must have xsdb in one of your PATH environment variable directories.

4.2.3. Creating a PDI with Zephyr RTOS

You can create a PDI with Zephyr RTOS in it. The PDI, then, can be load from any boot device Versal supports.

To create a PDI, you use bootgen.

bootgen requires a .bif file. A sample .bif file is:

new_bif:
{
    image
    {
        { type = bootimage, file = /path/to/your.pdi }
    }
    image
    {
        name = apu_ss, id = 0x1c000000
        { core = r5-lockstep, file = ~/myproject/zephyr/build/zephyr/zephyr.elf }
    }
}

Save it as, say, mytest.bif, then:

$ source /path/to/xilinx/2025.1/Vivado/settings64.sh
$ bootgen -arch versal -image mytest.bif -w -o boot.bin

bootgen is provided by AMD (Vivado or Vitis). Make sure you have installed it and source the setup script before use.

Generated boot.bin can be placed on a SD card or can be written to one of the SPI NOR flash memories.

To load the PDI 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".

To load the PDI from one of the SPI Flash memories , you have to set the boot MODE [3:0] pins to "QSPI32" or "0010" by setting SW1 of V1 Carrier Board SC-MPN-0062A to "OFF OFF ON OFF".

See Versal documentations for more details.