Prototyping · Study deck
Microcontroller Programming: Timing and Reliability
Digital pins now behave as expected, but sensor readings and timed work add new failure paths.
Voltage Vera is your guide for this deck.
After studying this chapter
Learning objectives
You will be able to:
- Explain: Feeding it right before a long delay() or an unbounded wait defeats the purpose, because the feed call proves nothing about whether the rest of the loop would actually have completed.
- Explain: On Cortex-M4, xPSR is the combined view of three overlapping status-register roles: the Application Program Status Register (APSR), Interrupt Program Status Register (IPSR), and Execution Program Status Register (EPSR).
- Explain: The non-blocking half instead shows the millis() test interleaving A, B, and C, so elapsed time becomes a condition to check rather than a command that halts execution.
- interpret ADC evidence
Major section
Non-Blocking Timing With millis()
While the loop is delayed, firmware cannot read a button, service a state machine, check a timeout, or publish a new sensor sample.
- The replacement pattern is to compare elapsed time.
- Responsiveness is easier to judge when the two timing models share one time axis.
- The non-blocking half instead shows the millis() test interleaving A, B, and C, so elapsed time becomes a condition to check rather than a command that halts execution.
- That contrast connects directly to the running firmware narrative: a prototype that must sample, communicate, and react should demonstrate that every duty still gets a turn within its deadline.
Major section
Interrupt Top and Bottom Halves
Interrupts are for urgent hardware events.
- An interrupt service routine pauses normal execution, runs a small handler, then returns to the main context.
- The safest beginner pattern is to set a flag in the ISR and do the real work in loop().
- IRAM_ATTR is ESP32-specific.
Major section
Watchdog Timer: A Reliability Backstop
Feeding it right before a long delay() or an unbounded wait defeats the purpose, because the feed call proves nothing about whether the rest of the loop would actually have completed.
- Interrupts and millis() scheduling keep the loop responsive to events its author anticipated.
- wdt_enable() and wdt_reset() are the classic AVR watchdog API from the AVR watchdog header.
- A watchdog only protects a loop that is already structured to return often.
Major section
Compiler And Fixed-Point Lab
More fractional bits improve resolution but reduce range.
- A compiler can schedule independent instructions, use vector instructions when the target has them, and replace a short branch with predicated work.
- None of those transformations removes the need for evidence.
- Fixed-point arithmetic makes that evidence boundary visible.
Try it: Compiler And Fixed-Point Lab in the chapter
Major section
Cortex-M core and address maps
Actual cacheability, MPU attributes, bus fabric, and external-memory support are core- and SoC-specific.
- In everyday MCU firmware the critical ranges are normally code, on-chip SRAM, peripherals, and the System Control Space.
- Memory-mapped I/O means a peripheral owns addresses just as RAM owns addresses, but reads and writes are not ordinary storage operations.
- The frame pointer is a convention, not a new architectural register.
Major section
Cortex-M status registers
On Cortex-M4, xPSR is the combined view of three overlapping status-register roles: the Application Program Status Register (APSR), Interrupt Program Status Register (IPSR), and Execution Program Status Register (EPSR).
- The arithmetic flags are easiest to separate with two examples.
- 0xFFFFFFFF + 1 produces zero, so Z=1 and C=1; interpreted as signed −1+1, it does not overflow, so V=0.
- IPSR gives exception context, not a generic interrupt-enabled flag.
Major section
Cortex-M status registers (continued)
Handler mode has a nonzero exception number; Thread mode reads zero.
- EPSR's ICI/IT fields are execution-resume state maintained by the processor around interrupted multi-cycle instructions or IT blocks.
- Application code should not treat them as spare flags.
- When a debugger shows xPSR, decode each view by its own meaning: arithmetic result in APSR, active exception in IPSR, and execution state in EPSR.
Major section
Memory Hierarchy For IoT Firmware
A design review should keep volatile working memory, immutable boot code, updateable firmware, calibration values, event logs, and high-write counters separate before selecting a device.
- Endurance is a workload calculation: a one-million-cycle cell can still fail early if firmware rewrites it many times per second without wear distribution.
- Below it, Arguments and return assigns r0-r3, while Control the call identifies r13 SP, r14 LR, and r15 PC as the registers that reconstruct execution flow.
- Their xPSR combination is a convenient snapshot, not a single undifferentiated meaning.
Deck summary
Key takeaways
While the loop is delayed, firmware cannot read a button, service a state machine, check a timeout, or publish a new sensor sample.
- Interrupts are for urgent hardware events.
- Feeding it right before a long delay() or an unbounded wait defeats the purpose, because the feed call proves nothing about whether the rest of the loop would actually have completed.
- More fractional bits improve resolution but reduce range.
- Actual cacheability, MPU attributes, bus fabric, and external-memory support are core- and SoC-specific.
Retrieval practice
Recall check 1 of 3

Voltage Vera says: answer from memory, then check your reasoning.
Q1This chapter states the LM35 sensor outputs 10 mV per degree C, and its lm35CelsiusFromVoltage() function returns voltage * 100.0. If the ADC-derived voltage is 0.250 V, what temperature does the function return, and why multiply by 100.0 rather than some other factor?
Show answer
Answer: C see answers page
Retrieval practice
Recall check 2 of 3

Voltage Vera says: answer from memory, then check your reasoning.
Q2This chapter's non-blocking timing pattern compares elapsed time using now - lastBlinkMs >= 500 rather than checking whether lastBlinkMs + 500 has passed. Per the chapter, why is the subtraction form the standard pattern?
Show answer
Answer: B The chapter states the subtraction form now - lastTime >= interval 'continues to work when millis() rolls over,' which is why it replaces a naive lastTime + interval <= now comparison.
Retrieval practice
Recall check 3 of 3

Voltage Vera says: answer from memory, then check your reasoning.
Q3A button input is configured as INPUT with no pull-up or pull-down resistor. What is the main risk when the button is not pressed?
Show answer
Answer: B GPIO input behavior is part firmware and part circuit design.
Print reference
Answers 1 of 2
Answer key.
- C · The chapter states the LM35 outputs 10 mV per degree C, so each volt of sensor output represents 100 degrees C (1 V / 0.010 V-per-degree = 100). The lm35CelsiusFromVoltage() function encodes exactly that: voltage * 100.0. At 0.250 V, the result is 25.0 degrees C, independent of the board's ADC reference voltage, which only affects the earlier raw-to-voltage step.
Print reference
Answers 2 of 2
Answer key.
- B · The chapter states the subtraction form now - lastTime >= interval 'continues to work when millis() rolls over,' which is why it replaces a naive lastTime + interval <= now comparison.
- B · GPIO input behavior is part firmware and part circuit design.