$ embedded-explainer timer_config.c --depth detailed
── timer_config.c [detailed] ──
Detected: STM32 HAL · ISR ×1 · Timer · volatile ×1
## STM32F4 TIM2 — 1 kHz Interrupt Configuration
**Clock gating** — __HAL_RCC_TIM2_CLK_ENABLE() sets TIM2EN in RCC_APB1ENR,
connecting TIM2 to the bus matrix. Without this, writes to TIM2 registers do
nothing.
**Prescaler arithmetic** — Prescaler=83 divides the 84 MHz APB1 timer clock to
1 MHz. The hardware always adds 1, so PSC=83 means ÷84.
**Period and overflow** — Period=999 makes the counter overflow at 1 kHz
(1 MHz ÷ 1000). AutoReloadPreload double-buffers ARR so runtime changes take
effect cleanly at the next cycle boundary.
**ISR dispatch chain** — TIM2_IRQHandler → HAL_TIM_IRQHandler (clears UIF in
TIM2_SR) → HAL_TIM_PeriodElapsedCallback. Clearing UIF before the callback is
critical: if it is still set on ISR return, the CPU re-enters immediately.
**Race condition** — tick_count++ is a load-add-store sequence, not atomic.
Read it into a local variable in main before comparing.
Generic code explainers tell you what the code says. This one tells you what the hardware is doing.
Most LLMs explain HAL_TIM_Base_Init() as "initializes the timer base." That's the function name — not an explanation. embedded-explainer detects STM32 HAL calls, ISR handlers, DMA transfers, volatile shared variables, and memory-mapped register patterns, then builds a domain-aware prompt that produces explanations like:
"Prescaler=83 divides the 84 MHz APB1 timer clock to 1 MHz. The hardware always adds 1 to PSC, so writing 83 gives you a ÷84 divisor."
That's the explanation a senior firmware engineer gives a junior on their first week.
pip install embedded-explainerOr install from source:
git clone https://github.com/aulsz/embedded-explainer
cd embedded-explainer
pip install -e .Set your API key:
export ANTHROPIC_API_KEY=sk-ant-...No key? Try the built-in demo first (no key required):
embedded-explainer --demoembedded-explainer [FILE] [OPTIONS]
Arguments:
FILE Path to a .c or .py file
Options:
-d, --depth [quick|detailed|teach]
quick — 3-4 sentence summary
detailed — section-by-section with hardware implications [default]
teach — full walkthrough for a junior developer
--stream / --no-stream Stream tokens as they generate [default: stream]
--demo Run on bundled STM32 TIM2 example (no API key)
--no-cache Force a fresh API call, skip cache
--clear-cache Delete all cached responses and exit
-h, --help Show this message and exit
--version Show version and exit
Examples:
# Explain a file with default (detailed) depth
embedded-explainer src/motor_control.c
# Get a quick summary
embedded-explainer usart.c --depth quick
# Full junior-dev walkthrough
embedded-explainer dma_config.c --depth teach
# Run the built-in STM32 demo — no API key needed
embedded-explainer --demo --depth teach
# Force re-analysis (skip cache)
embedded-explainer isr.c --no-cacheembedded-explainer scans the file before calling the API and injects targeted context for whatever it finds:
| Pattern | What gets injected |
|---|---|
HAL_* calls |
STM32 HAL peripheral knowledge, clock gating requirements |
*_IRQHandler / __attribute__((interrupt)) |
ISR dispatch chain, UIF clearing, re-entrancy |
DMA_* / HAL_DMA_* |
Transfer direction, completion behavior, cache coherency |
TIM_* / HAL_TIM_* |
Prescaler/ARR arithmetic, double-buffering |
UART_* / USART_* |
Baud rate calculation, clock source |
volatile variables |
Atomicity assessment, ISR/main shared-state risks |
| RTOS primitives | ISR-safe API variants, priority inversion |
Raw *(uint32_t*)0x4... |
Peripheral address range identification |
Responses are cached in ~/.cache/embedded-explainer/ keyed by SHA-256(file_content + depth). Rerunning on the same file at the same depth is instant and costs no API tokens.
embedded-explainer --clear-cache # wipe all cached responses
embedded-explainer file.c --no-cache # force fresh callThe preprocessing pipeline is what separates this from a generic "send to ChatGPT" script:
- Pattern detection (
preprocess.py) — regex scan for HAL calls, ISR handlers, DMA patterns, volatile variables, RTOS primitives. Builds aCodeContextdataclass. - Dynamic system prompt (
prompts.py) — assembles a targeted system prompt from the detected context. Different peripherals inject different domain knowledge. A file with DMA gets cache coherency context. A file with ISRs gets interrupt dispatch chain context. - Depth-aware user prompt — three prompt templates (
quick,detailed,teach) that set different output format expectations. - SHA-256 cache (
cache.py) — keyed on file content + depth. Repeated analysis of unchanged files is free. - Streaming CLI (
cli.py) — Click-based interface with streaming output, colored headers, and pattern tag display.
| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
— | Required (except --demo) |
EXPLAINER_MODEL |
claude-3-5-haiku-20241022 |
Override the model |
MIT