git:20260225.a4aeb64 to git:20260226.186740f

154 added, 69 removed. Audit C to C.

- # Debug Trace Patterns
-
- A comprehensive pattern library and knowledge base for debug-trace.
+ # debug-trace-patterns
## Knowledge Base
- ### Core Concepts
- - **Fundamentals**: The foundational principles that govern debug-trace
- - **Terminology**: Standard vocabulary and definitions used in the domain
- - **Standards**: Industry standards and specifications that apply
- - **Tools**: Common tools and frameworks used for debug-trace
+ Practical debug patterns for ARM Cortex-M firmware. Tools: OpenOCD, GDB, J-Link, logic analyzer.
- ### Architecture Principles
- - Separation of concerns within debug-trace implementations
- - Modularity and reusability of components
- - Scalability considerations for growing systems
- - Integration patterns with adjacent domains
+ ---
- ### Quality Attributes
- - **Correctness**: Implementations must meet functional requirements
- - **Maintainability**: Code and artifacts should be easy to understand and modify
- - **Performance**: Implementations should meet non-functional requirements
- - **Security**: Sensitive data and operations must be properly protected
+ ## Pattern 1: Decode CFSR After HardFault
- ## Patterns
+ Given a CFSR value (e.g., from `monitor mdw 0xE000ED28`), decode:
- ### Pattern 1: Structured Approach
- - Start with requirements analysis
- - Design before implementing
- - Validate against acceptance criteria
- - Document decisions and rationale
+ ```
+ CFSR = 0x00020000 → UFSR.INVSTATE (bit 17)
+ Cause: Attempted to execute code with Thumb bit cleared in xPSR.
+ Common cause: function pointer stored with bit 0 cleared (missing |1 for Thumb).
- ### Pattern 2: Iterative Refinement
- - Begin with a minimal viable implementation
- - Gather feedback early and often
- - Refine based on real-world usage
- - Continuously improve based on metrics
+ CFSR = 0x00000400 → BFSR.IMPRECISERR (bit 10)
+ Cause: Imprecise bus error. BFAR is not valid.
+ Common cause: DMA write to invalid address, async fault from write buffer.
+ Fix: set SCB->CCR |= SCB_CCR_BFHFNMIGN_Msk temporarily to locate source.
- ### Pattern 3: Convention Over Configuration
- - Follow established conventions where they exist
- - Configure only what needs to deviate from defaults
- - Document any non-standard choices
- - Prefer explicit over implicit behavior
+ CFSR = 0x00008200 → BFSR.PRECISERR + BFSR.BFARVALID
+ Cause: Precise data bus error. BFAR = 0xE000ED38 contains fault address.
+ Common cause: null pointer dereference, access to unmapped memory region.
- ### Pattern 4: Defense in Depth
- - Validate at multiple levels
- - Handle errors gracefully at each layer
- - Provide meaningful feedback for failures
- - Log important events for debugging
+ CFSR = 0x02000000 → UFSR.DIVBYZERO (bit 25)
+ Cause: Integer divide by zero.
+ Fix: enable div-by-zero trap: SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk.
+ ```
- ## Anti-Patterns
+ ---
- ### Anti-Pattern 1: Premature Optimization
- - Optimizing before understanding the actual bottleneck
- - Adding complexity without measured need
- - Sacrificing readability for marginal performance gains
+ ## Pattern 2: addr2line — Fault PC to Source Line
- ### Anti-Pattern 2: Copy-Paste Without Understanding
- - Duplicating code without understanding its purpose
- - Propagating bugs through mechanical copying
- - Missing opportunities for abstraction
+ ```bash
+ # Convert stacked PC to source file + line number
+ arm-none-eabi-addr2line -e firmware.elf -f -i 0x08003A24
- ### Anti-Pattern 3: Ignoring Standards
- - Deviating from conventions without clear justification
- - Creating inconsistency across the codebase
- - Making onboarding harder for new contributors
+ # Output:
+ # sensor_read
+ # /home/user/project/src/sensor.c:87
- ### Anti-Pattern 4: Over-Engineering
- - Building for hypothetical future requirements
- - Adding abstraction layers without clear benefit
- - Creating complex solutions for simple problems
+ # Also inspect LR to find the caller:
+ arm-none-eabi-addr2line -e firmware.elf -f -i 0x080038F6
+ ```
- ## References
+ The `-i` flag follows inline function chains.
- ### Documentation
- - Official documentation for related tools and frameworks
- - Industry standards and specifications
- - Community best practices and guides
+ ---
- ### Learning Resources
- - Tutorials and walkthroughs for beginners
- - Advanced guides for experienced practitioners
- - Case studies and real-world examples
+ ## Pattern 3: GDB Commands for Live Fault Debugging
- ### Tools
- - Development tools for debug-trace
- - Testing and validation tools
- - Monitoring and observability tools
+ ```bash
+ # Full embedded debug session
+ arm-none-eabi-gdb firmware.elf
+ (gdb) target remote :3333 # OpenOCD GDB server
+ (gdb) monitor reset halt
+ (gdb) load
+
+ # After a fault occurs:
+ (gdb) info registers # All CPU registers
+ (gdb) p/x *((uint32_t*)0xE000ED28) # CFSR
+ (gdb) p/x *((uint32_t*)0xE000ED2C) # HFSR
+ (gdb) p/x *((uint32_t*)0xE000ED34) # MMFAR
+ (gdb) p/x *((uint32_t*)0xE000ED38) # BFAR
+ (gdb) x/16xw $sp # Stack dump
+ (gdb) backtrace # Unwind stack (requires -g and no -O2 optimization)
+
+ # Watchpoints: halt when variable changes
+ (gdb) watch g_critical_var
+ (gdb) rwatch *(uint32_t*)0x20001000 # Hardware read watchpoint (DWT)
+ ```
+
+ ---
+
+ ## Pattern 4: Stack Corruption Detection with Canary
+
+ ```c
+ #define STACK_CANARY_VAL 0xDEADBEEFUL
+
+ /* Place canary at bottom of task stack (lowest address, first to overflow) */
+ void stack_canary_init(uint32_t *stack_bottom, uint32_t depth)
+ {
+ for (uint32_t i = 0; i < depth; i++) {
+ stack_bottom[i] = STACK_CANARY_VAL;
+ }
+ }
+
+ /* Call periodically or from idle task hook */
+ bool stack_canary_check(const uint32_t *stack_bottom, uint32_t depth)
+ {
+ for (uint32_t i = 0; i < depth; i++) {
+ if (stack_bottom[i] != STACK_CANARY_VAL) {
+ return false; /* Overflow: canary corrupted */
+ }
+ }
+ return true;
+ }
+ ```
+
+ FreeRTOS alternative: `uxTaskGetStackHighWaterMark(NULL)` returns minimum free stack words ever observed for the current task.
+
+ ---
+
+ ## Pattern 5: ITM Trace Printf
+
+ ```c
+ /* Retarget printf to ITM port 0 (SWO output) */
+ int _write(int fd, const char *buf, int len)
+ {
+ (void)fd;
+ for (int i = 0; i < len; i++) {
+ ITM_SendChar((uint32_t)buf[i]);
+ }
+ return len;
+ }
+
+ /* ITM enable in SystemInit or debug init: */
+ void itm_enable(uint32_t cpu_freq, uint32_t swo_freq)
+ {
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+ /* SWO prescaler: cpu_freq / swo_freq - 1 */
+ TPI->ACPR = cpu_freq / swo_freq - 1U;
+ TPI->SPPR = 2U; /* NRZ (UART) encoding */
+ TPI->FFCR = 0x100U;
+ ITM->LAR = 0xC5ACCE55UL; /* Unlock ITM */
+ ITM->TCR = ITM_TCR_ITMENA_Msk | ITM_TCR_SYNCENA_Msk | (1UL << 16);
+ ITM->TER = 0xFFFFFFFFUL; /* Enable all 32 stimulus ports */
+ }
+ ```
+
+ Host: ST-Link SWV viewer in STM32CubeIDE, or J-Link SWO Viewer, or OpenOCD `tpiu` + PuTTY serial.
+
+ ---
+
+ ## Pattern 6: DWT Data Watchpoint (without debugger)
+
+ Use DWT comparators to detect writes to a specific address at runtime:
+
+ ```c
+ /* Trigger DebugMon exception when address 0x20001234 is written */
+ void dwt_set_watchpoint(uint32_t addr)
+ {
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk | CoreDebug_DEMCR_MON_EN_Msk;
+ DWT->COMP0 = addr;
+ DWT->MASK0 = 0U; /* Match exact address */
+ DWT->FUNCTION0 = 0x6U; /* Data write watchpoint → DebugMon */
+ }
+
+ /* DebugMon_Handler fires instead of halting (no debugger attached) */
+ void DebugMon_Handler(void)
+ {
+ DWT->FUNCTION0 = 0U; /* Disable watchpoint */
+ /* Log PC, LR for analysis */
+ }
+ ```
+
+ ---
+
+ ## Anti-Patterns
+
+ - **Using printf for timing analysis**: printf is slow (UART or ITM) and perturbs timing. Use DWT->CYCCNT or toggle a GPIO on oscilloscope.
+ - **Compiling with -O0 always**: some bugs are optimizer-sensitive. Debug with -Og (debug optimizations) to get accurate backtraces while keeping most debug info.
+ - **Ignoring IMPRECISERR**: it means the fault address is not directly available. Enable BFHFNMIGN + process in NMI to find the source.
+ - **Not initializing DWT before using cycle counter**: CoreDebug->DEMCR bit must be set first, or DWT->CYCCNT stays 0.
+
+ ## References
+
+ - ARM CoreSight Architecture Specification: IHI0029
+ - OpenOCD documentation: openocd.org/doc/html/
+ - Percepio Tracealyzer: trace tool for FreeRTOS
+ - "Hard Fault Analysis" by Joseph Yiu (ARM community blog)