Monal Gupta
Blogs

Systems · Oct 2026 · 7 min read

What benchmarking lightweight cryptography taught me about embedded systems

Working with STM32, measuring energy, and trying to make fair comparisons taught me much more than I expected about embedded systems, experimentation, and real-world constraints.

STM32 Nucleo development board on a dark desk

The setup

I worked with an STM32 Nucleo board (STM32F401RE) and implemented a few lightweight cryptographic algorithms, including Ascon and Speck, alongside a standard like AES for comparison. My goal was to measure not just execution time, but also energy consumption, code size, and RAM usage, to get a more complete picture of how these algorithms behave on a real microcontroller.

Prerequisites

An ARM Cortex-M board, the arm-none-eabi-gcc toolchain, and a current sensor (I used an INA219) if you want energy numbers.
c
// Example: measuring cycle count for an encryption function
uint32_t start = DWT->CYCCNT;
ascon_encrypt(plaintext, ciphertext, key, nonce);
uint32_t cycles = DWT->CYCCNT - start;

What I measured

  • Cycles per byte — raw speed on the chip
  • Energy per encryption — using a current sensor on the supply line
  • Code size (flash) and peak RAM usage

What went wrong

At first, my results looked almost too good to be true. After digging deeper, I realized I had made a few classic mistakes: compiler optimizations were eliminating parts of the code, I wasn't accounting for initialization time, and my measurements weren't consistent across different build configurations. It was a good reminder that benchmarking is hard, and small details can completely change the results.

Watch out

With -O2 or higher, the compiler may remove an encryption call whose output is never used. Mark buffers volatile or consume the result.
"The biggest lesson was that benchmarking is less about running code and more about controlling for everything else."

The results

AlgorithmCycles / byteFlash (KB)RAM (B)Energy (µJ)
Ascon-1281423.13204.8
Speck-64/128961.41803.2
AES-1281886.25606.9
Table 1. Averages over 1,000 runs, 64-byte messages, -O2, 84 MHz. (Example numbers.)

What I learned

Through this process, I gained a much deeper appreciation for the constraints of embedded systems. Memory, power, and performance are always trade-offs, and what looks good in theory doesn't always translate to real hardware. I also learned the importance of building a rigorous and repeatable benchmarking setup, from controlling compiler flags to measuring actual energy consumption using a current sensor.

Microcontroller board wired to a current sensor display
Figure 1.STM32 Nucleo board connected to a current sensor for measuring energy consumption during encryption operations.

My benchmarking checklist

  1. Fix compiler flags and record them with every result
  2. Warm up and exclude initialization time
  3. Repeat many runs and report averages and variance
  4. Verify outputs so the compiler can't skip work

Tip

Keep a small script that rebuilds and reruns every configuration — it turns a day of manual testing into one command.

What I'd do differently

If I were to do this again, I'd spend more time upfront on the benchmarking methodology, including defining clear metrics and running more iterations to account for variance. I'd also like to explore more algorithms and test on a lower-power STM32 board to see how the results change in an even more constrained environment.

References

  1. NIST Lightweight Cryptography Standardization — the competition Ascon won
  2. Ascon specification — official algorithm site
  3. STM32F401RE reference manual

Written by Monal Gupta