May 26

RTEMS BBB TFTP Boot Workflow

Goal

Establish a fast RTEMS development workflow:

Mac
→ TFTP Server
→ Ethernet
→ BBB U-Boot
→ RAM boot
→ RTEMS

without repeatedly reflashing SD cards.


1. UART Serial Console

Connect the BBB using a USB-to-TTL adapter:

TX
RX
GND

Find the serial device on macOS:

ls /dev/cu.*

Connect using:

screen /dev/cu.usbserial-XXXXX 115200

This is used for:

  • accessing U-Boot
  • viewing RTEMS boot logs

2. Enter U-Boot

Press the space bar during BBB boot to interrupt autoboot and enter:

=>

the U-Boot shell.


3. Configure Ethernet

Mac IP:

192.168.5.1

BBB U-Boot configuration:

setenv ethact ethernet@4a100000
setenv ipaddr 192.168.5.4
setenv serverip 192.168.5.1

Verify connectivity:

ping 192.168.5.1

This confirms BBB ↔ Mac Ethernet communication.


4. Start the TFTP Server on macOS

macOS exports TFTP files from:

/private/tftpboot

Create a working directory:

mkdir ~/tftpboot

Create symbolic links:

sudo ln -sf ~/tftpboot/rtems-app.img \
  /private/tftpboot/rtems-app.img

sudo ln -sf ~/tftpboot/am335x-boneblack.dtb \
  /private/tftpboot/am335x-boneblack.dtb

Start the TFTP server:

sudo launchctl load -F \
/System/Library/LaunchDaemons/tftp.plist

5. Build the RTEMS Application

Generate:

hello_dcan.exe

Convert it into a bootable U-Boot image:

arm-rtems7-objcopy hello_dcan.exe \
  -O binary app.bin

gzip -9 app.bin

mkimage -A arm -O linux -T kernel -a 0x80000000 -e 0x80000000 -n RTEMS -d app.bin.gz rtems-app.img


6. Update the TFTP File

Copy the updated image:

cp rtems-app.img ~/tftpboot/

No need to recreate the symbolic links.


7. Download RTEMS via TFTP on BBB

In U-Boot:

tftpboot 0x80800000 rtems-app.img
tftpboot 0x88000000 am335x-boneblack.dtb

Memory layout:

AddressContent
0x80800000RTEMS image
0x88000000DTB

8. Boot RTEMS

Run:

bootm 0x80800000 - 0x88000000

Boot flow:

U-Boot
→ RAM
→ RTEMS

RTEMS successfully boots from RAM over Ethernet.


Final Fast Development Loop

Modify code
    ↓
./waf
    ↓
Generate hello_dcan.exe
    ↓
mkimage → rtems-app.img
    ↓
Copy to ~/tftpboot
    ↓
BBB tftpboot
    ↓
bootm
    ↓
Test RTEMS

Main Advantage

This workflow enables very fast iteration for:

  • RTEMS CAN driver development
  • BBB BSP work
  • RX/TX testing
  • interrupt debugging
  • embedded bring-up

without constantly removing and reflashing SD cards.


Details during the process

The goal of this work was to establish a professional RTEMS development workflow on the BeagleBone Black (BBB) using U-Boot, Ethernet, and TFTP, instead of repeatedly reflashing SD cards for every RTEMS build iteration. The final objective was to successfully boot RTEMS over the network directly from RAM using U-Boot.

The complete workflow that was achieved is:

Mac host
→ TFTP server
→ Ethernet connection
→ BBB U-Boot
→ TFTP transfer of RTEMS image into RAM
→ TFTP transfer of Device Tree Blob (DTB)
→ bootm execution
→ RTEMS boot successfully

The final successful RTEMS output was:

RTEMS Beagleboard: am335x-based
Hello from RTEMS on BeagleBone Black!

The first stage was establishing UART serial communication with the BBB. A USB-to-TTL FTDI adapter was connected using TX, RX, and GND lines. On macOS, the serial console device appeared as:

/dev/tty.usbserial-A5069RR4

The serial console was accessed using screen:

screen /dev/tty.usbserial-A5069RR4 115200

Initially, boot logs were difficult to analyze because screen only displayed a limited amount of scrollback history. To solve this, screen logging was enabled:

TERM=xterm screen -L /dev/tty.usbserial-A5069RR4 115200

This generated a log file named:

screenlog.0

in the current working directory, which preserved the complete UART output, including U-Boot logs, RTEMS boot messages, Linux kernel logs, and debugging information.

It was also learned that screen should not be exited using Ctrl-C, because this can leave the serial device busy. The proper exit method is:

Ctrl-A
then k
then y

If the serial port became locked or busy, the following commands were used:

lsof /dev/tty.usbserial-A5069RR4

to determine which process owned the serial port, and:

kill -9 <PID>

or:

pkill screen

to terminate stale screen sessions.

The next stage was entering the U-Boot shell. Initially this was difficult because bootdelay was set to zero, which caused autoboot to proceed immediately into Debian Linux before any user interaction could occur. By continuously pressing the space key during reset, U-Boot autoboot was interrupted and the prompt:

=>

was reached successfully.

Once inside U-Boot, environment variables and bootloader configuration concepts were explored. Important commands included:

printenv
setenv
bootm

Key environment variables included:

ipaddr
serverip
ethact
bootdelay
bootcmd

The next major task was bringing up Ethernet networking between the Mac and the BBB. A USB Ethernet adapter on the Mac appeared as interface:

en7

A static IP configuration was created:

Mac:
192.168.5.1

BBB:
192.168.5.4

The BBB side network settings in U-Boot were configured with:

setenv ethact ethernet@4a100000
setenv ipaddr 192.168.5.4
setenv serverip 192.168.5.1

Network connectivity was verified using:

ping 192.168.5.1

One important discovery was that U-Boot sometimes automatically switched to the USB gadget Ethernet interface instead of the physical RJ45 Ethernet interface. This produced messages such as:

using musb-hdrc
RNDIS ready
CDC Ethernet

To ensure the correct Ethernet interface was used, the following environment variable was explicitly set:

setenv ethact ethernet@4a100000

During Ethernet debugging, several real hardware-level networking issues were encountered. The RJ45 LEDs on the BBB were observed carefully. When the LEDs turned off, it indicated loss of physical Ethernet carrier or PHY negotiation failure. Reconnecting the Ethernet cable restored link negotiation and the LEDs became active again.

On the Mac side, network status was monitored using:

ifconfig en7

A working Ethernet link required:

status: active

and:

media: autoselect (100baseTX ...)

When the link failed, the interface showed:

status: inactive
media: autoselect (none)

This demonstrated that the problem was not IP configuration but rather physical Ethernet link establishment.

The next major stage was setting up a TFTP server on macOS. macOS includes a built-in TFTP server daemon (tftpd), but it only exports files from:

/private/tftpboot

A working directory was created:

mkdir ~/tftpboot

and files were connected into the TFTP export directory using symbolic links:

sudo ln -sf ~/tftpboot/test.txt /private/tftpboot/test.txt

The TFTP daemon was started using:

sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist

A self-test was first performed locally on the Mac using the TFTP client:

tftp localhost

This confirmed the TFTP server was functioning correctly.

The first successful BBB-side TFTP transfer was:

tftpboot 0x80800000 test.txt

This demonstrated that U-Boot Ethernet and TFTP communication were working correctly.

A major conceptual realization during this stage was understanding that:

tftpboot does not load files into a filesystem

Instead, it loads raw bytes directly into RAM at a specified memory address. For example:

tftpboot 0x80800000 test.txt

loads the file contents into RAM beginning at address:

0x80800000

This reflects the fundamental bootloader execution model used in embedded systems.

The next stage involved transferring the actual RTEMS image:

tftpboot 0x80800000 rtems-app.img

The image was verified using:

iminfo 0x80800000

which confirmed that the image was a valid U-Boot legacy image with a correct checksum, load address, and entry point.

Initially, booting failed using:

bootm 0x80800000

The boot log showed:

FDT and ATAGS support not compiled in

followed by a reset and automatic fallback to Debian Linux boot.

At this point, it became clear that the RTEMS image required a Device Tree Blob (DTB) for successful boot.

Reference was made to the previously working SD-card boot configuration:

setenv bootdelay 5
uenvcmd=echo loading RTEMS from SD...; run boot
boot=fatload mmc 0 0x80800000 rtems-app.img; fatload mmc 0 0x88000000 am335x-boneblack.dtb; bootm 0x80800000 - 0x88000000

This revealed that the correct boot process required:

RTEMS image at 0x80800000
DTB at 0x88000000
bootm with DTB parameter

The DTB file was then added to the TFTP workflow:

tftpboot 0x88000000 am335x-boneblack.dtb

However, the TFTP server initially returned:

TFTP error: 'Access violation' (2)

This issue was traced to Unix file permissions. The DTB file permissions were:

-rwx------

meaning only the file owner could access the file. Since the macOS TFTP daemon runs as a different system user, it could not read the DTB.

This was fixed using:

chmod 644 ~/tftpboot/am335x-boneblack.dtb

which changed the permissions to:

-rw-r--r--

allowing the TFTP daemon to read the file successfully.

After this, the DTB transfer succeeded.

Finally, the complete successful RTEMS network boot sequence became:

setenv ethact ethernet@4a100000
setenv ipaddr 192.168.5.4
setenv serverip 192.168.5.1

tftpboot 0x80800000 rtems-app.img
tftpboot 0x88000000 am335x-boneblack.dtb
bootm 0x80800000 - 0x88000000

This successfully booted RTEMS directly from RAM over Ethernet.

Through this work, the following concepts and technologies were explored and successfully applied:

UART serial debugging
U-Boot shell interaction
U-Boot environment variables
ARM boot flow
bootm
TFTP networking
Ethernet PHY negotiation
RJ45 link debugging
macOS TFTP server configuration
Unix symbolic links
Unix file permissions and chmod
RAM-based executable loading
Device Tree Blob handling
RTEMS BSP boot workflow
Network-based embedded system bring-up

This workflow now provides a fast iterative RTEMS development environment suitable for future RTEMS CAN driver and BSP development work.