Skip to main content
Set PLATFORM_TARGET=0 to target BeagleBone Black hardware. This is the default when no TARGET is specified.

Hardware peripherals

The following memory-mapped peripherals are used on BeagleBone Black:
PeripheralAddressDescription
UART00x44E09000TL16C750-compatible serial port
DMTIMER20x48040000General-purpose timer
INTCPS0x48200000ARM interrupt controller
CM_PER0x44E00000Clock Manager (peripheral clocks)
WDT10x44E35000Hardware watchdog timer

Memory layout

The linker script linker/linker_beagle.ld places the OS and both user processes in DDR RAM above 0x82000000:
RegionOriginSize
os_ram0x82000000256K
p1_ram0x8210000064K
p1_stack0x821100004K
p2_ram0x8220000064K
p2_stack0x822100004K
linker/linker_beagle.ld
MEMORY
{
    os_ram   : ORIGIN = 0x82000000, LENGTH = 256K

    p1_ram   : ORIGIN = 0x82100000, LENGTH = 64K
    p1_stack : ORIGIN = 0x82110000, LENGTH = 4K

    p2_ram   : ORIGIN = 0x82200000, LENGTH = 64K
    p2_stack : ORIGIN = 0x82210000, LENGTH = 4K
}
The OS stack bottom begins at __bss_end__ and the stack top is the end of os_ram (0x82040000).

Building

1

Build for BeagleBone Black

Run either of the following commands from the project root:
make TARGET=beagle
or use the convenience alias:
make beagle
The Makefile defaults to TARGET=beagle when no target is specified, so a bare make also works.
2

Locate the output files

After a successful build, two output files are produced inside bin/:
FileDescription
bin/program.elfELF image with debug symbols (for GDB / bootelf)
bin/program.binRaw binary image (for go / fatload)
The BeagleBone build compiles with -O2 and no debug info.

Deploying with U-Boot

U-Boot is the typical first-stage bootloader on BeagleBone Black. Two common methods to load the OS image are shown below.
Copy bin/program.bin to the FAT partition of your SD card, then at the U-Boot prompt:
fatload mmc 0:1 0x82000000 program.bin
go 0x82000000
go jumps directly to the raw binary entry point. Use this when loading program.bin.
The OS entry point is _start, defined in OS/root.s. All load addresses above must match os_ram origin 0x82000000.

Watchdog

BeagleBone Black’s hardware watchdog (WDT1) starts counting down at power-on by default. If the OS does not disable it, the board resets after the watchdog period expires. watchdog_disable() in OS/watchdog.c sends the two-step magic sequence to the Watchdog Write Sequence and Pending Register:
OS/watchdog.c
#define WDT1_BASE   0x44E35000
#define WDT_WSPR    (WDT1_BASE + 0x48)
#define WDT_WWPS    (WDT1_BASE + 0x34)

void watchdog_disable(void) {
    #if PLATFORM_TARGET == 0
        PUT32(WDT_WSPR, 0xAAAA);
        while (GET32(WDT_WWPS) & (1 << 4));
        PUT32(WDT_WSPR, 0x5555);
        while (GET32(WDT_WWPS) & (1 << 4));
    #endif
}
The write-pending bit (bit 4 of WWPS) must clear between each step. This function is a no-op when compiled for QEMU (PLATFORM_TARGET == 1).
Call watchdog_disable() early in your boot sequence. If it is not called, the hardware watchdog will reset the board before the OS finishes initializing.

DMTIMER2 clock and timer

Enabling the clock

DMTIMER2 requires its functional clock to be enabled through the Clock Manager before use. The Makefile passes CM_PER_BASE=0x44E00000, and timer.c derives:
Lib/timer.c
#define CM_PER_TIMER2_CLKCTRL   (CM_PER_BASE + 0x80)
During timer_init(), the clock is enabled first:
Lib/timer.c
// Enable timer2 clock
PUT32(CM_PER_TIMER2_CLKCTRL, 0x2);

Timer configuration

The timer runs at 24 MHz on BeagleBone Black. The load register value is calculated to produce approximately a 2-second overflow period:
Lib/timer.c
#define FREQ_BEAGLE   0xFFFFFFFF - (24000000 * 2)
The full timer_init() sequence for BeagleBone Black:
Lib/timer.c
// Unmask interrupt 68 and give it priority
PUT32(INTC_MIR_CLEAR2, (1 << 4));
PUT32(INTC_ILR68, 0x0);

// Stop timer and clear pending flags
PUT32(TCLR, 0x0);
PUT32(TISR, 0x7);

// Load start value for ~2 seconds at 24 MHz
PUT32(TLDR, FREQ_BEAGLE);
PUT32(TCRR, FREQ_BEAGLE);

// Enable overflow interrupt and auto-reload
PUT32(TIER, 0x2);
PUT32(TCLR, 0x3);
DMTIMER2 register offsets from DMTIMER2_BASE (0x48040000):
MacroOffsetDescription
TISR+0x28Interrupt Status Register
TIER+0x2CInterrupt Enable Register
TCLR+0x38Timer Control Register
TCRR+0x3CTimer Counter Register
TLDR+0x40Timer Load Register

Environment file

The .venv.beagle file defines all platform addresses loaded by the Makefile when TARGET=beagle:
OS/.venv.beagle
PLATFORM_TARGET=0

OS_BASE=0x82000000
OS_STACK=0x82010000

P1_BASE=0x82100000
P1_STACK=0x82110000

P2_BASE=0x82200000
P2_STACK=0x82210000

UART0_BASE=0x44E09000
TIMER_BASE=0x48040000
INTC_BASE=0x48200000
CM_PER_BASE=0x44E00000

Build docs developers (and LLMs) love