Skip to content

The firmware you flash

The same call is a different function on every board. Context is the image this product runs.

The build gives the context

ByteAsk Context indexes the functions and calls your compile commands select. The examples below show what was captured for this domain.

portENTER_CRITICAL();

Text search
205 lines in 168 files. 128 #defines, in 128 port files. GCC 42, IAR 32, RVDS/Keil 7, Renesas 6, and others
POSIX index
One definition: vPortEnterCritical(), portable/ThirdParty/GCC/Posix/port.c:249, with 32 callers

Lines and #defines: rg -w portENTER_CRITICAL, FreeRTOS-Kernel 8e2dd5b. The definition and the 32 callers are the POSIX build index, from the embedded deck notes, not from that rg.

How ByteAsk Context works

A watchpoint finds the wrong joint

armctl, a simulated arm controller. The watchpoint stops on the joint written by mistake. The rebuilt program finishes with every joint inside its soft limits.

Shown here: a watchpoint in gdb, then a rebuild. This recording does not run the sanitizers after the fix.

Hardware watchpoint 2: -location *(double*)0x555555559280
Old value = -1.9057374359644947
New value = -1.8236172821972838
$8 = 5
$12 = "elbow\000\000"
I have the concrete bad store: after reprioritization, controller `joint_id_=5` still targets `slot_=5`, and slot 5 now holds `elbow`.
+            for (int i = 0; i < kNumJoints; ++i) ctl[i].bind(static_cast<std::uint32_t>(i));
completed, all joints within soft limits
Recorded 2026-09-11.
Read the full captured excerpt
{"action":"cmd","session":1,"command":"print &g_joints[5].measured_rad"}
$6 = (double *) 0x555555559280 <rtc::g_joints+256>
{"action":"cmd","session":1,"command":"watch -location *(double*)0x555555559280"}
Hardware watchpoint 2: -location *(double*)0x555555559280
{"action":"cmd","session":1,"command":"continue"}
Old value = -1.9057374359644947
New value = -1.8236172821972838
{"action":"cmd","session":1,"command":"print this->joint_id_"}
$8 = 5
{"action":"cmd","session":1,"command":"print g_joints[this->slot_].name"}
$12 = "elbow\000\000"
I have the concrete bad store: after reprioritization, controller `joint_id_=5` still targets `slot_=5`, and slot 5 now holds `elbow`.
+            for (int i = 0; i < kNumJoints; ++i) ctl[i].bind(static_cast<std::uint32_t>(i));
/usr/bin/zsh -lc './build/armctl 20000' in ~/byteask/cppcon/demos/04-runtime-forensics
completed, all joints within soft limits

The source behind the answer

STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 Advanced Arm-based 32-bit MCUs Reference Manual (RM0090, DM00031020)
pp.613–614

Figure 169 gives an example of counter behavior when TI1FP1 polarity is inverted (same configuration as above except CC1P=1).

Retrieved with search_docs on 2026-10-26. This document lookup is separate from the recorded session above.