pebble
  • Tutorials
  • Get the SDK
  • Guides
  • Documentation
  • PebbleOS
  • Examples
  • Index 01
  • Community
  • Blog
  • More
Privacy
Cookies
Publish

PebbleOS

  • Overview
  • Contributing
  • Exposing APIs to the SDK
  • Development
  • Architecture
    • Health Algorithms
    • CRC
    • Kernel
    • Kernel internals
    • Shell
    • Task watchdog
  • Boards
  • Reference
  • Firmware API Reference

Architecture overview

A guided tour of how PebbleOS is put together, deep-linking to the design prose that lives in the source tree. The in-source comments are canonical — these pages summarize and point, they do not duplicate.

Layering

PebbleOS runs on its own kernel API (include/pbl/kernel, implemented under kernel/). The main source layers, as described on the API reference main page:

  • fw/applib — application framework and UI, the API surface exposed to watchapps (SDK export describes how functions get there).

  • fw/services — system services (Bluetooth, filesystem, activity, …).

  • fw/kernel — task management, events, memory.

  • drivers/ — hardware drivers (public interfaces under include/pbl/drivers).

  • subsys/ — OS subsystems shared beyond the firmware tree; currently logging, cron, the Bluetooth backends, CRC, the debug shell and the task watchdog, included via the pbl/logging/, pbl/cron/, pbl/bluetooth/, pbl/crc/, pbl/shell/ and pbl/task_wdt/ header paths.

Alongside these sit fw/shell (launcher/watchface UX flow), fw/process_management (app lifecycle) and fw/comm (phone communication).

Task model

The firmware runs a fixed set of kernel threads, enumerated in fw/kernel/pebble_tasks.h: KernelMain, KernelBackground, Worker, App, the Bluetooth tasks (host, controller, HCI), NewTimers and PULSE. main() (fw/main.c) performs SoC init and spawns KernelMain, which brings up the rest of the system.

Boot and firmware variants

The bootloader is not part of this tree; it selects which firmware image to launch, coordinated through boot bits (see BOOT_BIT_* usage in fw/main.c) and the slot metadata in fw/system/firmware_storage.h.

Normal firmware and PRF (Pebble Recovery Firmware — the minimal fallback image used to reinstall the main firmware) are separate compile-time variants: pbl configure --variant=prf (see build options) applies fw/prj_prf.conf on top of the base config, disabling the JS engine and marking the image as recovery firmware.

Processes and apps

  • App identity — an installed app is referred to by several identifiers (AppInstallId, AppInstallEntry, UUID, PebbleProcessMd); the comment at the top of fw/process_management/app_install_manager.h explains which to use where and which are deprecated.

  • Shell flow — which app launches at startup and what happens when an app exits is a deliberately flat state machine rooted in the launcher and the watchface; see the diagrammed comment at the top of fw/shell/normal/system_app_state_machine.c.

  • Privilege boundary — third-party app and worker code runs unprivileged (processes built into the firmware stay privileged); anything touching OS state crosses into the kernel through a sys_* syscall (declared in fw/syscall/syscall.h) defined with DEFINE_SYSCALL from fw/syscall/syscall_internal.h, which raises privileges on entry and drops them on return unless the caller was already privileged.

Memory layout

fw/linker/pebbleos.ld (“Section concepts!” comment) documents the flash/RAM picture: VMA vs LMA, the kernel data/bss/stack/heap region, and the fixed app region where third-party app code, data and heap live. fw/linker/memory.ld explains how SRAM is carved between kernel, app and worker regions, and fw/linker/regions.ld notes the MPU power-of-two constraints.

Bluetooth

fw/comm/ble/ is the host-side BLE layer and carries substantial design prose:

  • gap_le_connect.c — connection management and the “connection intent” abstraction that virtualizes the link across multiple clients.

  • gap_le_advert.c — round-robin scheduling of multiple advertising jobs onto a controller that only holds one payload at a time (the comment predates the current controllers, but the scheduler it describes is still in use).

  • gap_le_connect_params.c — a primer on connection intervals, slave latency and supervision timeouts, and why the firmware deviates from the spec-recommended parameter-update pause for iOS.

Beneath it sits NimBLE (third_party/nimble), glued in by subsys/bluetooth/. The HCI transport is chosen per SoC (BT_HCI): the NimBLE controller on the nRF52 radio, the SiFli LCPU over IPC on SF32LB52, and a fake controller on QEMU that acknowledges every command so the host runs without a radio. On QEMU the phone link is the emulator’s serial channel, fw/comm/qemu/.

Storage

PFS, the Pebble File System, lives in fw/services/filesystem/. The API and on-flash layout are documented in pfs.h; the wear-leveling strategy (round-robin page allocation tracking the last written page) is described alongside the allocator in pfs.c.

Drivers

  • Accelerometer — include/pbl/drivers/accel.h explains the split between the dumb low-level driver and the accel service that owns buffering, clients and subsampling, so the same service code runs on any accel part.

  • Flash — drivers/flash/README.md documents the two flash APIs: the main one, and a coredump-only path that must work without OS services.

Coredumps

The on-flash coredump image format (header plus chunked records, including per-thread register sets) is documented in fw/kernel/core_dump.c.

Design documents

Longer design documents live as their own pages:

  • Health Algorithms
  • CRC
  • Kernel
  • Kernel internals
  • Shell
  • Task watchdog

Generated from PebbleOS 91af4a22c. This page is maintained in the pebbleos repository: docs/architecture/index.md.

Overview

  • Layering
  • Task model
  • Boot and firmware variants
  • Processes and apps
  • Memory layout
  • Bluetooth
  • Storage
  • Drivers
  • Coredumps
  • Design documents