Forum Discussion
Agilex5 HPS running bare-metal code does not access FPGA fabric
- 6 months ago
Hi,
I do not have time to look into it now, and will be out Monday But if you want to use FreeRTOS, see below the instructions on how to make it work there:# install cmake and ninja build tools sudo apt-get install cmake ninja-build # create a top folder sudo rm -rf artifacts && mkdir artifacts && cd artifacts export TOP_FOLDER=`pwd` # add quartus tool to path export QUARTUS_ROOTDIR=~/altera_pro/25.3.1/quartus/ export PATH=$QUARTUS_ROOTDIR/bin:$QUARTUS_ROOTDIR/linux64:$QUARTUS_ROOTDIR/../qsys/bin:$PATH # download toolchain and add to path cd $TOP_FOLDER wget https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-elf.tar.xz tar xf arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-elf.tar.xz rm -f arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-elf.tar.xz export PATH=`pwd`/arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-elf/bin/:$PATH # get freertos cd $TOP_FOLDER git clone https://github.com/Ignitarium-Technology/freertos-socfpga cd freertos-socfpga git checkout -b test v25.4 git submodule update --init --recursive # get sof file cd $TOP_FOLDER wget -O ghrd_a5ed065bb32ae6sr0.sof https://releases.rocketboards.org/2026.01/gsrd/agilex5_dk_a5e065bb32aes1_gsrd.baseline-a55/baseline_a55_hps.sof # build the bridge example cd $TOP_FOLDER/freertos-socfpga/samples/bridge cmake -B build . -G Ninja -DSOF_PATH=$TOP_FOLDER/ghrd_a5ed065bb32ae6sr0.sof cmake --build build --parallel -t sd-imageOnce you build it,you will get the following files:
- JIC QSPI Image: $TOP_FOLDER/freertos-socfpga/samples/bridge/build/sd_atf_binaries/qspi_image.jic
- SD Card Image: $TOP_FOLDER/freertos-socfpga/samples/bridge/build/sd_atf_binaries/sd.img
Write the above images and boot the board. You will see this:
... NOTICE: DDR: Reset type is 'Power-On' NOTICE: IOSSM: Calibration success status check... NOTICE: IOSSM: All EMIF instances within the IO96 have calibrated successfully! NOTICE: DDR: Calibration success NOTICE: DDR: ECC is enabled NOTICE: IOSSM: Memory initialized successfully on IO96B NOTICE: ###DDR:init success### NOTICE: DFI interface selected successfully to SDEMMC NOTICE: SOCFPGA: SDMMC boot NOTICE: BL2: v2.13.0(release): NOTICE: BL2: Built : 20:29:07, Feb 13 2026 NOTICE: BL2: Booting BL31 NOTICE: SOCFPGA: Boot Core = 0 NOTICE: SOCFPGA: CPU ID = 0 NOTICE: SOCFPGA: Setting CLUSTERECTRL_EL1 NOTICE: BL31: v2.13.0(release): NOTICE: BL31: Built : 20:29:07, Feb 13 2026 Starting the bridge sample application Read 217000 bytes from sdmmc drive successfully Bitstream data send successfully bitstream configuration successful Bitstream loaded successfully Starting h2f sample Write data buffer 1 : 1111111111111111 buffer 2 : 2222222222222222 Writing data to memory 0x40000000 Writing data to memory 0x7ffffff8 Reading data from memory 0x40000000 Reading data from memory 0x7ffffff8 Read data buffer 1 : 1111111111111111 buffer 2 : 2222222222222222 Validating the buffers Buffer validation successful HPS2FPGA sample completed successfully Completed h2f sample Starting lwh2f sample SYSID_ID : 1 WRITE DATA write buffer : 11111111 READ DATA read buffer : 11111111 LWHPS2FPGA sample completed successfully Completed lwh2f sample Bridge sample completedI actually prefer using an RTOS versus pure bare-metal, as it offers a lot of convenience. If you do not need the features, you can just put all your code in a single task (like the above example) and ignore them.
Note the above example uses HPS First (the default for the GSRD) and it configures the fabric with the file core.rbf which it builds and puts in the SD card image. It also uses DDR instead of OCRAM.
Regards,
Radu
Hi,
If you only need this for validating the IP in the fabric, and do not want to use the RTOS, I reccomend to use U-Boot applications. They run inside U-Boot, but have separate source code and can be compiled individually. See below a complete example on how to do it:
# top folder
sudo rm -rf artifacts
mkdir artifacts
cd artifacts
export TOP_FOLDER=`pwd`
# compiler toolchain
cd $TOP_FOLDER
wget https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/\
arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
tar xf arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
rm -f arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
export PATH=`pwd`/arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu/bin/:$PATH
export CROSS_COMPILE=aarch64-none-linux-gnu-
# quartus
export QUARTUS_ROOTDIR=~/altera_pro/25.3.1/quartus/
export PATH=$QUARTUS_ROOTDIR/bin:$QUARTUS_ROOTDIR/linux64:$QUARTUS_ROOTDIR/../qsys/bin:$PATH
# sof
cd $TOP_FOLDER
wget -O ghrd.sof https://releases.rocketboards.org/2026.01/gsrd/agilex5_dk_a5e065bb32aes1_gsrd.baseline-a55/baseline_a55_hps.sof
# atf
cd $TOP_FOLDER
rm -rf arm-trusted-firmware
git clone -b QPDS25.3.1_REL_GSRD_PR https://github.com/altera-fpga/arm-trusted-firmware
cd arm-trusted-firmware
make -j 48 PLAT=agilex5 bl31
cd ..
# u-boot
cd $TOP_FOLDER
rm -rf u-boot-socfpga
git clone -b QPDS25.3.1_REL_GSRD_PR https://github.com/altera-fpga/u-boot-socfpga
cd u-boot-socfpga
sed -i 's/u-boot,spl-boot-order.*/u-boot\,spl-boot-order = \&mmc;/g' arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
sed -i '/&nand {/!b;n;c\\tstatus = "disabled";' arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
ln -s ../arm-trusted-firmware/build/agilex5/release/bl31.bin
cat << EOF > config-fragment
CONFIG_BOOTDELAY=2
CONFIG_BOOTFILE="Image"
CONFIG_NAND_BOOT=n
CONFIG_SPL_NAND_SUPPORT=n
CONFIG_CMD_NAND_TRIMFFS=n
CONFIG_CMD_NAND_LOCK_UNLOCK=n
CONFIG_NAND_DENALI_DT=n
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=n
CONFIG_SPL_NAND_FRAMEWORK=n
CONFIG_CMD_NAND=n
CONFIG_MTD_RAW_NAND=n
CONFIG_CMD_UBI=n
CONFIG_CMD_UBIFS=n
CONFIG_MTD_UBI=n
CONFIG_ENV_IS_IN_UBI=n
CONFIG_UBI_SILENCE_MSG=n
CONFIG_UBIFS_SILENCE_MSG=n
CONFIG_DISTRO_DEFAULTS=n
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT_HUSH_PS2="> "
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="mmc rescan;load mmc 0:1 \${loadaddr} ghrd.core.rbf;fpga load 0 \${loadaddr} \${filesize};bridge enable; load mmc 0:1 0x90000000 fpga_test.bin"
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_DOS_PARTITION=y
CONFIG_SPL_DOS_PARTITION=y
CONFIG_CMD_PART=y
CONFIG_SPL_CRC32=y
CONFIG_LZO=y
CONFIG_CMD_DHCP=y
CONFIG_API=y
CONFIG_EXAMPLES=y
CONFIG_SYS_MMC_MAX_DEVICE=1
EOF
# enable u-boot applications
sed -i '/extra-$(CONFIG_PPC) *. += sched/a extra-y += fpga_test' examples/standalone/Makefile
sed -i 's/LOAD_ADDR:.*/LOAD_ADDR:=0x90000000/g' examples/standalone/Makefile
sed -i '/# Disable LTO/a CFLAGS_REMOVE_fpga_test.o := $(LTO_CFLAGS)' examples/standalone/Makefile
# enter source code for the u-boot application
cat << 'EOF' > examples/standalone/fpga_test.c
#include <exports.h>
int fpga_test(int argc, char *const argv[])
{
unsigned long addr;
unsigned long val;
volatile uint32_t *reg;
int i;
app_startup(argv);
if (get_version() != XF_VERSION) {
printf("ABI version mismatch!\n");
return 1;
}
printf("FPGA fabric test\n");
printf("argc = %d\n", argc);
for (i = 0; i < argc; i++)
printf("argv[%d] = \"%s\"\n", i, argv[i]);
if (argc < 2) {
printf("Usage: go <load_addr> <address> [value]\n");
printf(" address: memory/register address to access\n");
printf(" value: if provided, write this value first\n");
return 1;
}
addr = simple_strtoul(argv[1], NULL, 16);
reg = (volatile uint32_t *)addr;
if (argc >= 3) {
val = simple_strtoul(argv[2], NULL, 16);
printf("Writing 0x%08lx to 0x%08lx\n", val, addr);
*reg = (uint32_t)val;
}
printf("Read 0x%08lx => 0x%08x\n", addr, *reg);
return 0;
}
EOF
# build u-boot
make clean && make mrproper
make socfpga_agilex5_defconfig
./scripts/kconfig/merge_config.sh -O . -m .config config-fragment
make -j 64
cd ..
# build hps.jic and core.rbf
cd $TOP_FOLDER
quartus_pfg -c $TOP_FOLDER/ghrd.sof ghrd.jic \
-o device=MT25QU128 \
-o flash_loader=A5ED065BB32AE6SR0 \
-o hps_path=$TOP_FOLDER/u-boot-socfpga/spl/u-boot-spl-dtb.hex \
-o mode=ASX4 \
-o hps=1
# build sd card
cd $TOP_FOLDER
sudo rm -rf sd_card && mkdir sd_card && cd sd_card
wget https://releases.rocketboards.org/release/2020.11/gsrd/tools/make_sdimage_p3.py
sed -i 's/\"\-F 32\",//g' make_sdimage_p3.py
chmod +x make_sdimage_p3.py
mkdir fatfs && cd fatfs
cp $TOP_FOLDER/u-boot-socfpga/u-boot.itb .
cp $TOP_FOLDER/ghrd.core.rbf .
cp $TOP_FOLDER/u-boot-socfpga/examples/standalone/fpga_test.bin .
cd ..
sudo python3 make_sdimage_p3.py -f \
-P fatfs/*,num=1,format=vfat,size=20M \
-s 32M \
-n sdcard.img
cd ..At the end you will have the following files:
- $TOP_FOLDER/ghrd.hps.jic - QSPI image
- $TOP_FOLDER/sd_card/sdcard.img - SD card image
Then write the JIC and SD card image, boot the board and let U-Boot run its 'boot' commad which will load the core.rbf, then load the custom u-boot application at address 0x90000000:
mmc rescan;
load mmc 0:1 ${loadaddr} ghrd.core.rbf;
fpga load 0 ${loadaddr} ${filesize};
bridge enable;
load mmc 0:1 0x90000000 fpga_test.binThen it will drop to U-Boot console, and you can run the sample u-boot application. The code provided above is similar with the devmem2 application, in that it just reads and writes memory. Here is an example usage that reads the Sysid, then reads the OCRAM, writes another value to OCRAM, then reads it back:
SOCFPGA_AGILEX5 # go 0x90000000 0x20010000
## Starting application at 0x90000000 ...
FPGA fabric test
argc = 2
argv[0] = "0x90000000"
argv[1] = "0x20010000"
Read 0x20010000 => 0x00000001
## Application terminated, rc = 0x0
SOCFPGA_AGILEX5 # go 0x90000000 0x40000000
## Starting application at 0x90000000 ...
FPGA fabric test
argc = 2
argv[0] = "0x90000000"
argv[1] = "0x40000000"
Read 0x40000000 => 0x00000000
## Application terminated, rc = 0x0
SOCFPGA_AGILEX5 # go 0x90000000 0x40000000 0x12345678
## Starting application at 0x90000000 ...
FPGA fabric test
argc = 3
argv[0] = "0x90000000"
argv[1] = "0x40000000"
argv[2] = "0x12345678"
Writing 0x12345678 to 0x40000000
Read 0x40000000 => 0x12345678
## Application terminated, rc = 0x0
SOCFPGA_AGILEX5 # go 0x90000000 0x40000000
## Starting application at 0x90000000 ...
FPGA fabric test
argc = 2
argv[0] = "0x90000000"
argv[1] = "0x40000000"
Read 0x40000000 => 0x12345678
## Application terminated, rc = 0x0You would change the U-Boot application according to your needs, then just run 'make' in the U-Boot folder to rebuild the app.
You could write the app back on the SD card, but you could also TFTP over network, to speed up iteration time. Also, you could download the core.rbf over network too, to reduce time. And if you do massive changes in the hardware design, and you need to also change the jic, you could switch to configuring with an rbf with the Quartus Programmer instead.
Thank you,
Radu