Files
Laan Tungir ac2e6347a2 v0.1.6 - Teensy 4.1 SD-card OTP pad: real implementation working on hardware
- otppad_embedded: bit-compatible port of libotppad (2386/2386 host tests pass)
- otp_pad_sd: SdFat-direct SD card pad reader (FAT-only, ASCII armor + binary .otp)
- pad_gen.ino: TRNG-sourced 1 MB pad generator using i.MX RT1062 TRNG registers
- Linker script: moved .rodata from DTCM to FLASH (EXCLUDE_FILE ed25519),
  reclaiming 124 KB DTCM, free stack 5.9 KB -> 130.9 KB
- check_stack.sh: build-time FlexRAM stack gauge, wired into build_signer.sh
- test_otp_sd.py: 8/9 hardware tests pass (ASCII + binary round-trips,
  offset advance, tamper detection; 10 KB plaintext times out on perf)
- test_classical.py: 16/16 pass with new memory layout (ed25519 OK)
- Memory evaluation document: plans/teensy41_memory_evaluation.md
2026-07-30 17:10:50 -04:00

108 lines
3.9 KiB
Bash
Executable File

#!/bin/bash
# check_stack.sh — Teensy 4.1 FlexRAM stack gauge.
#
# Computes the same ITCM/DTCM split the i.MX RT1062 boot ROM will perform, and
# fails if the resulting free stack is below a threshold. The linker cannot
# catch this because the split is computed at reset from _itcm_block_count,
# not at link time.
#
# Usage: check_stack.sh <signer.ino.elf> [min_stack_bytes]
# min_stack_bytes defaults to 16384 (16 KB).
#
# Exits 0 if the stack is above the threshold, 1 if below (with a diagnostic).
#
# The arithmetic (from imxrt1062_t41_flashmem.ld:215-217):
# itcm_banks = ceil((.text.itcm + .ARM.exidx) / 32768)
# dtcm_total = (16 - itcm_banks) * 32768
# free_stack = dtcm_total - .data - .bss
# _estack = ORIGIN(DTCM) + dtcm_total (stack grows down from here)
#
# Note: .bss here is the DTCM .bss (RAM1), NOT .bss.dma (RAM2/OCRAM). The
# .bss.dma section lives in a separate 512 KB region and does not affect the
# stack.
set -euo pipefail
ELF="${1:-}"
MIN_STACK="${2:-16384}"
if [ -z "$ELF" ] || [ ! -f "$ELF" ]; then
echo "check_stack: usage: $0 <signer.ino.elf> [min_stack_bytes]" >&2
exit 2
fi
# Locate the arm-none-eabi-size tool from the Teensy toolchain.
SIZE_BIN=""
for candidate in \
/home/user/.arduino15/packages/teensy/tools/teensy-compile/*/arm/bin/arm-none-eabi-size \
"$(dirname "$0")/../.arduino15/packages/teensy/tools/teensy-compile/*/arm/bin/arm-none-eabi-size"; do
if [ -x "$candidate" ]; then SIZE_BIN="$candidate"; break; fi
done
# Fall back to PATH
if [ -z "$SIZE_BIN" ]; then SIZE_BIN="$(command -v arm-none-eabi-size || true)"; fi
if [ -z "$SIZE_BIN" ]; then
echo "check_stack: cannot find arm-none-eabi-size" >&2
exit 2
fi
# We need per-section sizes, not the aggregate. Use objdump -h.
OBJDUMP_BIN="${SIZE_BIN%size}objdump"
# Extract section sizes (in bytes, decimal) by name.
get_section_size() {
local section="$1"
# objdump -h prints: idx Name Size VMA LMA File-off Al
"$OBJDUMP_BIN" -h "$ELF" 2>/dev/null \
| awk -v sec="$section" '$2 == sec { print strtonum("0x"$3); exit }'
}
TEXT_ITCM=$(get_section_size ".text.itcm")
ARM_EXIDX=$(get_section_size ".ARM.exidx")
DATA_SEC=$(get_section_size ".data")
BSS_SEC=$(get_section_size ".bss")
BSS_DMA=$(get_section_size ".bss.dma")
# Guard against missing sections (e.g. exidx may be 0/absent).
: "${TEXT_ITCM:=0}"
: "${ARM_EXIDX:=0}"
: "${DATA_SEC:=0}"
: "${BSS_SEC:=0}"
: "${BSS_DMA:=0}"
BANK=32768
ITCM_BYTES=$(( TEXT_ITCM + ARM_EXIDX ))
ITCM_BANKS=$(( (ITCM_BYTES + BANK - 1) / BANK ))
DTCM_TOTAL=$(( (16 - ITCM_BANKS) * BANK ))
DATA_BSS=$(( DATA_SEC + BSS_SEC ))
FREE_STACK=$(( DTCM_TOTAL - DATA_BSS ))
# Also report RAM2 (OCRAM) usage for completeness.
RAM2_TOTAL=$(( 512 * 1024 ))
RAM2_FREE=$(( RAM2_TOTAL - BSS_DMA ))
echo "=== Teensy 4.1 FlexRAM stack gauge ==="
echo " .text.itcm : $(printf '%7d' $TEXT_ITCM) bytes"
echo " .ARM.exidx : $(printf '%7d' $ARM_EXIDX) bytes"
echo " ITCM total : $(printf '%7d' $ITCM_BYTES) bytes -> $ITCM_BANKS banks ($(( ITCM_BANKS * BANK )) bytes)"
echo " .data (DTCM) : $(printf '%7d' $DATA_SEC) bytes"
echo " .bss (DTCM) : $(printf '%7d' $BSS_SEC) bytes"
echo " DTCM total : $(printf '%7d' $DTCM_TOTAL) bytes ($(( 16 - ITCM_BANKS )) banks)"
echo " data + bss : $(printf '%7d' $DATA_BSS) bytes"
echo " FREE STACK : $(printf '%7d' $FREE_STACK) bytes (threshold: $MIN_STACK)"
echo " ---"
echo " .bss.dma RAM2: $(printf '%7d' $BSS_DMA) / $RAM2_TOTAL bytes (free: $RAM2_FREE)"
if [ "$FREE_STACK" -lt "$MIN_STACK" ]; then
echo ""
echo " ❌ FAIL: free stack $FREE_STACK < threshold $MIN_STACK"
echo " The boot ROM will allocate $ITCM_BANKS ITCM banks, leaving only"
echo " $DTCM_TOTAL bytes of DTCM. .data+.bss needs $DATA_BSS bytes."
echo " Reduce ITCM (route more code to FLASH) or reduce .data/.bss"
echo " (move .rodata to FLASH)."
exit 1
fi
echo ""
echo " ✅ OK: free stack $FREE_STACK >= threshold $MIN_STACK"
exit 0