RTEMS
RTEMS is an embedded, open-source, real-time operating system.
External Documentation
Installation Notes (Ubuntu 18.04)
Build the RSB Tools
The first step is to build a suitable cross-compiler toolchain for the target
CPU architectures. This is done using the rtems-source-builder
tool.
First, install the system packages required to build the cross compiler:
sudo apt-get install build-essential g++ gdb git unzip pax bison flex libpython-dev libncurses5-dev zlib1g-dev
Now pull down the Python-based rtems-source-builder
project and
(optionally) check out the specific revision that was used when writing these
notes:
git clone git://git.rtems.org/rtems-source-builder.git
cd rtems-source-builder/rtems
git checkout f0e34ea
These are some optional, but useful commands you can run at this point:
../source-builder/sb-check
../source-builder/sb-set-builder --list-bsets
Then build the 32-bit ARM toolchain:
$ DOCBOOK_TO_MAN="xmlto man --skip-validation" \
../source-builder/sb-set-builder --without-rtems \
--prefix=/opt/rsb-tools-rtems-6-f0e34ea 6/rtems-arm
and/or the 64-bit ARM toolchain:
$ DOCBOOK_TO_MAN="xmlto man --skip-validation" \
../source-builder/sb-set-builder --without-rtems \
--prefix=/opt/rsb-tools-rtems-6-f0e34ea 6/rtems-aarch64
Build the Desired RTEMS BSPs
First, pull down the rtems
source repository and (optionally) check out
the specific revision that was used when writing these notes:
git clone git://git.rtems.org/rtems.git
cd rtems
git checkout acf4eb2
Now make sure that the rtems-source-builder
tools are in your path:
export PATH="/opt/rsb-tools-rtems-6-f0e34ea/bin:$PATH"
These are some optional, but useful commands you can run at this point:
./waf bsplist
./waf bsplist --rtems-bsps='arm/.*zynq.*'
./waf bsplist --rtems-bsps='aarch64/xilinx_zynqmp.*'
./waf bspdefaults --rtems-bsps='aarch64/xilinx_zynqmp_lp64_zu3eg'
Now create a sample configuration file for the BSP to build. The following is suitable for use with an UltraZed board:
echo -e "[aarch64/xilinx_zynqmp_lp64_zu3eg]" > config.ini
echo -e "BUILD_SAMPLES = False" >> config.ini
echo -e "RTEMS_POSIX_API = True" >> config.ini
echo -e "BSP_RESET_BOARD_AT_EXIT = 0" >> config.ini
The following is suitable for use with a MicroZed or ZedBoard:
echo -e "[arm/xilinx_zynq_zedboard]" > config.ini
echo -e "BUILD_SAMPLES = False" >> config.ini
echo -e "RTEMS_POSIX_API = True" >> config.ini
echo -e "BSP_RESET_BOARD_AT_EXIT = 0" >> config.ini
echo -e "BSP_ARM_A9MPCORE_PERIPHCLK = 333333333" >> config.ini
echo -e "ZYNQ_RAM_LENGTH = 0x40000000" >> config.ini
The following is suitable for use with a Zynq7000 QEMU setup:
echo -e "[arm/xilinx_zynq_a9_qemu]" > config.ini
echo -e "BUILD_SAMPLES = False" >> config.ini
echo -e "RTEMS_POSIX_API = True" >> config.ini
echo -e "BSP_RESET_BOARD_AT_EXIT = 0" >> config.ini
The following is suitable for use with a ZynqMP QEMU setup:
echo -e "[aarch64/xilinx_zynqmp_lp64_qemu]" > config.ini
echo -e "BUILD_SAMPLES = False" >> config.ini
echo -e "RTEMS_POSIX_API = True" >> config.ini
echo -e "BSP_RESET_BOARD_AT_EXIT = 0" >> config.ini
The following is suitable for use with a Raspberry Pi:
echo -e "[arm/raspberrypi]" > config.ini
echo -e "BUILD_SAMPLES = False" >> config.ini
echo -e "RTEMS_POSIX_API = True" >> config.ini
echo -e "BSP_RESET_BOARD_AT_EXIT = 0" >> config.ini
Once you have a config file, you can build an RTEMS BSP like this:
./waf configure --prefix=/opt/rsb-tools-rtems-6-f0e34ea
./waf
./waf install
Note that appropriate compiler/linker flags for each BPS can be found in the
associated .pc
files found here:
/opt/rsb-tools-rtems-6-f0e34ea/lib/pkgconfig/
Note
With the appropriate options, the RTEMS BSPs can alternatively be built from an “out-of-tree” build directory. e.g.
/path/to/rtems/waf --out=$PWD/build --top=/path/to/rtems --no-lock-in-top --no-lock-in-run --prefix=/opt/rsb-tools-rtems-6-f0e34ea configure --rtems-config $PWD/config.ini
/path/to/rtems/waf --out=$PWD/build --top=/path/to/rtems --no-lock-in-top --no-lock-in-run --prefix=/opt/rsb-tools-rtems-6-f0e34ea
/path/to/rtems/waf --out=$PWD/build --top=/path/to/rtems --no-lock-in-top --no-lock-in-run --prefix=/opt/rsb-tools-rtems-6-f0e34ea install
Compile a Hello World Application
Create a file called hello.c
containing:
#include <stdio.h>
void *POSIX_Init()
{
puts("Hello World");
return NULL;
}
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT
#define CONFIGURE_UNLIMITED_OBJECTS
#define CONFIGURE_UNIFIED_WORK_AREAS
#include <rtems/confdefs.h>
Then compile it, using any required flags found in the .pc
file mentioned
above:
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-gcc -c -o hello.o -I/opt/rsb-tools-rtems-6-f0e34ea/arm-rtems6/raspberrypi/lib/include -mcpu=arm1176jzf-s -ffunction-sections -fdata-sections hello.c
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-gcc -o hello.elf -mcpu=arm1176jzf-s -B/opt/rsb-tools-rtems-6-f0e34ea/arm-rtems6/raspberrypi/lib -qrtems -Wl,--gc-sections hello.o
Build the bootgen tool (Zynq/ZynqMP Targets)
First, pull down the bootgen
source repository and (optionally) check out
the specific revision that was used when writing these notes:
git clone https://github.com/Xilinx/bootgen.git
cd bootgen
git checkout xilinx_v2021.1
Now make sure that you have the libssl-dev
package required in order to compile bootgen
:
sudo apt-get install libssl-dev
Now you can build bootgen
:
make
This should generate the bootgen
executable.
Note that later releases of this tool seem to generate warning messages for
the Zynq 7000 target when both an FSBL and bitstream are specified in a
.bif
file.
Building the ARM Trusted Firmware for ZynqMP Targets
First, pull down the source code:
git clone https://github.com/Xilinx/arm-trusted-firmware
cd arm-trusted-firmware
Now build it:
CROSS_COMPILE=aarch64-rtems6- make PLAT=zynqmp RESET_TO_BL31=1
If you run into trouble, you can build with with debug output:
CROSS_COMPILE=aarch64-none-elf- make PLAT=zynqmp RESET_TO_BL31=1 LOG_LEVEL=50 ZYNQMP_ATF_MEM_BASE=0x12000000 ZYNQMP_ATF_MEM_SIZE=0x00100000
This yields a bl31.elf
file that is used with bootgen
.
Building the PMU Firmware for ZynqMP
In Vivado SDK, perform the following steps:
File->New->Application Project
Project name: pmu
Processor: psu_pmu_0
Next, PSU PMU Firmware, Finish
Yields pmu.elf
Build a Boot Image for Zynq Targets
Create a file called hello.bif
containing:
the_ROM_image:
{
[bootloader]fsbl.elf
system_wrapper.bit
hello.elf
}
The fsbl.elf
and system_wrapper.bit
files are generated in Vivado.
Now generate a bootable image for the “Hello World” application:
/path/to/bootgen -arch zynq -image hello.bif -o hello.bin
Build a Boot Image for ZynqMP Targets
Create a file called hello.bif
containing:
the_ROM_image:
{
//[pmufw_image]pmu.elf // pmu fw loaded by boot rom
[bootloader, destination_cpu=a53-0]fsbl.elf
[destination_cpu=pmu]pmu.elf // pmu fw loaded by fsbl
[destination_device=pl]system_wrapper.bit // optional
[destination_cpu=a53-0, exception_level=el-3, trustzone]bl31.elf
[destination_cpu=a53-0, exception_level=el-2]hello.elf
}
The fsbl.elf
, pmu.elf
and system_wrapper.bit
files are generated
in Vivado.
Now generate a bootable image for the “Hello World” application:
/path/to/bootgen -arch zynqmp -image hello.bif -o hello.bin
QEMU Setup
If you want to emulate any of the ARM or AARCH64 targets, you will need to install the QEMU emulator:
sudo apt install qemu-system-arm
Raspberry Pi Setup
The following instructions were tested with a first-generation Raspberry Pi.
First, configure an SD card for booting the Raspberry Pi using the standard process, but choose one of the minimal images. On Ubuntu, this is best done via:
sudo apt-get install rpi-imager
rpi-imager
Choose the Raspberry Pi OS Lite (Legacy/Buster)
image and write it to an
SD card.
The default configuration should have the serial boot console enabled. Connect up something like the FTDI TTL-232R-3V3 cable to your PC. With this cable, the yellow PC-RXD pin connects to the PI-TXD (P1-PIN8), the black PC-GND pin connects to the PI-GND (P1-PIN6), and the orange PC-TXD pin connects to the PI-RXD (P1-PIN10) as shown here.
Now run the following command in a terminal window and power up the Pi with the SD card inserted:
sudo picocom /dev/ttyUSB0 --b 115200 --d 8 --p n --f
You should see kernel boot output. Now type <ctrl-a><ctrl-q> to quit picocom.
Booting RTEMS currently requires an older version of the Pi firmware to be installed on the SD card, so download a zip file with the required firmware from this link. Checking out the whole Git repo takes a very long time.
Now mount the SD card boot partition and move all the files in that boot
directory into a subdirectory (except for config.txt
), as they will be
replaced. Now copy all the files from the boot directory of the zip file you
just downloaded onto the boot partition of the SD card:
mkdir /media/user/boot/backup
mv /media/user/boot/* /media/user/boot/backup
mv /media/user/boot/backup/config.txt /media/user/boot
cp -r firmware-1.20200601/boot/* /media/user/boot
We also need to add the following lines to the end of config.txt
:
dtoverlay=disable-bt
kernel_address=0x200000
kernel=kernel.img
You can test the booting of this configuration once more to make sure you still see serial output.
Building a Raspberry Pi Kernel Image
In order to create a bootable image for use on the Raspberry Pi, you must run the following command:
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-objcopy -Obinary hello.elf kernel.img
Booting a Raspberry Pi Kernel Image
You can now copy the kernel.img
file you created previously onto the boot
partition of the Raspberry Pi SD card (overwriting the existing one) and
power up the board:
cp kernel.img /media/user/boot/
You should text see output appear in the picocom
terminal window that you
set up previously.
Booting a QEMU Image
For the Zynq 7000 QEMU target, run:
qemu-system-arm -serial null -serial mon:stdio -net none -nographic -M xilinx-zynq-a9 -m 256M -kernel hello.elf
Note that stdin does not appear to work for the Zynq 7000 QEMU target, but stdout does.
For the Zynq 7000 QEMU target with ethernet emulation, run:
qemu-system-arm -serial null -serial mon:stdio -net nic,model=cadence_gem,macaddr=0e:b0:ba:5e:ba:11 -net user,hostfwd=tcp:127.0.0.1:2000-:23 -nographic -M xilinx-zynq-a9 -m 256M -kernel hello.elf
For the ZynqMP QEMU target, run:
qemu-system-aarch64 -serial mon:stdio -net none -nographic -machine xlnx-zcu102 -m 4096 -kernel hello.elf
For the ZynqMP QEMU target with ethernet emulation, run:
qemu-system-aarch64 -serial mon:stdio -net nic,model=cadence_gem,macaddr=0e:b0:ba:5e:ba:11 -net user,hostfwd=tcp:127.0.0.1:2000-:23 -nographic -machine xlnx-zcu102 -m 4096 -kernel hello.elf
To exit or issue QEMU commands, use these key sequences:
Ctrl-a h -> Help
Ctrl-a x -> Exit QEMU
Booting a MicroZed BOOT.BIN Image
Now copy the hello.bin
file (generated via bootgen
) into the root
directory of a MicroZed’s SD card, renaming it BOOT.BIN
.
Now put the SD card into the MicroZed and boot it up.
Before turning on power to the development board, connect up the USB UART cable to your workstation and run this command in a terminal window:
picocom /dev/ttyUSB0 --b 115200 --d 8 --p n --f n
Now type <ctrl-a><ctrl-q> to quit picocom.
Booting an UltraZed BOOT.BIN Image
Now copy the hello.bin
file (generated via bootgen
) into the root
directory of an UltaZed’s SD card, renaming it BOOT.BIN
.
Now put the SD card into the UltraZed and boot it up.
Before turning on power to the development board, connect up the USB UART cable to your workstation and run this command in a terminal window:
picocom /dev/ttyUSB1 --b 115200 --d 8 --p n --f n
Now type <ctrl-a><ctrl-q> to quit picocom.
Build libbsd for RTEMS (Optional)
If you want extra features like networking and SD card drivers, you will also
need to build libbsd
.
In order to do this, first pull down the rtems-libbsd
source repository
and (optionally) check out the required branch that works with RTEMS (commit
ac4cf946a28329cc65cbc0c30ec1ed0d6449d7cc
was used when writing these
notes):
git clone git://git.rtems.org/rtems-libbsd.git
cd rtems-libbsd
git checkout 6-freebsd-12
git submodule init
git submodule update rtems_waf
./waf configure --prefix=/opt/rsb-tools-rtems-6-f0e34ea \
--rtems-bsps="aarch64/xilinx_zynqmp_lp64_zu3eg" \
--buildset=buildset/default.ini
./waf
./waf install
Note
With the appropriate command-line options, libbsd can alternatively be built from an “out-of-tree” build directory:
/path/to/libbsd/waf --prefix=/opt/rsb-tools-rtems-6-f0e34ea --rtems-bsps="aarch64/xilinx_zynqmp_lp64_zu3eg" --buildset=buildset/default.ini --out=$PWD/build --top=/path/to/libbsd configure
/path/to/libbsd/waf --prefix=/opt/rsb-tools-rtems-6-f0e34ea --rtems-bsps="aarch64/xilinx_zynqmp_lp64_zu3eg" --buildset=buildset/default.ini --out=$PWD/build --top=/path/to/libbsd
/path/to/libbsd/waf --prefix=/opt/rsb-tools-rtems-6-f0e34ea --rtems-bsps="aarch64/xilinx_zynqmp_lp64_zu3eg" --buildset=buildset/default.ini --out=$PWD/build --top=/path/to/libbsd install
Please note that (unlike the RTEMS out-of-tree build) the
--no-lock-in-top
and --no-lock-in-run
options cannot be specified
because the waf configuration is loaded from the lock files during the
“build” phase.
An Application to Test libbsd
In order to test libbsd
, you can create a file called netcon.c
containing:
#include <stdio.h>
#include <rtems/shell.h>
#include <rtems/bsd/bsd.h>
#include <machine/rtems-bsd-rc-conf.h>
#define BOARD_ETH_IFC "cgem0" // microzed and ultrazed
static const char* rc_conf_text = \
"hostname=\"rtems\"\n" \
"ifconfig_" BOARD_ETH_IFC "=\"inet 172.18.14.227 netmask 255.255.0.0\"\n" \
"\n";
void *POSIX_Init(void * arg)
{
rtems_status_code sc;
sc = rtems_bsd_initialize();
if (sc != RTEMS_SUCCESSFUL)
printf ("rtems_bsd_initialize error: %s (%d)\n",
rtems_status_text (sc), sc);
sc = rtems_bsd_run_rc_conf_script("internal", rc_conf_text, 10, true);
if (sc != RTEMS_SUCCESSFUL)
printf ("rtems_bsd_run_rc_conf_script error: %s (%d)\n",
rtems_status_text (sc), sc);
sc = rtems_task_wake_after(100);
if (sc != RTEMS_SUCCESSFUL)
printf ("rtems_task_wake_after error: %s (%d)\n",
rtems_status_text (sc), sc);
sc = rtems_shell_init(
"net_shell", 60 * 1024, 150, "/dev/console", 0, 1, NULL);
if (sc != RTEMS_SUCCESSFUL)
printf ("rtems_shell_init error: %s (%d)\n",
rtems_status_text (sc), sc);
return NULL;
}
#define RTEMS_BSD_CONFIG_BSP_CONFIG
#define RTEMS_BSD_CONFIG_INIT
#include <machine/rtems-bsd-config.h>
#include <rtems/netcmds-config.h>
#define CONFIGURE_SHELL_USER_COMMANDS \
&rtems_shell_ARP_Command, \
&rtems_shell_HOSTNAME_Command, \
&rtems_shell_PING_Command, \
&rtems_shell_ROUTE_Command, \
&rtems_shell_NETSTAT_Command, \
&rtems_shell_IFCONFIG_Command
#define CONFIGURE_SHELL_COMMANDS_ALL
#define CONFIGURE_SHELL_COMMANDS_INIT
#include <rtems/shellconfig.h>
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT
#define CONFIGURE_UNLIMITED_OBJECTS
#define CONFIGURE_UNIFIED_WORK_AREAS
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 80
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
#include <rtems/confdefs.h>
And then compile it as before, but link in libbsd
and libm
:
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-gcc -c -o netcon.o -I/opt/rsb-tools-rtems-6-f0e34ea/arm-rtems6/raspberrypi/lib/include -mcpu=arm1176jzf-s -ffunction-sections -fdata-sections netcon.c
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-gcc -o netcon.elf -mcpu=arm1176jzf-s -B/opt/rsb-tools-rtems-6-f0e34ea/arm-rtems6/raspberrypi/lib -qrtems -Wl,--gc-sections netcon.o -lbsd -lm
Note that ethernet does not currently work for the Raspberry Pi, but does for the MicroZed and UltraZed.
Tools for Examining Executables
Print the size of an executable:
/opt/rsb-tools-rtems-6-f0e34ea/bin/aarch64-rtems6-size hello.elf
To see the memory layout of an executable:
/opt/rsb-tools-rtems-6-f0e34ea/bin/aarch64-rtems6-readelf -S hello.elf
Building U-Boot (Optional)
If you have a need for a more sophisticated bootloader, you can set up U-Boot.
In order to do this, first pull down the u-boot
source repository and
(optionally) check out the commit that was used when writing these notes):
git clone https://github.com/Xilinx/u-boot-xlnx.git
cd u-boot-xlnx
git checkout xilinx-v2022.2
The (forked) URL/commit above is applicable to the Xilinx Zynq and ZynqMP boards. For other targets (like the Raspberry Pi), the master repository should be used:
git clone https://github.com/u-boot/u-boot.git
cd u-boot
You can see the available boards and device trees in places like these:
ls configs/xilinx_zynq_virt_defconfig
ls arch/arm/dts/zynq-microzed.dts
ls configs/rpi_defconfig
ls arch/arm/dts/bcm2835-rpi-b.dts
To configure for the MicroZed board, issue these commands:
export CROSS_COMPILE=/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-
export DEVICE_TREE=zynq-microzed
make xilinx_zynq_virt_defconfig
For the UltraZed, issue these commands instead:
export CROSS_COMPILE=/opt/rsb-tools-rtems-6-f0e34ea/bin/aarch64-rtems6-
export DEVICE_TREE=avnet-ultrazedev-cc-v1.0-ultrazedev-som-v1.0
make avnet_ultrazedev_cc_v1_0_ultrazedev_som_v1_0_defconfig
You will also need to follow these steps for the UltraZed:
Run
make menuconfig
Select
Device Drivers
Then select
SOC specific Drivers
Then select
Enable SOC Device ID driver for Xilinx ZynqMP
Save and exit
For the UltraZed ethernet to work, you must also change reg = <0>
to
reg = <9>
in arch/arm/dts/avnet-ultrazedev-som-v1.0.dtsi
.
If you want to use TFTP boot with a non-privileged server port, you will need
to remove this #ifdef
line (and the corresponding #endif
line) in
net/tftp.c
:
#ifdef CONFIG_TFTP_PORT
To kick off the build do:
make -j
This build process should result in a u-boot.elf
in the top-level
directory. For Zynq/ZynqMP targets a BOOT.BIN
file can be created using
bootgen
following the previous instructions and replacing hello.elf
with u-boot.elf
. The resulting BOOT.BIN should be able to boot on the
target board. For the the Raspberry Pi, the u-boot.elf
file can be used
to create a kernel.img
in the same way that was done for hello.elf
.
If you want to clean everything up to build for another board, run:
make distclean
Basic U-Boot Configuration for the MicroZed (Optional)
You can add a boot.scr
file to the root SD card partition to customize
what u-boot does when it boots up. As an example, create a text file named
boot.txt
containing the following text:
fatload mmc 0 0x104000 hello.img
echo "Booting hello.img from SD card..."
bootm 0x104000
These commands instruct u-boot to look for a file named hello.img
on the
SD card, load it into memory at the specified address, and then run it.
Now we need to convert this text file to an .scr
script image:
u-boot-xlnx/tools/mkimage -A arm -T script -C none -n "Boot Script" -d boot.txt boot.scr
The resulting boot.scr
file can then be copied into the root directory of
the SD card.
Now we need to convert our hello.elf
file into a binary image:
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-objcopy -R -S -Obinary hello.elf hello.binary
Now we need to make a u-boot
image from the binary image:
u-boot-xlnx/tools/mkimage -A arm -O rtems -T kernel -C none -a 0x104000 -e 0x104000 -n "Hello World" -d hello.binary hello.img
Now copy the resulting hello.img
output file onto the root partition of
the SD card and boot up the board.
Basic U-Boot Configuration for the UltraZed (Optional)
You can add a boot.scr
file to the root SD card partition to customize
what u-boot does when it boots up. As an example, create a text file named
boot.txt
containing the following text:
fatload mmc 1 0x10000000 hello.img
echo "Booting hello.img from SD card..."
bootm 0x10000000
These commands instruct u-boot to look for a file named hello.img
on the
SD card, load it into memory at the specified address, and then run it.
Now we need to convert this text file to an .scr
script image:
u-boot-xlnx/tools/mkimage -A arm64 -T script -C none -n "Boot Script" -d boot.txt boot.scr
The resulting boot.scr
file can then be copied into the root directory of
the SD card.
Now we need to convert our hello.elf
file into a binary image:
/opt/rsb-tools-rtems-6-f0e34ea/bin/aarch64-rtems6-objcopy -R -S -Obinary hello.elf hello.binary
Now we need to make a u-boot
image from the binary image:
u-boot-xlnx/tools/mkimage -A arm64 -O rtems -T kernel -C none -a 0x10000000 -e 0x10000000 -n "Hello World" -d hello.binary hello.img
Now copy the resulting hello.img
output file onto the root partition of
the SD card and boot up the board.
TFTP Boot on the MicroZed (Optional)
If we want to boot the MicroZed via TFTP, we can update the boot.txt
as
follows, re-generate boot.scr
and copy that to the SD card as before:
env set tftpdstp 54321
env set serverip 192.168.1.222
env set ipaddr 192.168.1.111
env set netmask 255.255.0.0
echo "Starting application from tftp..."
ping 192.168.1.222
tftpboot 0x104000 hello.img
bootm 0x104000
Just replace the network addresses/netmask with something applicable to your setup.
Before powering up the target board, run the following command on your
development host machine from the directory containing hello.img
:
/opt/rsb-tools-rtems-6-f0e34ea/bin/rtems-tftp-server -P 54321 -v --trace-packets
If you want to change the name of the image being loaded without updating
boot.scr
on the target system, you can do something like this:
/opt/rsb-tools-rtems-6-f0e34ea/bin/rtems-tftp-server -P 54321 -F net_shell.img
TFTP Boot on the UltraZed (Optional)
If we want to boot the UltraZed via TFTP, we can update the boot.txt
as
follows, re-generate boot.scr
and copy that to the SD card as before:
env set tftpdstp 54321
env set serverip 192.168.1.222
env set ipaddr 192.168.1.111
env set netmask 255.255.0.0
echo "Starting application from tftp..."
ping 192.168.1.222
tftpboot 0x10000000 hello.img
bootm 0x10000000
Just replace the network addresses/netmask with something applicable to your setup.
Before powering up the target board, run the following command on your
development host machine from the directory containing hello.img
:
/opt/rsb-tools-rtems-6-f0e34ea/bin/rtems-tftp-server -P 54321 -v --trace-packets
If you want to change the name of the image being loaded without updating
boot.scr
on the target system, you can do something like this:
/opt/rsb-tools-rtems-6-f0e34ea/bin/rtems-tftp-server -P 54321 -F net_shell.img
Alternative U-Boot Boot Commands
If you want to boot a “binary” file (like hello.binary
mentioned
previously) without having to convert it to a u-boot
image file
(i.e. hello.img
), you can do this by using go
to execute the program
instead of bootm
:
tftpboot 0x10000000 hello.binary
go 0x10000000
You can also go a step further and directly boot the .elf
file. The
caveat here is that you must load the .elf
file into a different,
non-overlapping memory area rather than the program start address that we
have been using up until now:
tftpboot 0x20000000 hello.elf
bootelf 0x20000000
This approach applies to both the SD card and TFTP boot methods.
Using a Remote Debugger with the MicroZed/UltraZed
If you want to do remote debugging over ethernet, you need to set up
libdebugger
in your application. Start with the libbsd
test
application shown previously and add the following #include
directives:
#include <rtems/rtems-debugger.h>
#include <rtems/rtems-debugger-remote-tcp.h>
then add the following static declaration:
static rtems_printer printer;
Now add the following lines before you initialize the shell in
POSIX_Init()
:
printf ("registering rtems debugger tcp remote...\n\n");
sc = rtems_debugger_register_tcp_remote();
if (sc != RTEMS_SUCCESSFUL)
printf ("error in rtems_debugger_register_tcp_remote()\n");
printf ("starting rtems debugger...\n\n");
sc = rtems_debugger_start("tcp", "1222", 3, 1, &printer);
if (sc != RTEMS_SUCCESSFUL)
printf ("error in rtems_debugger_start()\n");
rtems_debugger_break(1); // Wait here until debugger connects
You will also need to link the application with -ldebugger
.
Now when you boot up the target system with this application, it should wait for a remote debugger connection before starting the shell. You should be able to connect to the target system by executing these commands on your host development system:
/opt/rsb-tools-rtems-6-f0e34ea/bin/aarch64-rtems6-gdb dbg_test.elf
(gdb) target remote 192.168.1.111:1222
(gdb) up
(gdb) up
(gdb) up
(gdb) up
(gdb) up
(gdb) up
(gdb) list
(gdb) quit
After quitting the remote debugger, execution should continue on the target system.
Debugging a QEMU Image
For the Zynq 7000 QEMU target, run:
qemu-system-arm -serial null -serial mon:stdio -net none -nographic -M xilinx-zynq-a9 -m 256M -kernel hello.elf -S -s
This will freeze the CPU on application startup and wait for a debugger to
connect on TCP port 1234
.
Then you can run the following commands on your host development system to connect to the target system:
/opt/rsb-tools-rtems-6-f0e34ea/bin/arm-rtems6-gdb hello.elf
(gdb) target remote localhost:1234
The process is similar for the ZynqMP QEMU target.