- 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
108 lines
3.9 KiB
Bash
Executable File
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
|