API summary
Every core_ / hal_ / ll_ function in the SDK, in one place — grouped by subsystem in the same order as the guides and the implementation status. Switch the Core / HAL / LL toggle at the top of the sidebar to view a layer. It’s generated from the same manifests the guides use, so it stays in sync with the headers automatically.
173 Core functions · across 13 subsystems
Systemguide →
| Function | Access | Description |
|---|---|---|
core_delay_ms(uint32_t ms) | Tier 2 | Blocking delay in milliseconds. |
core_delay_us(uint32_t us) | Tier 2 | Blocking delay in microseconds. For delays > 1 ms prefer `delay_ms` — it won't starve the rest of the system as long. |
core_millis(void) | Tier 2 | Milliseconds since boot (wraps at ~49 days). |
core_timeout(uint32_t start, uint32_t ms) | Tier 2 | Check if a timeout has elapsed. start: value returned by core_millis() at the beginning ms: timeout duration in milliseconds Returns 1 if expired, 0 otherwise. |
core_cycle_init(void) | Tier 1 | Enable the DWT cycle counter. Idempotent; call once at startup. |
core_delay_cycles(uint32_t cycles) | Tier 1 | Busy-wait `cycles` CPU cycles (≈ ±a few cycles of loop overhead). |
core_delay_ns(uint32_t ns) | Tier 1 | Busy-wait `ns` nanoseconds (rounds to whole CPU cycles). |
core_watchdog_start(uint32_t timeout_ms) | Tier 2 | Start the independent watchdog with a timeout in milliseconds. Selects the best prescaler/reload combination automatically. Common values: 1000, 2000, 5000, 10000 (max ~28000). WARNING: Once started, the IWDG cannot be stopped. |
core_watchdog_feed(void) | Tier 2 | Feed the watchdog. Must be called before the timeout expires. |
core_watchdog_caused_reset(void) | Tier 1 | Check if the last reset was caused by the watchdog. On ROM_DFU builds, core_init() reads and clears the hardware flag early (for the strike counter), stashing the cause in reserved SRAM — so prefer that when it's valid; otherwise fall back to the raw RCC_CSR flag. |
core_watchdog_clear_flags(void) | Tier 1 | Clear all reset flags (call after checking cause). |
core_watchdog_debug_freeze(void) | Tier 1 | Freeze the IWDG while the core is halted under a debugger, so a breakpoint doesn't let the watchdog reset the chip out from under an SWD session. Firmware-side so it holds for any probe/toolchain (rev b exposes SWD on L4). |
Onboard LEDguide →
| Function | Access | Description |
|---|---|---|
core_led_on(void) | Tier 2 | Turn the onboard LED on. Simplest possible light control — useful alongside blink/heartbeat when the user wants explicit on/off state rather than a timed pattern. |
core_led_off(void) | Tier 2 | Turn the onboard LED off. |
core_led_toggle(void) | Tier 2 | Flip the onboard LED's current state. Non-blocking — no delay. Good for driving the LED from an event handler that fires at a rate you've already chosen (e.g., a pad-edge ISR on a button). |
core_led_blink(int n, int on_ms, int off_ms) | Tier 2 | Blink the LED n times. Each cycle turns the LED on for on_ms milliseconds and off for off_ms milliseconds. Blocking — returns after the last off period. |
core_led_heartbeat(int period_ms, int on_ms) | Tier 2 | Start a free-running, asymmetric heartbeat on the onboard LED. Set it up once (e.g. at startup) and it runs on its own — the LED turns on for on_ms, off for the rest of period_ms, repeating forever. Serviced from the 1 ms SysTick interrupt, so it does NOT block your main loop the way a toggle-and-delay would: the loop stays free for tile reads and logic. Call again at any time to change the rhythm; pass period_ms = 0 to stop the heartbeat (the LED is left off). on_ms is clamped to period_ms. Examples: heartbeat(1000, 100) — a 1 Hz "blip": 100 ms on, 900 ms off. heartbeat(500, 250) — a steady 1 Hz, 50%-duty pulse. Defined in core_led.c (not header-only) because it owns persistent state shared with the SysTick handler. |
core_led_init(void) | Tier 1 | Enable the GPIO clock and configure the LED pin as a push-pull output. Call once after core_init(). The LED starts in the off state. |
core_led_sos(void) | Tier 1 | Blink the SOS pattern (3 short, 3 long, 3 short) in an infinite loop. Use for unrecoverable errors. This function never returns. |
GPIOguide →
| Function | Access | Description |
|---|---|---|
core_pad_write(uint8_t pad, int state) | Tier 2 | Set a pad high (ON) or low (OFF). |
core_pad_read(uint8_t pad) | Tier 2 | Read a pad. Returns 0 or 1. |
core_pad_toggle(uint8_t pad) | Tier 2 | Toggle a pad output. |
core_pad_output(uint8_t pad) | Tier 1 | Configure a pad as push-pull output (default). |
core_pad_output_od(uint8_t pad, uint32_t pull) | Tier 1 | Configure a pad as open-drain output with optional pull resistor. Use PULL_UP for a wired-AND / I2C-style bus, PULL_NONE for external pull. |
core_pad_input(uint8_t pad, uint32_t pull) | Tier 1 | Configure a pad as input with pull resistor. |
core_pad_resolve(uint8_t pad) | Tier 1 | Resolve a pad to a fast handle once, outside the hot loop. |
core_pad_fast_set(core_pad_fast_t h) | Tier 1 | Drive the resolved pad high — single BSRR write. |
core_pad_fast_clear(core_pad_fast_t h) | Tier 1 | Drive the resolved pad low — single BSRR write. |
core_pad_fast_write(core_pad_fast_t h, int state) | Tier 1 | Drive the resolved pad to `state` (0/1) — single BSRR write. |
core_pad_fast_read(core_pad_fast_t h) | Tier 1 | Read the resolved pad — single IDR load. Returns 0 or 1. |
core_pad_bulk_write(GPIO_TypeDef * port, uint32_t set_mask, uint32_t clear_mask) | Tier 1 | Bulk update many pins on ONE port in a single atomic BSRR write: pins in `set_mask` go high, pins in `clear_mask` go low (set wins on overlap, per BSRR). Build the masks from the generated PAD_n_MASK defines. Useful for synchronized buses / LED matrices without per-pad jitter. |
core_pad_analog(uint8_t pad) | Tier 1 | Configure a pad as analog (for ADC, DAC, comparator). |
core_pad_speed(uint8_t pad, uint32_t speed) | Tier 1 | Set the output speed (slew rate) of a pad. Use SPEED_LOW / SPEED_MED / SPEED_HIGH / SPEED_VHIGH. Only affects outputs — input pads ignore this setting. |
core_pad_on_change(uint8_t pad, uint32_t edge, hal_callback_t cb, void * ctx) | Tier 1 | Register an edge-triggered callback on a pad. The pad is automatically configured as input with a sensible pull resistor based on edge direction: rising → pull-down (idle low) falling → pull-up (idle high) both → no pull (external bias expected) |
core_pad_on_change_stop(uint8_t pad) | Tier 1 | Stop the interrupt on a pad. |
UARTguide →
| Function | Access | Description |
|---|---|---|
core_serial_print_bus(uint8_t bus, const char * str) | Tier 2 | Write a null-terminated string to `bus` (blocking). Returns 0 on success or -1 on undeclared bus. The most-common DSL pattern — "drop a debug line on UART2" — is one line: serial.print(2, "ready\\n"); |
core_serial_putc_bus(uint8_t bus, uint8_t byte) | Tier 2 | Write a single byte to `bus` (blocking). Returns 0 on success or -1 on undeclared bus. |
core_serial_init(hal_uart_t * h, USART_TypeDef * instance, const hal_uart_config_t * cfg) | Tier 1 | Initialize a UART instance. Clock is auto-resolved from PCLK1_HZ (core_config.h). |
core_serial_init_clk(hal_uart_t * h, USART_TypeDef * instance, uint32_t pclk_hz, const hal_uart_config_t * cfg) | Tier 1 | |
core_serial_write(hal_uart_t * h, const uint8_t * data, uint32_t len) | Tier 1 | Transmit a buffer (blocking). |
core_serial_print(hal_uart_t * h, const char * str) | Tier 1 | Transmit a null-terminated string (blocking). |
core_serial_putc(hal_uart_t * h, uint8_t byte) | Tier 1 | Transmit a single byte (blocking). |
core_serial_available(hal_uart_t * h) | Tier 1 | Number of bytes available in the RX buffer. |
core_serial_getc(hal_uart_t * h) | Tier 1 | Receive a single byte (blocking -- waits for data). |
core_serial_read(hal_uart_t * h, uint8_t * buf, uint16_t max_len) | Tier 1 | Read available bytes from the RX ring buffer (non-blocking). Returns number of bytes read. |
I2Cguide →
| Function | Access | Description |
|---|---|---|
core_i2c_write_byte_bus(uint8_t bus, uint8_t addr, uint16_t reg, uint8_t value) | Tier 2 | Write a single byte to a register on a device on `bus`. Returns I2C_OK on success, I2C_NACK / I2C_ERROR on bus failure, or I2C_ERROR if `bus` isn't declared in config.json. |
core_i2c_read_byte_bus(uint8_t bus, uint8_t addr, uint16_t reg) | Tier 2 | Read a single byte from a register on a device on `bus`. Returns the byte value (0..255) on success, or -1 on any error (bus undeclared, NACK, timeout). The signed return lets DSL programs branch on `< 0` without an out-pointer. |
core_i2c_probe_bus(uint8_t bus, uint8_t addr) | Tier 2 | Check if a device responds at `addr` on `bus`. Returns 1 if the device ACKs, 0 on NACK / timeout / undeclared bus. |
_core_i2c_timing(uint32_t speed_hz) | Tier 1 | Resolve the TIMINGR value for a given speed using the compile-time I2C kernel clock (I2C_KERNEL_CLK_MHZ from core_config.h). Returns 0 if no pre-computed value exists. |
core_i2c_init(core_i2c_t * h, I2C_TypeDef * instance, uint32_t speed_hz) | Tier 1 | Initialize an I2C bus with automatic timing resolution. core_i2c_t bus; core_i2c_init(&bus, I2C1, I2C_400K); Resolves the TIMINGR value from the compile-time kernel clock. Enables FMP mode automatically when speed is I2C_1M. |
core_i2c_init_cfg(core_i2c_t * h, I2C_TypeDef * instance, const hal_i2c_config_t * cfg) | Tier 1 | Initialize I2C with explicit config struct (advanced). For most use cases, prefer core_i2c_init(h, instance, speed_hz). |
core_i2c_write(core_i2c_t * h, uint8_t addr, const uint8_t * data, uint32_t len) | Tier 1 | Write data to a 7-bit address device. |
core_i2c_read(core_i2c_t * h, uint8_t addr, uint8_t * buf, uint32_t len) | Tier 1 | Read data from a 7-bit address device. |
core_i2c_write_reg(core_i2c_t * h, uint8_t addr, uint16_t reg, const uint8_t * data, uint32_t len) | Tier 1 | Write to a device register (8 or 16-bit register address). |
core_i2c_read_reg(core_i2c_t * h, uint8_t addr, uint16_t reg, uint8_t * buf, uint32_t len) | Tier 1 | Read from a device register (repeated START). |
core_i2c_write_byte(core_i2c_t * h, uint8_t addr, uint16_t reg, uint8_t value) | Tier 1 | Write a single byte to a register. |
core_i2c_read_byte(core_i2c_t * h, uint8_t addr, uint16_t reg, uint8_t * value) | Tier 1 | Read a single byte from a register. |
core_i2c_probe(core_i2c_t * h, uint8_t addr) | Tier 1 | Check if a device responds at addr. Returns I2C_OK or I2C_NACK. |
core_i2c_scan(core_i2c_t * h, uint8_t * found, uint8_t * count, uint8_t max_count) | Tier 1 | Scan the I2C bus (0x08–0x77). Fills found[] with responding addresses. |
SPIguide →
| Function | Access | Description |
|---|---|---|
core_spi_xfer_byte_bus(uint8_t bus, uint8_t cs_pad, uint8_t tx) | Tier 2 | Single-byte full-duplex transfer over `bus`, with CS auto-managed around the call (asserted before, deasserted after). Returns the received byte (0..255) on success or -1 on any error (bus undeclared, cs_pad undefined). The signed return lets DSL programs branch on `< 0` without an out-pointer. Most chip protocols pair two of these (write a register address, then read or write the value). Multi-byte sequences that need CS held across them — display init streams, audio frame transfers — still need Tier 1 with manual select/deselect. |
core_spi_init(hal_spi_t * h, SPI_TypeDef * instance, const hal_spi_config_t * cfg) | Tier 1 | Initialize SPI in master mode. Same signature as hal_spi_init. |
core_spi_set_cs(hal_spi_t * h, uint8_t pad) | Tier 1 | Assign a CS pin using a tile pad number. Resolves pad to port/pin via hal_pad_lookup, then calls hal_spi_set_cs to configure and deassert the pin. |
core_spi_select(hal_spi_t * h) | Tier 1 | Assert CS (drive low). |
core_spi_deselect(hal_spi_t * h) | Tier 1 | Deassert CS (drive high). |
core_spi_transfer(hal_spi_t * h, uint8_t tx) | Tier 1 | Full-duplex single byte transfer. Returns received byte. |
core_spi_write(hal_spi_t * h, const uint8_t * data, uint32_t len) | Tier 1 | Write-only (discard received data). |
core_spi_read(hal_spi_t * h, uint8_t * buf, uint32_t len) | Tier 1 | Read-only (send zeros). |
core_spi_xfer(hal_spi_t * h, const uint8_t * tx, uint8_t * rx, uint32_t len) | Tier 1 | Convenience: select + full-duplex transfer + deselect. tx and rx can be the same buffer. Either can be NULL. |
core_spi_xfer_dma(hal_spi_t * h, const uint8_t * tx, uint8_t * rx, uint32_t len, hal_callback_t cb, void * ctx) | Tier 1 | Start a DMA-based SPI transfer (non-blocking). Full-duplex: tx bytes are sent while rx bytes are received simultaneously. Either tx or rx can be NULL for write-only or read-only transfers. The callback fires from DMA ISR context when the transfer completes. Caller must manage CS: assert before calling, deassert in the callback. The command/address byte should be sent via polling (core_spi_transfer) before starting DMA. |
core_spi_busy(hal_spi_t * h) | Tier 1 | Returns 1 if a DMA transfer is in progress. |
Timers & PWMguide →
| Function | Access | Description |
|---|---|---|
core_timer_init_freq(core_timer_t * h, TIM_TypeDef * instance, uint32_t freq_hz) | Tier 1 | Initialize a timer at a given overflow frequency. Use for PWM output and periodic tick — the frequency is how often the counter wraps (= the PWM frequency). core_timer_init_freq(&t, TIM2, 1000); // overflows at 1 kHz |
core_timer_init_tick(core_timer_t * h, TIM_TypeDef * instance, uint32_t tick_hz) | Tier 1 | Initialize a timer at a given tick rate, free-running to max count. Use for input capture — the tick rate sets the measurement resolution, and the counter runs as long as possible before wrapping (0xFFFF for 16-bit, 0xFFFFFFFF for 32-bit TIM2). core_timer_init_tick(&t, TIM2, 1000000); // 1 us per tick core_timer_capture_init(&t, 1); core_timer_start(&t); |
core_timer_start(core_timer_t * h) | Tier 1 | Start the timer counter. |
core_timer_stop(core_timer_t * h) | Tier 1 | Stop the timer counter. |
core_timer_set_freq(core_timer_t * h, uint32_t freq_hz) | Tier 1 | Change the timer frequency (recalculates PSC/ARR). |
core_timer_pwm_set(core_timer_t * h, uint8_t channel, uint16_t duty_permil) | Tier 1 | Set PWM duty cycle for a channel. channel: 1–4 duty_permil: 0–1000 (0 = off, 500 = 50%, 1000 = always on) |
core_timer_capture_init(core_timer_t * h, uint8_t channel) | Tier 1 | Configure a channel for input capture (rising edge). The timer must already be initialized with core_timer_init(). |
core_timer_capture_read(core_timer_t * h, uint8_t channel) | Tier 1 | Read the last captured value from a channel. |
core_timer_enable_tick(core_timer_t * h, core_callback_t cb, void * ctx) | Tier 1 | Enable periodic tick on an already-initialized timer. Does NOT touch PSC/ARR — the timer keeps its existing timebase. The callback fires on each counter overflow at the timer's frequency. Typical pattern: core_timer_init(&t, TIM2, 1000); // 1 kHz timebase core_timer_pwm_set(&t, 1, 500); // CH1 = 50% PWM (permil) core_timer_enable_tick(&t, on_tick, NULL); // also fire ISR at 1 kHz core_timer_start(&t); |
core_timer_disable_tick(core_timer_t * h) | Tier 1 | Disable the tick callback (clears UIE, keeps timer running). |
core_tick_init(core_timer_t * h, TIM_TypeDef * instance, uint32_t period_us, core_callback_t cb, void * ctx) | Tier 1 | Convenience: initialize a timer as a tick-only source. Sets up the timebase AND enables the update interrupt. Use this when the timer's only job is a periodic callback. core_tick_init(&t, TIM3, 500000, on_tick, NULL); // 2 Hz core_timer_start(&t); |
core_pwm_duty(uint8_t pad, uint16_t duty_permil) | Tier 2 | Set PWM duty cycle on a pad. Timer handle resolved from config.json. |
core_pwm_init(core_timer_t * h, TIM_TypeDef * instance, uint32_t freq_hz) | Tier 1 | Initialize a timer for PWM output at the given frequency. Clock is auto-resolved from SYSCLK_HZ (core_config.h). |
core_pwm_init_clk(core_timer_t * h, TIM_TypeDef * instance, uint32_t pclk_hz, uint32_t freq_hz) | Tier 1 | |
core_pwm_set(core_timer_t * h, uint8_t channel, uint16_t duty_permil) | Tier 1 | Set PWM duty cycle for a channel. channel: 1–4 duty_permil: 0–1000 (0 = off, 500 = 50%, 1000 = 100%) |
core_pwm_set_freq(core_timer_t * h, uint32_t freq_hz) | Tier 1 | Change PWM frequency (recalculates PSC/ARR, resets all channel duties). |
core_pwm_start(core_timer_t * h) | Tier 1 | Start the PWM timer. |
core_pwm_stop(core_timer_t * h) | Tier 1 | Stop the PWM timer. |
core_pwm_init_pad(core_timer_t * h, uint8_t pad, uint32_t freq_hz) | Tier 1 | Initialize PWM on a pad. Timer instance resolved from config.json. |
core_pwm_set_pad(core_timer_t * h, uint8_t pad, uint16_t duty_permil) | Tier 1 | Set PWM duty on a pad (0–1000 permil). |
core_every_us(core_timer_t * h, TIM_TypeDef * instance, uint32_t period_us, hal_callback_t cb, void * ctx) | Tier 1 | Configure a periodic callback at a fixed interval. period_us: interval in microseconds (1 – 1000000) cb: callback function (called from ISR context!) ctx: user context passed to callback Clock is auto-resolved from SYSCLK_HZ (core_config.h). |
core_every_us_clk(core_timer_t * h, TIM_TypeDef * instance, uint32_t pclk_hz, uint32_t period_us, hal_callback_t cb, void * ctx) | Tier 1 | |
core_every_start(core_timer_t * h) | Tier 1 | Start the periodic timer. |
core_every_stop(core_timer_t * h) | Tier 1 | Stop the periodic timer. |
Analog (ADC / DAC)guide →
| Function | Access | Description |
|---|---|---|
core_adc_read_pad(uint8_t pad) | Tier 2 | Read a pad as raw ADC counts (0–4095 at 12-bit resolution). |
core_adc_read_mv_pad(uint8_t pad) | Tier 2 | Read a pad as calibrated millivolts (uses VREFINT for per-chip accuracy). |
core_adc_temp_decidegc(void) | Tier 2 | Die temperature in tenths of deg C (e.g. 253 = 25.3 C). Dispatches to the default ADC instance. |
core_adc_vdd_mv(void) | Tier 2 | VDD supply voltage in millivolts (via VREFINT). Dispatches to the default ADC instance. |
core_adc_init(core_adc_t * adc, uint32_t resolution) | Tier 1 | Initialise the ADC at the given resolution. |
core_adc_add(core_adc_t * adc, uint8_t pad, uint32_t samp) | Tier 1 | Register a pad as an ADC input with the given sampling speed. |
core_adc_read(core_adc_t * adc, uint8_t pad) | Tier 1 | Single-shot read — returns raw ADC count. |
core_adc_read_mv(core_adc_t * adc, uint8_t pad) | Tier 1 | Single-shot read — returns calibrated millivolts. |
core_adc_temp(core_adc_t * adc) | Tier 1 | Die temperature in tenths of deg C (e.g. 253 = 25.3 C). |
core_adc_vdd(core_adc_t * adc) | Tier 1 | Actual VDD supply voltage in millivolts via VREFINT. |
core_adc_start_dma(core_adc_t * adc, uint16_t * buf, uint16_t len, hal_callback_t cb, void * ctx) | Tier 1 | Start continuous conversion with DMA circular buffer. |
core_adc_stop_dma(core_adc_t * adc) | Tier 1 | Stop continuous DMA conversion. |
core_adc_dma_read(core_adc_t * adc, uint8_t pad) | Tier 1 | Read most recent DMA result for a pad. |
core_dac_init(void) | Tier 2 | Initialize the DAC (clock, GPIO, peripheral). Call once from `on start` before any writes. |
core_dac_write(uint16_t val) | Tier 2 | Write a raw 12-bit value. Output = val / 4095 × VREF+. |
core_dac_write_mv(uint16_t mv) | Tier 2 | Write a voltage in millivolts. |
core_dac_read(void) | Tier 2 | Read back the current DAC output register value (12-bit). |
Audio (PDM mic)guide →
| Function | Access | Description |
|---|---|---|
core_pdm_init(core_pdm_cic_t * st, uint8_t order, uint16_t decimation, uint8_t gain_shift, uint8_t lsb_first) | Tier 1 | Initialise a CIC decimator. |
core_pdm_process(core_pdm_cic_t * st, const uint8_t * pdm, uint32_t nbytes, int16_t * out) | Tier 1 | Decimate a block of packed PDM bits into PCM samples. |
Powerguide →
| Function | Access | Description |
|---|---|---|
core_sleep(void) | Tier 2 | Sleep until any interrupt (CPU stopped, peripherals running). |
core_stop_for(uint32_t seconds) | Tier 2 | Enter Stop mode for a number of seconds, then wake and restore clocks. Uses RTC wakeup timer (LSI). Returns after wake with PLL + SysTick restored. |
core_woke_from_standby(void) | Tier 2 | Returns 1 if the MCU woke from Standby. |
core_stop_until_on_change(uint8_t pad, uint32_t edge) | Tier 1 | Enter Stop mode until a GPIO edge occurs on the given pad. Configures the pad as input, enables EXTI, enters Stop, and restores clocks on wake. Returns after the edge is detected. |
core_standby_for(void) | Tier 1 | Enter Standby mode with RTC wakeup after the given seconds. Does not return — MCU resets on wake. Check core_woke_from_standby() at the top of main() to detect a Standby wake. |
core_standby_until_on_change(uint8_t pad, uint32_t edge) | Tier 1 | Enter Standby mode until a GPIO edge on the given pad (via WKUP pin). Does not return — MCU resets on wake. Not all pads support WKUP; returns without entering Standby if the pad has no WKUP capability. On Core.ST.L4.2: pad 8 (PA0 = WKUP1) and pad 7 (PA2 = WKUP4). |
core_stop(void) | Tier 1 | Enter Stop mode (caller manages wakeup source + clock recovery). |
core_standby(void) | Tier 1 | Enter Standby (caller manages wakeup source). Does not return. |
core_clear_standby_flag(void) | Tier 1 | Clear the Standby wake flag. Call after core_woke_from_standby() returns 1. |
core_watchdog_start_seconds(uint32_t seconds) | Tier 1 | Start the independent watchdog with a timeout in seconds (convenience). For finer control use core_watchdog_start() from core_watchdog.h which accepts milliseconds. |
core_rtc_init(void) | Tier 2 | Initialize the RTC using LSI (~32kHz internal RC). Call once from `on start` before setting time, date, or alarms. For LSE, call ll_rtc_init(1) directly in hand-written C. |
core_rtc_set_time(uint8_t h, uint8_t m, uint8_t s) | Tier 2 | Set the time (24h format). |
core_rtc_set_date(uint8_t y, uint8_t mo, uint8_t d, uint8_t wd) | Tier 2 | Set the date. |
core_rtc_wakeup(uint32_t seconds) | Tier 2 | Configure a periodic wakeup timer. |
core_rtc_wakeup_stop(void) | Tier 2 | Disable the periodic wakeup timer. |
core_rtc_set_alarm(uint8_t hours, uint8_t minutes, uint8_t seconds) | Tier 2 | Set Alarm A to trigger at a specific time. Pass 0xFF for hours, minutes, or seconds to ignore that field. The alarm fires when all non-masked fields match the RTC time. |
core_rtc_clear_alarm(void) | Tier 2 | Clear the alarm (disable Alarm A). |
core_rtc_alarm_fired(void) | Tier 2 | Check if the alarm has fired (poll mode). Clears the flag on read. |
core_rtc_get_time(uint8_t * h, uint8_t * m, uint8_t * s) | Tier 1 | Read the current time. |
core_rtc_get_date(uint8_t * y, uint8_t * mo, uint8_t * d, uint8_t * wd) | Tier 1 | Read the current date. |
core_backup_read(uint8_t index) | Tier 2 | Read a backup register. |
core_backup_write(uint8_t index, uint32_t value) | Tier 2 | Write a backup register. Backup domain write access is enabled automatically. |
_core_backup_ensure_clk(void) | Tier 1 | Ensure the RTC/backup register clock domain is accessible. On L0/L4 the backup registers live inside the RTC peripheral block, so RTCEN (and a clock source) must be active for reads AND writes. On WBA/H5 they're in TAMP, which only needs PWR+DBP. |
Securityguide →
| Function | Access | Description |
|---|---|---|
core_rng_read(void) | Tier 2 | Read a single 32-bit random value (blocking). Returns 0 on timeout — check core_rng_error() if this happens. |
core_rng_init(void) | Tier 1 | Initialize the hardware RNG. Enables the peripheral clock, configures the RNG, and waits for the first random number to be ready. On Core.ST.L4: requires HSI48 to be running (auto-enabled if USB is used, otherwise call ll_rcc_hsi48_enable() first). |
core_rng_fill(uint32_t * buf, uint32_t count) | Tier 1 | Fill a buffer with random 32-bit values (blocking). |
core_rng_error(void) | Tier 1 | Check if the RNG has a seed error (entropy source failure). |
core_rng_deinit(void) | Tier 1 | Power down the RNG peripheral. |
USBguide →
| Function | Access | Description |
|---|---|---|
core_usb_print(const char * s) | Tier 2 | Print a string followed by a newline. Thin wrapper for DSL-style callers. |
core_usb_print_int(int v) | Tier 2 | Print a signed integer followed by a newline. |
core_usb_print_float(double v) | Tier 2 | Print a double with a newline. %g trims trailing zeros for readability. |
core_usb_print_bool(int v) | Tier 2 | Print "true" / "false" followed by a newline. |
core_usb_init(void) | Tier 1 | Initialize USB CDC. Device appears as /dev/tty.usbmodem* on the host. |
core_usb_connected(void) | Tier 1 | Returns 1 if a host terminal is connected (DTR set). |
core_usb_write(const uint8_t * buf, uint16_t len) | Tier 1 | Transmit data (blocking). Returns bytes sent, or -1 if not configured. |
core_usb_on_receive(hal_usb_cdc_rx_cb_t cb, void * ctx) | Tier 1 | Set a callback for received data. Called from USB ISR. When set, data is NOT buffered for polling reads. |
core_usb_available(void) | Tier 1 | Returns the number of bytes available to read (ring buffer mode). |
core_usb_getc(void) | Tier 1 | Read a single byte (blocking — waits for data). |
core_usb_read(uint8_t * buf, uint16_t max) | Tier 1 | Read available bytes into buf (non-blocking). Returns bytes read. |
core_usb_try_read(uint8_t * byte) | Tier 1 | Non-blocking single byte read. Returns 1 if a byte was read, 0 if empty. |
BLEguide →
| Function | Access | Description |
|---|---|---|
core_ble_set_services(void) | Tier 1 | Register a service builder function. Called before core_ble_init(). The builder is invoked during init after the GATT server is ready. |
core_ble_init(void) | Tier 1 | Initialize the BLE stack. Call once after core_init(). |
core_ble_advertise(const char * name) | Tier 1 | Start advertising. Call after init + at least one core_ble_process(). |
core_ble_stop_advertise(void) | Tier 1 | Stop advertising. |
core_ble_process(void) | Tier 1 | Process BLE events. Call continuously from main loop. |
core_ble_add_service(const char * name) | Tier 1 | Add a GATT service. Returns a handle for adding characteristics. The UUID is auto-assigned SEQUENTIALLY by registration order (0000B000-…, 0000B100-…, …). Convenient, but the UUIDs shift if you reorder or insert services — so for a contract shared with client apps, prefer core_ble_add_service_id() to pin a stable, order-independent UUID. |
core_ble_add_service_id(const char * name, uint16_t id) | Tier 1 | Add a GATT service with an EXPLICIT 16-bit ID. The full UUID is 0000<id>-8E22-4541-9D4C-21EDAE82ED19. Pinning the ID makes the GATT contract independent of registration order — the recommended path when the service map is a source of truth shared with phone / desktop client apps. |
core_ble_add_char(core_ble_svc_t svc, const char * name, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx) | Tier 1 | Add a characteristic to a service. |
core_ble_add_char_id(core_ble_svc_t svc, const char * name, uint16_t id, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx) | Tier 1 | Add a characteristic with an EXPLICIT 16-bit ID (0000<id>-8E22-…), the order-independent counterpart to core_ble_add_char(). Use for the stable contract shared with client apps. |
core_ble_add_service_sig(const char * name, uint16_t uuid16) | Tier 1 | Add a SIG-adopted service by its 16-bit Bluetooth UUID (e.g. 0x180F Battery Service, 0x180A Device Information). Use adopted services for standardised profiles so generic clients and the host OS recognise them; use the _id variants for custom application-specific data. |
core_ble_add_char_sig(core_ble_svc_t svc, const char * name, uint16_t uuid16, uint8_t access, uint8_t type, core_ble_write_cb on_write, void * ctx) | Tier 1 | Add a SIG-adopted characteristic by its 16-bit Bluetooth UUID (e.g. 0x2A19 Battery Level, 0x2A29 Manufacturer Name) to a service. |
core_ble_set_value(core_ble_char_t ch, const void * data, uint16_t len) | Tier 1 | Update a characteristic's value. For readable characteristics, this is what the central will read. For notify characteristics, call core_ble_notify() after to push the update. |
core_ble_notify(core_ble_char_t ch) | Tier 1 | Send a notification to the connected central. The central must have enabled notifications (CCCD) for this to work. Sends the current value set by core_ble_set_value(). |
core_ble_connected(void) | Tier 1 | Returns 1 if a central is connected. |
core_ble_on_connect(void * ctx) | Tier 1 | Set callback for connection events. |
core_ble_on_disconnect(void * ctx) | Tier 1 | Set callback for disconnection events. |
core_ble_set_tx_power(uint8_t level) | Tier 1 | TX power: 0=low(-20dBm), 1=medium(0dBm), 2=high(+10dBm). Default: 1. |
core_ble_set_adv_interval(uint16_t min_ms, uint16_t max_ms) | Tier 1 | Advertising interval in ms (20-10240). Default: 100/150. |
core_ble_set_conn_params(uint16_t min_ms, uint16_t max_ms, uint16_t latency, uint16_t timeout_ms) | Tier 1 | Request a preferred connection parameter set from the central. The central ultimately owns the connection timing, but a peripheral can ask for parameters that suit its traffic. After each connection the SDK sends an L2CAP update request (retrying until the stack accepts it, since the link is busy with pairing/discovery right after connecting). May also be called while connected to re-request — e.g. tighten the interval while streaming, relax it when idle. For Apple hosts, keep within their guidelines: interval_min >= 15 ms, interval_max >= interval_min + 15 ms, interval_max * (latency + 1) <= 2 s, and timeout in 2000..6000 ms. A short interval lowers latency for high-rate notifications at the cost of power; latency > 0 saves power when the peripheral often has nothing to send. |
core_ble_enable_pairing(void) | Tier 1 | Enable OS-level pairing + bonding (Just Works). When enabled, every characteristic is registered behind an encrypted link, so on first access the host runs its pairing flow (a "Pair?" prompt on most OSes; silent for Just Works on macOS). Keys are persisted in flash NVM, so the bond survives resets — the host doesn't re-pair on the next connection and the device stays listed in OS Bluetooth settings. (Reconnect itself is the central's choice; the peripheral simply re-advertises after a drop.) Call before core_ble_init(). Default: disabled (characteristics open, no pairing). Note that once enabled, *all* clients must pair to read/write. |

