Starter Kit: WCET-Aware Embedded Project Template (Makefile, Tests, Integration Hooks)
Hook: Is your team scrambling to show credible timing data for real-time features? Between fragmented test harnesses, inconsistent timing measurements, and new verification pipelines (VectorCAST + RocqStat on the rise in 2026), you need a repeatable, WCET-aware project skeleton that produces actionable timing reports for CI and verification tools.
Why this starter kit matters in 2026
Late 2025 and early 2026 saw a clear consolidation in timing analysis tooling: Vector Informatik's acquisition of StatInf's RocqStat has accelerated the drive toward unified verification + timing toolchains that combine functional tests and WCET insights. Teams preparing for VectorCAST + RocqStat pipelines must deliver consistent timing measurements, traceable test IDs, and machine-readable timing exports for automated analysis.
"Timing safety is becoming a critical..." — coverage of Vector's RocqStat acquisition and integration plans signals a shift toward integrated timing verification workflows (Automotive World, Jan 16 2026).
What you get from this article (and the local starter generator)
- A compact, architecture-aware project skeleton you can generate locally using the included bootstrap script.
- A Makefile with targets for build, unit tests, timing runs, and report export.
- Instrumentation hooks for cycle-accurate timers (Cortex-M DWT) and host-mode fallbacks (clock_gettime).
- Example tests designed to be VectorCAST-friendly and to produce CSV/JSON timing outputs for RocqStat ingestion.
- CI integration example (GitHub Actions) that collects artifacts and can call downstream verification steps.
Quick start: create the starter locally (one command)
Rather than rely on a hosted repository, use this small bootstrap to create the starter project in your workspace. Save the script below as bootstrap-wcet-starter.sh, make it executable, and run it.
#!/usr/bin/env bash
set -e
mkdir -p wcet-starter/{src,tests,tools,ci}
cat > wcet-starter/Makefile <<'EOF'
# Simple WCET-aware Makefile
CC ?= arm-none-eabi-gcc
CFLAGS ?= -Os -g -mcpu=cortex-m4 -mthumb -Wall
LDFLAGS ?= -Tstm32_flash.ld
BUILD_DIR = build
SRC = $(wildcard src/*.c)
OBJ = $(patsubst src/%.c,$(BUILD_DIR)/%.o,$(SRC))
.PHONY: all clean test timing export
all: $(BUILD_DIR)/app.elf
$(BUILD_DIR)/%.o: src/%.c | $(BUILD_DIR)
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/app.elf: $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -o $@ $(LDFLAGS)
test: all
./tools/run_tests.sh --runner host --report $(BUILD_DIR)/test_report.json
timing: all
./tools/run_timing.sh --report $(BUILD_DIR)/timing.csv
export: timing
./tools/export_for_rocqstat.sh $(BUILD_DIR)/timing.csv $(BUILD_DIR)/rocqstat_import.json
clean:
rm -rf $(BUILD_DIR)
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
EOF
cat > wcet-starter/src/timer.h <<'EOF'
#ifndef TIMER_H
#define TIMER_H
#include
void timer_init(void);
uint64_t timer_now_cycles(void);
uint64_t timer_freq_hz(void);
#endif
EOF
cat > wcet-starter/src/timer.c <<'EOF'
#include "timer.h"
#ifdef HOST
#include
void timer_init(void) { }
uint64_t timer_now_cycles(void) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return (uint64_t)t.tv_sec * 1000000000ULL + t.tv_nsec; // ns
}
uint64_t timer_freq_hz(void) { return 1000000000ULL; }
#else
/* Cortex-M DWT-based implementation (cycles) */
#include
#define DWT_CTRL (*(volatile uint32_t*)0xE0001000)
#define DWT_CYCCNT (*(volatile uint32_t*)0xE0001004)
#define DEMCR (*(volatile uint32_t*)0xE000EDFC)
void timer_init(void) {
DEMCR |= (1 << 24); // TRCENA
DWT_CYCCNT = 0;
DWT_CTRL |= 1; // enable
}
uint64_t timer_now_cycles(void) { return (uint64_t)DWT_CYCCNT; }
uint64_t timer_freq_hz(void) { return 48000000ULL; } // adjust per MCU
#endif
EOF
cat > wcet-starter/src/main.c <<'EOF'
#include "timer.h"
#include
int workload(int n) {
volatile int sum = 0;
for (int i = 0; i < n; ++i) sum += i;
return sum;
}
int main(void) {
timer_init();
uint64_t t0 = timer_now_cycles();
workload(1000);
uint64_t t1 = timer_now_cycles();
uint64_t freq = timer_freq_hz();
printf("TIMING,workload,cycles,%llu,freq,%llu\n", (unsigned long long)(t1 - t0), (unsigned long long)freq);
return 0;
}
EOF
cat > wcet-starter/tools/run_timing.sh <<'EOF'
#!/usr/bin/env bash
set -e
REPORT=${2:-build/timing.csv}
# Run the target binary in host mode or on-target via OpenOCD/serial
# This script demonstrates host-mode sampling and CSV output
./build/app.elf | awk -F, '/^TIMING/ { print $2","$3","$4 }' > $REPORT
EOF
chmod +x wcet-starter/tools/run_timing.sh
cat > wcet-starter/tools/export_for_rocqstat.sh <<'EOF'
#!/usr/bin/env bash
CSV=$1
OUT=$2
# Convert simple CSV of "workload,cycles,freq" to a minimal JSON that downstream tools can read
awk -F"," 'BEGIN{print "["} NR>1{print ","} {printf " {'test':'%s','cycles':%s,'freq':%s}", $1, $2, $4} END{print "\n]"}' "$CSV" > "$OUT"
EOF
chmod +x wcet-starter/tools/export_for_rocqstat.sh
cat > wcet-starter/tools/run_tests.sh <<'EOF'
#!/usr/bin/env bash
# Very small test runner: runs app and captures timing; extend for VectorCAST harness
./build/app.elf > ${2:-build/test_report.json}
EOF
chmod +x wcet-starter/tools/run_tests.sh
echo "Created wcet-starter/"
Related Reading
- Eco-Friendly Gift Ideas: Upcycling Toy Packaging into Candle Displays
- How to Build a Portable Switch 2 Arcade Box: Storage, Power, and Mod Tips
- How to Use New Social Features (Cashtags, LIVE badges) to Land Sponsorships and Partnerships
- From Notebook to Necklace: How Petite Luxury Items Become Viral Fashion Statements
- When 3D Scanning Meets Art Reproduction: Use Cases and Ethical Pitfalls