System
The services every Core gives you for free — blocking delays and a millisecond clock, the independent watchdog for recovering from hangs, and fault handlers that turn a crash into a readable register dump. None of them need a pad or any configuration. Use the Core / HAL / LL toggle at the top of the sidebar to see each at the layer you work in.
Overview
System features handle timing and fault recovery. They’re available on every Core tile and require no pad assignments or peripheral configuration — they’re part of the Core itself, not something you wire up.
Delays, timekeeping, and the fault handlers come in automatically through core.h — no extra includes. The watchdog is opt-in: include core_watchdog.h when you want it. Most calls are Tier 2 — you call them directly, no handle. A few watchdog helpers are Tier 1, meant for a one-time check at boot.
Delays & timing
Blocking delays and a free-running millisecond counter come from core.h. The counter is handy for timeouts and general timekeeping without tying up a hardware timer.
core_delay_ms(500); // block for 500 ms
core_delay_us(100); // block for 100 us
uint32_t start = core_millis();
// ... your application code ...
if (core_timeout(start, 1000)) {
// 1 second has elapsed since 'start'
}core_delay_usis for short waits — for anything over a millisecond prefercore_delay_ms, which won’t starve the rest of the system as long.core_millis()counts up from boot and wraps after ~49 days. Compare withcore_timeout()rather than subtracting raw values, so a wrap doesn’t bite you.
Watchdog
The independent watchdog (IWDG) runs on its own 32 kHz LSI clock, completely separate from the system clock. Once started, it cannot be stopped — only a full MCU reset disables it. If your code doesn’t refresh it before the timeout, the MCU resets itself. That’s exactly what you want in a deployed system: a hang, an infinite loop, or a deadlock all recover automatically.
#include "core.h"
#include "core_watchdog.h"
int main(void)
{
core_init();
if (core_watchdog_caused_reset()) {
// We rebooted from a watchdog reset — handle recovery
core_watchdog_clear_flags();
}
core_watchdog_start(2000); // 2-second timeout
while (1) {
// ... your application code ...
core_watchdog_feed(); // must call within 2 seconds
}
}Pass the timeout in milliseconds; the prescaler and reload are chosen for you. The usable range is roughly 100 ms to 28 s. start and feed are the everyday Tier 2 calls; core_watchdog_caused_reset() and core_watchdog_clear_flags() are Tier 1 helpers you typically call once, at boot, to detect and acknowledge a watchdog-induced reset.
stop. Start the watchdog only after init is complete and your loop is actually feeding it, or the first slow path will reset you mid-bring-up.Fault handlers
The SDK installs handlers for the four CPU faults — HardFault, MemManage, BusFault, and UsageFault. When one fires, the handler captures the stacked register frame (PC, LR, R0–R3, R12, PSR) and the Configurable Fault Status Register (CFSR), dumps them over USB CDC, then blinks SOS on the onboard LED.
No setup required. The handlers are compiled into every project automatically and override the default infinite-loop handlers from the startup code. The USB dump uses polled transmit that works with interrupts disabled, so it runs even from fault context; if USB CDC was never initialized, the dump is silently skipped and you still get the LED SOS.
Example output
*** HardFault ***
PC = 0xDEADDEAC
LR = 0x08002345
R0 = 0x00000000
R1 = 0x20001234
R2 = 0x00000000
R3 = 0x00000001
R12 = 0x00000000
PSR = 0x61000000
CFSR = 0x00000001
SOS...The PC value is the instruction that faulted — look it up in your .map file or a disassembly to find the source line.
Optional callback
Register a callback to run just before the dump and SOS — e.g. to log the fault to flash or set a flag for the next boot. It runs in fault context, so keep it minimal: no heap, no interrupts.
#include "core_fault.h"
void my_fault_handler(hal_fault_type_t type, const hal_fault_frame_t *frame)
{
// Log fault PC to NVM, set a flag, etc. Keep it tiny.
(void)type;
(void)frame;
}
// In main, before your loop:
core_fault_set_callback(my_fault_handler);API reference
Delays & timing
void core_delay_ms(uint32_t ms);void core_delay_us(uint32_t us);uint32_t core_millis(void);int core_timeout(uint32_t start, uint32_t ms);void core_cycle_init(void);void core_delay_cycles(uint32_t cycles);void core_delay_ns(uint32_t ns);Generated from core_timing.h — tiles@777be99.
Watchdog
void core_watchdog_start(uint32_t timeout_ms);void core_watchdog_feed(void);int core_watchdog_caused_reset(void);void core_watchdog_clear_flags(void);void core_watchdog_debug_freeze(void);Generated from core_watchdog.h — tiles@0ea79c0.
Fault handlers
Fault handling has a single hook (the rest is automatic — see above). No generated manifest yet, so this one is listed by hand:
void core_fault_set_callback(hal_fault_callback_t cb);
