Architecture

One radio-independent core runs on every radio. Each radio adds a board directory that describes it and drives its chips. The core never includes a board or platform header and never tests a radio define: what differs by radio reaches it at run time through the board descriptor, board_t in hal/board.h.

Layers

 core/        DMR stack, radio core, UI, codeplug, settings, storage, hotspot, host link, CPS, debug link,
              APRS, IP services (TCP, HTTP, mDNS, TFTP, SNMP)
   |  calls only hal/*.h and board.<field>
 hal/         interfaces: board_t, radio, DMR modem, audio, vocoder, display, input, flash, power, stream, netif,
              system, AFSK, broadcast receiver
   |  implemented by
 boards/<b>/  the radio: board_t, pins, key map, how its build differs from the platform's, codec hosting, chip glue
   |  uses
 drivers/     chips shared by several radios: AT1846S, BK4819, FD6818, SKY72310, HR_C6000, HR_C7000, ST7735, ST7789,
              RDA5807M, SPI NOR, key matrix, encoder, NMEA GPS, USB; and the math they share (mic level, battery)
 platform/<p>/ the SoC: start-up, clocks, interrupts, time base, FreeRTOS port glue, and the build defaults its
              boards share (stm32f4, hrc7000)
 third_party/ FreeRTOS, TinyUSB, ST HAL and CMSIS (submodules, permissive licenses)
Layer Rule
core/ Portable C. Tests every radio difference through board (bands, power levels, display geometry and insets, key map, optional hooks that may be NULL). Host tests compile it unchanged
hal/ Headers only: structs of function pointers and the data types between core and board
drivers/ One chip each, no knowledge of the radio it sits in beyond what its init call is given. Also header-only helpers the boards share, such as audio/miclevel (the VOX level) and power/battery (the battery average and charge estimate)
boards/ The only place that knows the radio. Fills in board_t; maps physical keys to logical actions
platform/ The SoC, shared by every radio on it (the STM32F405 radios share platform/stm32f4), and in subdirectories the glue for a chip on that SoC that several radios share (platform/stm32f4/hrc, gps_uart, spi_flash, fsmc_keypad), built for the boards that list it in BOARD_DIRS. Also the build defaults: platform.mk (compiler, part defines, HAL modules), config.mk (feature defaults), common.ld (the memory layout), FreeRTOSConfig.h. A board's files list only how it differs

Besides board_t, every board provides three functions (hal/board.h): board_early_init (pins and clocks before the RTOS), board_init (from the first task) and board_rf_safe (transmitter off with register writes only). The platform calls board_rf_safe first in main(), in its fault handlers and before every software reset or jump out of the application; the crash capture in core/crash calls it too. It must work with interrupts off, without the RTOS and before the clocks are set up (crash-log.md 8).

Tasks

FreeRTOS tasks, created by core/app/app.c (its header comment has the priorities and stack sizes):

Task Owner Does
start / housekeeping core/app Start-up, then the power switch poll, settings saves and codeplug writes (storage jobs)
radio core/radio The radio state machine: requests, status poll, squelch, PTT, time-out, the DMR call stack tick, the data service
dmr board Modem events to the DMR call stack or the hotspot
audio board PCM blocks; the vocoder runs here
input core/input Key scan, gestures; PTT and monitor go straight to the radio core
host core/hostlink The host port: MMDVM hotspot, CPS shim, debug link; in network mode the IP gateway and the radio's own services (core/net, core/snmp)
usb drivers/usb TinyUSB device stack
ui core/ui Frame pacing, drawing, the UI's behavior
gps board NMEA from the GPS module, on radios that have one

Other tasks talk to the radio core through requests (radio_req_*, queued, never waiting) and read a copy of its state (radio_view_t). The UI never calls the RTOS from its behavior code, so the host simulator runs it unchanged.

The core, by directory

Directory Spec Contents
core/radio radio-features, dmr-roaming, airband-and-broadcast The radio state machine (radio_sm.c), its task, scan, beeps, battery, Morse, roaming, air band and broadcast receive
core/dmr/call dmr-voice, dmr-modem The DMR call stack: talk targets, filters, late entry, talker alias
core/dmr/fec, core/dmr/ambe dmr-modem ETSI FEC, AMBE frame FEC and the voice path around the codec
core/dmr/*.c dmr-data, dmr-emergency, sfr, usb-network Data service (SMS, CSBK signaling, ARS, LRRP, confirmed data, SAP 3 compression), emergency, privacy, SFR, IP gateway
core/hotspot mmdvm-protocol, split-duplex MMDVM modem protocol, the hotspot, MMDVM SFR and the split duplex repeater
core/net tcp-services, mdns, tftp The minimal TCP and the radio's services on the USB network link: KISS, HTTP, rigctld, APRS-IS, mDNS, TFTP
core/snmp snmp SNMPv2c agent, the RadioFoundry MIB, notifications
core/aprs aprs AX.25 / AFSK, beacons, messages, KISS TNC, iGate rules
core/usbaudio usb-audio USRP and the jitter buffer (host tested, not in an image yet)
core/hostlink cps-protocol 1 Dispatch of the host port by first byte; the USB network side
core/cps cps-protocol The open-firmware CPS shim
core/codeplug open-firmware-cps, codeplug-native Codeplug reading and editing, the DMR ID database
core/settings, core/storage settings-store The settings ring, the sector journal, the foreign region guard
core/ui ui, docs/ux Drawing, screens, navigation, Find, the services the UI calls
core/input ui 3 Gesture engine (press, long, repeat), injected keys
core/debuglink debuglink The debug protocol and its view sections
core/app Start-up and housekeeping

The UI's seams

The UI asks for data other packages own through core/ui/ui_svc.h. Each call has a weak "not in this build" stub in ui_svc_stub.c; the owning package's strong definition replaces it at link time. A screen whose feature is missing is dimmed and says why. See ui.md section 4.

Build switches

Features that cost flash sit behind CONFIG_ switches (config/features.mk, core/config.h). Code tests them with #if CONFIG_X; whole directories drop out in the Makefile. See Building.

Gotchas

docs/spec/gotchas.md collects the lessons from earlier firmware work, by subsystem: modem timing, hotspot buffering, data retries, storage. Read the section for the subsystem you touch.

View the source of this page