About me
Blog
Europe/Berlin
--:--:--

Embedded Security as a Future Topic (Secure Boot, TrustZone)

June 11, 2024Threat modeling, secure boot chains and lifecycle updates for device fleets. Monorepo vs. multirepo, vendor drops and tooling for release traces. Unit tests (host/target), mocks/stubs, HIL and measuring release quality. When to use which protocol? Edge-to-cloud paths with practical patterns and pitfalls.
Anyone building sensor devices faces two challenges: security (ensuring only your code runs and data is authentic) and signal quality (ensuring the data is accurate). Both are interrelated: a clean secure boot chain protects firmware and keys; a clean ADC/DAC chain protects against aliasing interference, drift and measurement chaos. In this article, we connect both topics in a practical way -- with STM32, Arduino and ESP32 examples.
ADC (Analog-to-Digital) converts voltages into numbers; DAC (Digital-to-Analog) generates test signals, drives actuators or feeds HIL rigs. Key parameters:
  • Resolution (bits): determines the LSB size (Vref/2^N).
  • Sampling rate fs: determines how fast you measure (Nyquist: >= 2*fmax of the signal).
  • Quantization/ENOB: real effective bits < datasheet bits; can be improved via oversampling & averaging (e.g. +1 bit at 4x, +2 bits at 16x). (Silicon Labs, Texas Instruments)
TI/ADI articles and app notes -- linked below -- provide design guides for filters and oversampling in greater depth. (Texas Instruments, Analog Devices)
Aliasing turns high frequencies into seemingly lower ones -- fatal for sensor applications. Solution: an analog low-pass filter before the ADC, typically 1st or 2nd order (RC) for "normal cases", active Bessel/Butterworth for more demanding applications (clean phase response or steep roll-off, respectively). As a starting point: fc ~ 0.4...0.45*fs (for pure baseband signals), more margin in harsh interference environments. TI/ADI provide concrete calculation methods and example circuits. (Texas Instruments, Analog Devices) Practical pitfalls:
  • The input source must charge the ADC's sample-and-hold capacitor quickly -- high source impedance leads to erroneous samples. Good practical explanations are available on this topic. (Embedded Related)
  • RC filter close to the pin, star grounding, short traces, dedicated VDDA/VSSA (decoupling!). (EDN)

Rule of thumb: 4x samples yields ~+0.5 bit ENOB; 16x yields ~+2 bits. Sufficient white noise (also dither) and a stable Vref are important. Properly implemented, you gain resolution without new hardware. Step-by-step guides are available from Silicon Labs, TI and classic embedded articles. (Silicon Labs, Texas Instruments, Embedded)
Setup concept: Timer triggers ADC sampling; DMA (circular) writes samples into a ring buffer -- minimal CPU load, low jitter.
C
// Global buffers
#define ADC_BUF 1024
volatile uint16_t adc_buf[ADC_BUF];

// Init: ADC (Scan, Continuous off), external trigger e.g. TIM3_TRGO
// DMA: Peripheral->Memory, Half/Full Transfer IRQ, Circular
// Timer: Upcounter, Update Event as TRGO, Rate = desired fs

void start_adc_dma(void) {
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_BUF);
    HAL_TIM_Base_Start(&htim3); // provides TRGO to ADC
}

// Callbacks: deterministic processing in blocks
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) {
    // process adc_buf[0 .. ADC_BUF/2-1]
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
    // process adc_buf[ADC_BUF/2 .. ADC_BUF-1]
}
Why this approach? Timer trigger provides constant fs, DMA double buffer eliminates gaps and ISR storms. ST wiki/app notes introduce the ADC+DMA/TIM topic; the DMA introduction summarizes transfer modes well. (STMicroelectronics, STMicroelectronics) Tip: On CM7 cores (e.g. STM32H7), watch out for cache coherency (invalidate D-Cache or place DMA buffer in a non-cacheable section). ST documentation and practical guides show common pitfalls and workarounds. (STMicroelectronics, skybluetrades.net)
Cpp
const int PIN = A0;
const float VREF = 5.0; // or 3.3V -- depends on board/analogReference()

void setup() {
  Serial.begin(115200);
}

void loop() {
  const int N = 32;          // simple averaging
  long acc = 0;
  for (int i=0; i<N; ++i) acc += analogRead(PIN);
  float avg = acc / float(N);               // 10-bit -> 0..1023
  float volt = avg * (VREF / 1023.0);
  Serial.println(volt);
}
Additionally: set analogReference() appropriately (DEFAULT/EXTERNAL/INTERNAL depending on board). The official documentation describes the details of analogRead() behavior. (docs.arduino.cc, Arduino)
The ESP32 has two 8-bit DAC channels (GPIO25/GPIO26). For simple stimuli the DAC driver is sufficient; for continuous signals (sawtooth/sine) use I2S "built-in DAC mode" with buffering. (Espressif Docs)
C
#include "driver/dac.h"
void app_main(void) {
    dac_output_enable(DAC_CHANNEL_1); // GPIO25
    for (;;) {
        for (int v=0; v<256; ++v) {
            dac_output_voltage(DAC_CHANNEL_1, v); // 0..255 -> 0..Vref
        }
    }
}
Practical use: This allows you to feed the STM32 ADC reproducibly -- ideal for HIL tests. (More on HIL principles in common overviews.) (Ansys)
  • Reference voltage (Vref): internal vs. external, temperature drift/noise; decouple separately, short return path to ADC ground. Poor Vref ruins any calibration; app notes on oversampling and practical articles show effects and countermeasures. (Silicon Labs, EDN)
  • Layout: Separate AGND/DGND sensibly, star topology, no return currents crossing the measurement front; filter close to the pin. (EDN)
  • Oversampling/Averaging: Sample N times, use averaged values; for high dynamics, use adaptive averaging. Formal bit gains as described above. (Silicon Labs)
  • DMA double buffer: deterministic blocks; with caches: use non-cacheable regions. (STMicroelectronics)
  • Calibration: 2-point (offset/gain), characterize across temperature.
  • Anti-aliasing: Bessel for time-domain signals (clean phase), Butterworth for spectral separation; TI/ADI provide concrete dimensioning. (Texas Instruments, Analog Devices)

Secure boot chain: Root of Trust (ROM/immutable boot), signature verification (ECDSA/RSA), rollback protection (monotonic counter), secure OTA update path. For STM32, SBSFU (Secure Boot & Secure Firmware Update, including Secure Engine/memory mapping) exists, as well as TrustZone-based solutions with TF-M (Trusted Firmware-M) as the secure world reference. (STMicroelectronics, trustedfirmware-m.readthedocs.io) Open-source bootloader: MCUboot (signing via imgtool, A/B slots, recovery). Integrated into Zephyr and other ecosystems. (mcuboot, Zephyr Project Documentation) TrustZone-M isolates "Secure" (crypto, keys, update agent, secure storage) from "Non-Secure" (app/peripherals). ARM documentation explains the separation and calls between the two worlds. TF-M provides PSA-compliant secure services (Crypto, Attestation, Protected Storage) along with update API guidelines for the entire lifecycle. (Arm Developer, trustedfirmware-m.readthedocs.io, arm-software.github.io) Firmware resilience: NIST SP 800-193 defines the principles of Protect-Detect-Recover -- relevant for embedded/IoT as well (adapted to resource constraints). Keep these three pillars in mind during design and operation. (NIST Publications)
  • MQTT (TCP/TLS, Pub/Sub): excellent for telemetry, "last will", QoS 0/1/2; ideal for gateway/cloud integration, v5 brings better error reporting and features. (OASIS Open Docs, mqtt.org)
  • CoAP (UDP/DTLS, REST-like): lightweight, Observe/Blockwise; well-suited for constrained networks, IPv6/6LoWPAN. (IETF Datatracker)
  • HTTP/2/3: updates/downloads, broad infrastructure -- with TLS/mTLS and resume mechanisms.
Pattern: Device -> (optional) Gateway -> Cloud. mTLS for device identity, backoff/store-and-forward when offline, don't forget time base (SNTP) for certificate validity. (CoAP is even being used for PKI flows -- CMP via CoAP). (RFC Editor)
  • Monorepo vs. multirepo: Monorepo simplifies cross-cutting changes, multirepo isolates components/products. There is no dogma -- tooling and team size decide. Martin Fowler examines the trade-offs and branching patterns. (martinfowler.com)
  • Vendor drops (HAL/SDK): pull in as submodules/mirrors with immutable tags; reference changelogs; no manual patch mixing in the project root.
  • Release traces: build SBOMs (e.g. CycloneDX) and provenance (SLSA) directly into the pipeline -- artifacts can later be traced back to sources/builds unambiguously. Invaluable for IoT fleets (forensics, CVE matching). (CycloneDX, GitHub, SLSA)

  • Unit tests (host): e.g. Unity/Ceedling -- a lean ANSI C framework, ideal for driver logic (with CMock for HAL stubs). (Throw The Switch, GitHub) Mini example (scaling):
    C
    // scales raw ADC value (0..4095) to volts (Vref=3.3)
    float adc_to_volt(uint16_t raw) { return (3.3f * raw) / 4095.0f; }
    
    TEST(AdcScale, ConvertsCorrectly) {
      TEST_ASSERT_FLOAT_WITHIN(0.005f, 1.650f, adc_to_volt(2048));
    }
    
  • Unit tests (target): small test suite on-target (e.g. via semihosting/serial) to catch compiler/ABI/linker effects.
  • HIL: real controller hardware ↔ simulated environment (ESP32 DAC feeds STM32 ADC; digital I/Os drive simulated sensors). Critical for timing/I/O paths and safety functions (e.g. secure update recovery). (Ansys)
  • Release metrics: code coverage (host), on-target smoke tests, latency/jitter measurements of the DMA chain, ENOB/noise floor, update MTTR (recovery time per SP 800-193). (NIST Publications)

  1. Threat model: Which attackers? (Physical/remote). Which assets? (Keys, IP, cloud credentials, sensor integrity).
  2. Harden the boot chain: ROM root, mandatory signatures, rollback protection, secure storage. SBSFU/TF-M/MCUboot are battle-tested. (STMicroelectronics, mcuboot)
  3. Isolation: TrustZone-M for crypto/keys/update agent. (Arm Developer)
  4. Lifecycle updates: consider standardized PSA Firmware Update API concepts; clean, repeatable process -- before series production. (arm-software.github.io)
  5. Transports: MQTT/CoAP with (m)TLS/DTLS, device identity via mTLS, robust retry/backoff, clock sync. (OASIS Open Docs, IETF Datatracker)
  6. Supply chain: SBOM + SLSA provenance per release. (CycloneDX, SLSA)

Secure embedded products are created when the secure boot chain and the signal chain are taken equally seriously: one strand protects who is allowed to execute code, the other ensures what is being measured. With ADC+DMA, anti-aliasing and oversampling you get the maximum from your sensors; with TrustZone, SBSFU/TF-M/MCUboot and a clean OTA strategy, device fleets remain reliable -- and secure -- for years.

Bonus idea for the lab: Use the ESP32 DAC as a programmable stimulus, feed it into the STM32 ADC (DMA, timer-triggered) and verify filter/scaling in a HIL loop -- including automated Unity tests for signal processing. This way you can test security-relevant update recovery paths and measure real ENOB at the same time. (Espressif Docs, STMicroelectronics, Throw The Switch)