Support for NXP T1040 RDB

pull/729/head
David Garske 2026-03-18 11:15:07 -07:00 committed by Daniele Lacamera
parent 7458d6dbc2
commit a56c70e90a
21 changed files with 5242 additions and 3390 deletions

View File

@ -270,6 +270,9 @@ endif
ifeq ($(TARGET),nxp_t1024)
MAIN_TARGET:=factory_wstage1.bin
endif
ifeq ($(TARGET),nxp_t1040)
MAIN_TARGET:=factory_wstage1.bin
endif
ifeq ($(TARGET),sama5d3)
MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin

View File

@ -695,7 +695,7 @@ ifeq ($(ARCH),PPC)
# Target-specific CPU flags
ifeq ($(TARGET),nxp_t2080)
CFLAGS+=-mcpu=e6500 -mno-altivec -mbss-plt
else ifeq ($(TARGET),nxp_t1024)
else ifneq ($(filter nxp_t1024 nxp_t1040,$(TARGET)),)
CFLAGS+=-mcpu=e5500
endif
@ -1034,8 +1034,8 @@ ifeq ($(ARCH),ARM_BE)
endif
endif
ifeq ($(TARGET),nxp_t1024)
# Power PC big endian
ifneq ($(filter nxp_t1024 nxp_t1040,$(TARGET)),)
# Power PC big endian (e5500 core, T1024 2-core / T1040 4-core)
ARCH_FLAGS=-mhard-float -mcpu=e5500
CFLAGS+=$(ARCH_FLAGS)
BIG_ENDIAN=1

View File

@ -0,0 +1,67 @@
# NXP QorIQ T1040 (4 core)
ARCH=PPC
TARGET=nxp_t1040
SIGN?=ECC384
HASH?=SHA384
IMAGE_HEADER_SIZE?=512
DEBUG?=0
DEBUG_UART?=1
VTOR?=1
CORTEX_M0?=0
NO_ASM?=0
EXT_FLASH?=0
SPI_FLASH?=0
NO_XIP?=0
UART_FLASH?=0
ALLOW_DOWNGRADE?=0
NVM_FLASH_WRITEONCE?=0
WOLFBOOT_VERSION?=0
NO_MPU?=0
SPMATH?=0
SPMATHALL?=1
RAM_CODE?=0
DUALBANK_SWAP?=0
WOLFTPM?=0
ELF?=1
DEBUG_ELF=0
# NOR Base Address (128MB NOR at 0xE8000000 - 0xEFFFFFFF)
ARCH_FLASH_OFFSET?=0xE8000000
# Flash Sector Size (128KB)
WOLFBOOT_SECTOR_SIZE=0x20000
# wolfBoot start address (same as T1024 - NOR top is 0xEFFFFFFF)
WOLFBOOT_ORIGIN=0xEFF40000
# wolfBoot partition size (custom)
BOOTLOADER_PARTITION_SIZE=0xC0000
# Application Partition Size (15MB)
WOLFBOOT_PARTITION_SIZE?=0xF00000
# Location in Flash for Application Partition
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xEE000000
# Load Partition to RAM Address
WOLFBOOT_LOAD_ADDRESS?=0x70000000
# Location in Flash for Update Partition
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xEEF00000
# Location of temporary sector used during updates
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xE80F0000
# Stage 1 loader settings (16KB)
WOLFBOOT_STAGE1_SIZE=0x4000
# Location in Flash for stage 1 loader (XIP from boot ROM)
WOLFBOOT_STAGE1_FLASH_ADDR=0xEFFFC000
# Address in RAM to load wolfBoot (end of DDR at 2GB-1MB for 32-bit addressing)
WOLFBOOT_STAGE1_LOAD_ADDR=0x7FF00000
# DTS (Device Tree)
WOLFBOOT_DTS_BOOT_ADDRESS?=0xE8800000
WOLFBOOT_DTS_UPDATE_ADDRESS?=0xE8820000
# DTS Load to RAM Address
WOLFBOOT_LOAD_DTS_ADDRESS?=0x7F100000
# Load to RAM before hash and verify
CFLAGS_EXTRA+=-DWOLFBOOT_USE_RAMBOOT

View File

@ -28,7 +28,7 @@ This README describes configuration of supported targets.
* [NXP MCXN947](#nxp-mcxn947)
* [NXP S32K1XX](#nxp-s32k1xx)
* [NXP P1021 PPC](#nxp-qoriq-p1021-ppc)
* [NXP T1024 PPC](#nxp-qoriq-t1024-ppc)
* [NXP T10xx PPC (T1024 / T1040)](#nxp-qoriq-t10xx-ppc-t1024--t1040)
* [NXP T2080 PPC](#nxp-qoriq-t2080-ppc)
* [Qemu x86-64 UEFI](#qemu-x86-64-uefi)
* [Raspberry Pi pico 2 (rp2350)](#raspberry-pi-pico-rp2350)
@ -3714,13 +3714,29 @@ make factory_wstage1.bin
```
## NXP QorIQ T1024 PPC
## NXP QorIQ T10xx PPC (T1024 / T1040)
The NXP QorIQ T1024 is a two core 64-bit PPC e5500 based processor at 1400MHz. Each core has 256KB L2 cache.
The NXP QorIQ T1024 and T1040 are 64-bit PPC e5500 based processors at 1400MHz. Each core has 256KB L2 cache. Both share the same HAL code (`hal/nxp_t10xx.c`) with `#ifdef` guards for differences.
Board: T1024RDB
Board rev: 0x3031
CPLD ver: 0x42
| Feature | T1024 | T1040 |
| -------------- | ---------------------- | ---------------------------- |
| Cores | 2 | 4 |
| SVR | 0x8548_0010 | 0x8528_0011 |
| DDR4 | 2 GB | 8 GB (Micron 18ASF1G72AZ) |
| NOR Flash | 64 MB at 0xEC000000 | 128 MB at 0xE8000000 |
| Flash TLB | 64 MB page | 256 MB page (no 128M on e5500) |
| PCIe | 3 controllers | 3 controllers |
| Ethernet | 4 mEMAC | 5 DTSEC |
| QE FW address | 0xEFE00000 | 0xEFF10000 |
| Board | T1024RDB | T1040D4RDB |
| Config | `nxp-t1024.config` | `nxp-t1040.config` |
Both use the same wolfBoot partition layout at the top of flash — addresses
differ only because the NOR base differs (64MB vs 128MB NOR).
### T1024 Board Info
Board: T1024RDB, Board rev: 0x3031, CPLD ver: 0x42
T1024E, Version: 1.0, (0x8548_0010)
e5500, Version: 2.1, (0x8024_1021)
@ -3731,9 +3747,9 @@ Reset Configuration Word (RCW):
00000020: 00000000 00000000 60000000 00036800
00000030: 00000100 484a5808 00000000 00000006
Flash is NOR on IFC CS0 (0x0_EC00_0000) 64MB (default).
Flash is NOR on IFC CS0 (0x0_EC00_0000) 64MB.
Default NOR Flash Memory Layout (64MB) (128KB block, 1K page)
#### T1024 NOR Flash Layout (64MB, 128KB block)
| Description | Address | Size |
| ----------------- | ---------- | ------------------- |
@ -3743,33 +3759,192 @@ Default NOR Flash Memory Layout (64MB) (128KB block, 1K page)
| Free | 0xEC100000 | 0x00700000 ( 7 MB) |
| FDT (Primary) | 0xEC800000 | 0x00020000 (128 KB) |
| FDT (Update) | 0xEC820000 | 0x00020000 (128 KB) |
| Free | 0xEC840000 | 0x008A0000 ( 8MB) |
| Ethenet Config | 0xED0E0000 | 0x00000400 ( 1 KB) |
| Free | 0xEC840000 | 0x008A0000 ( 8 MB) |
| Ethernet Config | 0xED0E0000 | 0x00000400 ( 1 KB) |
| Free | 0xED100000 | 0x00F00000 ( 15 MB) |
| Application (OS) | 0xEE000000 | 0x00F00000 ( 15 MB) |
| Update (OS) | 0xEEF00000 | 0x00F00000 ( 15 MB) |
| QUICC | 0xEFE00000 | 0x00100000 ( 1 MB) |
| QUICC (QE) | 0xEFE00000 | 0x00100000 ( 1 MB) |
| DPAA (FMAN) | 0xEFF00000 | 0x00020000 (128 KB) |
| wolfBoot | 0xEFF40000 | 0x000BC000 (752 KB) |
| wolfBoot Stage 1 | 0xEFFFC000 | 0x00004000 ( 16 KB) |
QE: uploading microcode 'Microcode for T1024 r1.0' version 0.0.1
### T1040 Board Info
DDR4 2GB
Board: T1040D4RDB, Board ID: 0x1130013, CPLD PLD ver: 0x13
### Building wolfBoot for NXP T1024 PPC
T1040E, Version: 1.1, (0x8528_0011)
e5500, Version: 2.1, (0x8024_1021)
Reset Configuration Word (RCW):
00000000: 0c18000e 0e000000 00000000 00000000
00000010: 66000002 40000002 ec027000 01000000
00000020: 00000000 00000000 00000000 00030810
00000030: 00000000 0342580f 00000000 00000000
Flash is NOR on IFC CS0 (0x0_E800_0000) 128MB (Micron JS28F00AM29EWHA, 16-bit, AMD CFI).
#### T1040 NOR Flash Layout (128MB, 128KB block)
| Description | Address | Size |
| ----------------- | ---------- | -------------------- |
| RCW | 0xE8000000 | 0x00020000 (128 KB) |
| Free | 0xE8020000 | 0x000D0000 (832 KB) |
| Swap Sector | 0xE80F0000 | 0x00010000 ( 64 KB) |
| Free | 0xE8100000 | 0x00700000 ( 7 MB) |
| FDT (Primary) | 0xE8800000 | 0x00020000 (128 KB) |
| FDT (Update) | 0xE8820000 | 0x00020000 (128 KB) |
| Free | 0xE8840000 | 0x057C0000 ( 87 MB) |
| Application (OS) | 0xEE000000 | 0x00F00000 ( 15 MB) |
| Update (OS) | 0xEEF00000 | 0x00F00000 ( 15 MB) |
| Free | 0xEFE00000 | 0x00100000 ( 1 MB) |
| DPAA (FMAN) | 0xEFF00000 | 0x00010000 ( 64 KB) |
| QUICC (QE) | 0xEFF10000 | 0x00010000 ( 64 KB) |
| Free | 0xEFF20000 | 0x00020000 (128 KB) |
| wolfBoot | 0xEFF40000 | 0x000BC000 (752 KB) |
| wolfBoot Stage 1 | 0xEFFFC000 | 0x00004000 ( 16 KB) |
Note: On T1040, FMAN and QE firmware share the same 128KB NOR erase sector
(0xEFF00000-0xEFF1FFFF). They must be programmed together in a single
erase/write operation.
### Design
Both T1024 and T1040 use a two-stage boot. Stage1 runs XIP from NOR flash,
initializes DDR, and copies wolfBoot to DDR for execution.
#### Boot Sequence
```
Reset vector (0xEFFFFFFC) -> Stage1 bootstrap TLB (0xEFFFF000)
-> Stage1 loader XIP from flash (0xEFFFC000)
-> hal_early_init: DDR controller init
-> boot_entry_C: copies wolfBoot .data/.bss to DDR
-> Copies wolfBoot binary to DDR (0x7FF00000)
-> Jumps to wolfBoot
-> wolfBoot (running from DDR at 0x7FF00000)
-> LAW/TLB init, UART, LIODN, IFC, CPLD, PCIe, QE, FMAN, multi-core
-> Verify + load application ELF to 0x70000000
-> FDT fixup, do_boot -> application entry
```
#### Memory Hierarchy
```
CPU Core (e5500) -> L1 (32KB I + 32KB D) -> L2 (256KB per core)
-> CoreNet Fabric -> CPC (256KB, SRAM or cache)
-> DDR Controller -> DDR4
-> IFC Controller -> NOR Flash
```
#### Memory Map
| Region | Virtual Address | Physical Address | Size | Notes |
| ---------------- | --------------- | ------------------ | ------ | --------------------------- |
| DDR | 0x00000000 | 0x00000000 | 2/8 GB | T1024: 2GB, T1040: 8GB |
| CPC SRAM | 0xFDFE0000 | 0xFDFE0000 | 256 KB | Initial stack (stage1) |
| L1 Locked DCache | 0xFDFC0000 | 0xFDFC0000 | 16 KB | Stage1 stack before DDR |
| NOR Flash | 0xE8/EC000000 | 0x0F_E8/EC000000 | 64/128 MB | T1024: EC, T1040: E8 |
| CCSRBAR | 0xFE000000 | 0x0F_FE000000 | 16 MB | Peripheral registers |
Note: Stage1 uses 32-bit physical addresses (PHYS_HIGH=0x0). wolfBoot main
relocates to 36-bit physical addresses (PHYS_HIGH=0xF) matching the hardware
default bus routing.
#### TLB Entries (MMU TLB1)
Configured by `boot_ppc_start.S` during stage1:
| Entry | Virtual Address | Physical Address | Size | Attributes | Purpose |
| ----- | ---------------- | ----------------- | ------ | ---------- | ------------------ |
| 0 | 0xFFFFF000 | 0xFFFFF000 | 4 KB | I, SX/SR | Boot ROM |
| 1 | 0xFE000000 | 0xFE000000 | 16 MB | I\|G, All | CCSRBAR |
| 2 | FLASH_BASE_ADDR | FLASH_BASE_ADDR | 64/256 MB | W\|G, All | NOR Flash (XIP) |
| 9 | 0xFDFE0000 | 0xFDFE0000 | 256 KB | M, All | CPC SRAM |
| 12 | 0x00000000 | 0x00000000 | 2 GB | M, All | DDR |
The e5500 supports a 2GB MMU page size, so a single TLB entry covers the
low 2GB of DDR. Larger DDR (T1040's 8GB) is accessible via LAW but only the
first 2GB is mapped in the 32-bit effective address space.
T1024 uses 64MB flash TLB page (matching its 64MB NOR). T1040 uses 256MB
page because e5500 has no 128MB page size (jumps 64M to 256M). The 128MB
over-map is harmless as the extra region has no LAW target.
#### LAW Entries (Local Access Windows)
**Stage1 (assembly):**
| Index | Base Address | Size | Target | Purpose |
| ----- | ---------------- | ------ | ------------- | -------------------- |
| 0 | 0xFE000000 | 16 MB | CoreNet | CCSRBAR routing |
| 1 | FLASH_BASE_ADDR | 64/128 MB | IFC | NOR Flash |
| 2 | 0xFDFE0000 | 256 KB | DDR_1 | CPC SRAM routing |
**wolfBoot main (C code, law_init):**
| Index | Base Address | Size | Target | Purpose |
| ----- | ------------ | ------ | ------------- | -------------------- |
| 3 | BMAN_BASE | 32 MB | BMAN | Buffer Manager |
| 4 | QMAN_BASE | 32 MB | QMAN | Queue Manager |
| 5 | DCSR_BASE | 4 MB | DCSR | Debug Control/Status |
| 15 | 0x00000000 | 2/8 GB | DDR_1 | Main DDR memory |
#### Cold Boot Stack
Stage1 uses L1 locked data cache (16KB at 0xFDFC0000) as the initial stack.
`dcbz` allocates cache lines without bus reads; `dcbtls` locks them to prevent
eviction. This provides a core-local stack before DDR is available.
After DDR init in `hal_early_init()`, the CPC is configured as 256KB SRAM for
general use. wolfBoot main runs with its stack in DDR.
#### DDR Errata
- **A-008378** (T1024/T1040): Set DEBUG_29[8:11]=0x9 before DDR enable
- **A-009942** (T1040 only): Adjust CPO setting after DDR training completes
- **A-008109** (T1024 only): DDR_SLOW mode and debug register adjustments
#### Multi-Core
T1024 has 2 cores; T1040 has 4 cores. The primary core (core 0) completes all
initialization. Secondary cores spin on a spin-table in DDR, waiting for a
non-zero entry point written by the OS. The boot page is at 0x7FFFF000.
#### UART
DUART0 at CCSRBAR + 0x11C500 (0xFE11C500), 115200 baud, 8N1.
Both RDB boards use UART0 on the front-panel micro-USB connector.
#### Lauterbach TRACE32 Scripts
Debugging scripts are in `tools/scripts/nxp_t1040/`:
- **t1040_flash.cmm** — Flash programming using CPC SRAM as target buffer.
Programs RCW, FMAN+QE (combined), wolfBoot, stage1, and test application.
Also supports full backup/restore of the 128MB NOR.
- **t1040_debug.cmm** — Debug session setup. Configures TLB/LAW for debugger
access, loads wolfBoot + stage1 + test-app ELF symbols, and sets breakpoints.
Supports source-level debugging with STRIPPART for path resolution.
The debug script sets high TLB1 entries (10-13) so they do not conflict with
the boot_ppc_start.S entries (0-9, 12). The e5500 has only 2 on-chip
instruction breakpoints.
### Building
By default wolfBoot will use `powerpc-linux-gnu-` cross-compiler prefix. These tools can be installed with the Debian package `gcc-powerpc-linux-gnu` (`sudo apt install gcc-powerpc-linux-gnu`).
The `make` creates a `factory_stage1.bin` image that can be programmed at `0xEC000000`
```
cp ./config/examples/nxp-t1024.config .config
cp ./config/examples/nxp-t1024.config .config # T1024
cp ./config/examples/nxp-t1040.config .config # T1040
make clean
make keytools
make
```
The `make` creates a `factory_wstage1.bin` image. For T1024 it is programmed at `0xEC000000`; for T1040 at `0xE8000000`.
Or each `make` component can be manually built using:
```
@ -3780,6 +3955,19 @@ make test-app/image_v1_signed.bin
If getting errors with keystore then you can reset things using `make distclean`.
Use `V=1` to show verbose output for build steps.
Use `DEBUG=1` to enable debug symbols.
The first stage loader must fit into 16KB. To build stage1 in release and wolfBoot with debug symbols:
```
make clean
make stage1
make DEBUG=1 wolfboot.bin
make DEBUG=1 test-app/image_v1_signed.bin
make factory_wstage1.bin
```
### Signing Custom application
```
@ -3788,10 +3976,12 @@ If getting errors with keystore then you can reset things using `make distclean`
### Assembly of custom firmware image
**T1024:**
```
./tools/bin-assemble/bin-assemble factory_custom.bin \
0xEC000000 RCW_CTS.bin \
0xEC020000 custom.dtb \
0xEC000000 RCW.bin \
0xEC800000 custom.dtb \
0xEE000000 custom_v1_signed.bin \
0xEFE00000 iram_Type_A_T1024_r1.0.bin \
0xEFF00000 fsl_fman_ucode_t1024_r1.0_108_4_5.bin \
@ -3801,6 +3991,20 @@ If getting errors with keystore then you can reset things using `make distclean`
Flash factory_custom.bin to NOR base 0xEC00_0000
**T1040:**
```
./tools/bin-assemble/bin-assemble factory_custom.bin \
0xE8000000 RCW.bin \
0xE8800000 custom.dtb \
0xEE000000 custom_v1_signed.bin \
0xEFF00000 fsl_fman_ucode_t1040.bin \
0xEFF10000 t1040_qe.bin \
0xEFF40000 wolfboot.bin \
0xEFFFC000 stage1/loader_stage1.bin
```
Flash factory_custom.bin to NOR base 0xE800_0000
## NXP QorIQ T2080 PPC

View File

@ -94,12 +94,70 @@
#endif
#define FLASH_BASE_ADDR 0xEC000000UL
#define FLASH_BASE_PHYS_HIGH 0xFULL
#ifndef BUILD_LOADER_STAGE1
#define FLASH_BASE_PHYS_HIGH 0xFULL /* 36-bit: 0xF_EC000000 */
#else
#define FLASH_BASE_PHYS_HIGH 0x0ULL /* 32-bit stage1 */
#endif
#define FLASH_LAW_SIZE LAW_SIZE_64MB
#define FLASH_TLB_PAGESZ BOOKE_PAGESZ_64M
#define USE_LONG_JUMP
#elif defined(TARGET_nxp_t1040)
/* NXP T1040 */
#define CORE_E5500
#define CPU_NUMCORES 4
#define CORES_PER_CLUSTER 1
#define LAW_MAX_ENTRIES 16
#define CCSRBAR_DEF (0xFE000000) /* T1040RM 4.4.1 default base */
#define CCSRBAR_SIZE BOOKE_PAGESZ_16M
#define ENABLE_L1_CACHE
#define ENABLE_INTERRUPTS
/* T1040 has a 256KB CPC (CoreNet Platform Cache), not PSRAM.
* Stage1: Use L1 locked dcache (16KB) as initial stack before DDR.
* wolfBoot main: DDR already initialized by stage1, use DDR stack. */
#ifdef BUILD_LOADER_STAGE1
#define L1_CACHE_ADDR (0xFDFC0000UL)
#endif
#define L2SRAM_ADDR (0xFDFE0000UL) /* CPC as SRAM (256KB) */
#define L2SRAM_SIZE (256UL * 1024UL)
#define INITIAL_SRAM_ADDR L2SRAM_ADDR
#define INITIAL_SRAM_LAW_SZ LAW_SIZE_256KB
#define INITIAL_SRAM_LAW_TRGT LAW_TRGT_DDR_1 /* CPC target per T1040RM */
#define INITIAL_SRAM_BOOKE_SZ BOOKE_PAGESZ_256K
#ifdef BUILD_LOADER_STAGE1
#define ENABLE_L2_CACHE
#else
/* relocate to 64-bit 0xF_ */
#define CCSRBAR_PHYS_HIGH 0xFULL
#define CCSRBAR_PHYS (CCSRBAR_PHYS_HIGH + CCSRBAR_DEF)
#endif
#define ENABLE_DDR
#ifndef DDR_SIZE
#define DDR_SIZE (8192ULL * 1024ULL * 1024ULL) /* 8GB */
#endif
/* 128MB NOR: 0xE8000000 - 0xEFFFFFFF */
#define FLASH_BASE_ADDR 0xE8000000UL
#ifndef BUILD_LOADER_STAGE1
#define FLASH_BASE_PHYS_HIGH 0xFULL /* 36-bit: 0xF_E8000000 */
#else
#define FLASH_BASE_PHYS_HIGH 0x0ULL /* 32-bit stage1 */
#endif
#define FLASH_LAW_SIZE LAW_SIZE_128MB
/* e5500 BookE has no 128M page size (64M->256M), use 256M TLB */
#define FLASH_TLB_PAGESZ BOOKE_PAGESZ_256M
#define USE_LONG_JUMP
#elif defined(TARGET_nxp_t2080)
/* NXP T2080 */
#define CORE_E6500
@ -189,7 +247,7 @@
#define USE_LONG_JUMP
#else
#error Please define TARGET (nxp_t2080, nxp_t1024, or nxp_p1021)
#error Please define TARGET (nxp_t2080, nxp_t1040, nxp_t1024, or nxp_p1021)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,20 @@ MEMORY
SECTIONS
{
/* .text is placed first via "> FLASH" which allocates from ORIGIN(FLASH).
* .boot and .reset use explicit addresses at end-of-flash and do NOT
* consume FLASH region space (no "> FLASH" directive). */
.text :
{
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
_start_text = .;
*(.text*)
*(.rodata*)
*(.sdata*)
} > FLASH
/* boot code boot_ppc_start.S for _reset */
.boot BOOTSTRAP_TLB :
{
@ -44,17 +58,6 @@ SECTIONS
} = 0x4
. = ALIGN(4);
.text :
{
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
_start_text = .;
*(.text*)
*(.rodata*)
*(.sdata*)
} > FLASH
/* Read-only sections, merged into text segment: */
.interp : { *(.interp) }
.hash : { *(.hash) }
@ -108,3 +111,5 @@ SECTIONS
/* Platform SRAM heap/stack */
PROVIDE(_start_heap = ORIGIN(PSRAM));
PROVIDE(_end_stack = ORIGIN(PSRAM) + (LENGTH(PSRAM)));
ASSERT(_stored_data <= BOOTSTRAP_TLB, ".text/.reloc overflow into bootstrap region")

23
hal/nxp_t1040.c 100644
View File

@ -0,0 +1,23 @@
/* nxp_t1040.c
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* Wrapper for shared T10xx HAL */
#include "nxp_t10xx.c"

89
hal/nxp_t1040.ld 100644
View File

@ -0,0 +1,89 @@
OUTPUT_ARCH( "powerpc" )
ENTRY( _reset )
MEMORY
{
/* DDR4 - 8GB physical (32-bit addressing limits window to <2GB) */
DRAM (rwx) : ORIGIN = @WOLFBOOT_STAGE1_LOAD_ADDR@,
LENGTH = 0x7FFFFFFF - 4K - @WOLFBOOT_STAGE1_LOAD_ADDR@
/* L1 locked dcache - 16KB */
L1RAM (rwx) : ORIGIN = 0xFDFC0000, LENGTH = 0x4000
/* CPC SRAM - 256KB */
CPCSRAM (rwx) : ORIGIN = 0xFDFE0000, LENGTH = 0x40000
}
SECTIONS
{
/* boot code boot_ppc_start.S for _reset */
.boot :
{
KEEP(*(.boot))
} > DRAM
. = ALIGN(4);
/* entry point branch offset to _reset */
.reset :
{
KEEP(*(.reset))
} > DRAM
. = ALIGN(4);
.text :
{
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
_start_text = .;
KEEP(*(.bootmp))
*(.text*)
*(.rodata*)
*(.sdata*)
} > DRAM
/* Read-only sections, merged into text segment: */
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_r : { *(.gnu.version_r) }
.gnu.hash : { *(.gnu.hash) }
.rela.dyn : { *(.rela.dyn) }
_stored_data = .;
.data : AT (_stored_data)
{
_start_data = .;
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
. = ALIGN(4);
_end_data = .;
} > DRAM
.bss (NOLOAD) :
{
_start_bss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
__bss_end__ = .;
. = ALIGN(16);
_end = .;
} > DRAM
}
/* DDR heap/stack */
PROVIDE(_start_heap = _end);
PROVIDE(_end_stack = ORIGIN(DRAM) + (LENGTH(DRAM)));
/* CPC SRAM heap/stack (unused - wolfBoot runs from DDR) */
/* PROVIDE(_start_heap = ORIGIN(CPCSRAM)); */
/* PROVIDE(_end_stack = ORIGIN(CPCSRAM) + (LENGTH(CPCSRAM))); */

View File

@ -0,0 +1,116 @@
OUTPUT_ARCH( "powerpc" )
ENTRY( _reset )
/* Boot ROM out of reset mapped to 0xEFFFF000 (top of 128MB NOR) */
BASE_ADDR = @WOLFBOOT_STAGE1_FLASH_ADDR@;
LOADER_STAGE1_SIZE = @WOLFBOOT_STAGE1_SIZE@;
/* Boot initialization code */
BOOTSTRAP_TLB = 0xEFFFF000;
/* Entry point where RCW directs code to execute from */
BOOTSTRAP_ENTRY = 0xEFFFFFFC;
MEMORY
{
/* Boot Location */
FLASH (rx) : ORIGIN = BASE_ADDR, LENGTH = LOADER_STAGE1_SIZE
/* L1 locked dcache as initial stack - 16KB */
L1RAM (rwx) : ORIGIN = 0xFDFC0000, LENGTH = 0x4000
/* CPC SRAM - 256KB (CoreNet Platform Cache configured as SRAM) */
CPCSRAM (rwx) : ORIGIN = 0xFDFE0000, LENGTH = 0x40000
/* DDR - 8GB physical, 32-bit addressing limits window to <2GB.
* Start at 16MB to avoid using 0x0 (NULL) addresses */
DRAM (rwx) : ORIGIN = 0x1000000, LENGTH = 0x7FFFFFFF - 0x1000000
}
SECTIONS
{
/* .text is placed first via "> FLASH" which allocates from ORIGIN(FLASH).
* .boot and .reset use explicit addresses at end-of-flash and do NOT
* consume FLASH region space (no "> FLASH" directive). */
.text :
{
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
_start_text = .;
*(.text*)
*(.rodata*)
*(.sdata*)
} > FLASH
/* boot code boot_ppc_start.S for _reset */
.boot BOOTSTRAP_TLB :
{
KEEP(*(.boot))
} = 0xFFFC
. = ALIGN(4);
/* entry point branch offset to _reset */
.reset BOOTSTRAP_ENTRY :
{
KEEP(*(.reset))
} = 0x4
. = ALIGN(4);
/* Read-only sections, merged into text segment: */
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_r : { *(.gnu.version_r) }
.gnu.hash : { *(.gnu.hash) }
.rela.dyn : { *(.rela.dyn) }
.reloc :
{
_GOT2_TABLE_ = .;
*(.got2)
_FIXUP_TABLE_ = .;
*(.fixup)
} > FLASH
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
__init_end = .;
. = ALIGN(8);
_stored_data = .;
.data : AT (_stored_data)
{
_start_data = .;
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
. = ALIGN(4);
_end_data = .;
} > DRAM
.bss (NOLOAD) :
{
_start_bss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
__bss_end__ = .;
. = ALIGN(16);
_end = .;
} > DRAM
}
/* CPC SRAM heap, L1 locked dcache stack */
PROVIDE(_start_heap = ORIGIN(CPCSRAM));
PROVIDE(_end_stack = ORIGIN(L1RAM) + (LENGTH(L1RAM)));
ASSERT(_stored_data <= BOOTSTRAP_TLB, ".text/.reloc overflow into bootstrap region")

3639
hal/nxp_t10xx.c 100644

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,11 @@ extern "C" {
/* program header type */
#define ELF_PT_LOAD (0x1)
/* Maximum program headers to cache for in-place ELF loading */
#ifndef ELF_MAX_PH
#define ELF_MAX_PH 8
#endif
typedef struct elf32_header {
uint8_t ident[16];
uint16_t type;

View File

@ -597,8 +597,15 @@ cpc_poll_invalidate:
stw r0, CPCSRCR1(r1) /* SRAM high address = 0 */
/* SRAM low address - use LOAD_ADDR32 on e6500 to avoid sign extension */
LOAD_ADDR32(r0, L2SRAM_ADDR)
/* Enable SRAM and set size (must match L2SRAM_SIZE = 1MB for P384) */
/* Enable SRAM and set size.
* e6500 (T2080): SRAMSZ_1024 = ways 8-15, 1MB
* e5500 (T1040): SRAMSZ_256 = ways 0-7, 256KB
* Both are (0x3 << 1) but interpreted differently per core. */
#ifdef CORE_E6500
ori r0, r0, (CPCSRCR0_SRAMSZ_1024 | CPCSRCR0_SRAMEN)
#else
ori r0, r0, (CPCSRCR0_SRAMSZ_256 | CPCSRCR0_SRAMEN)
#endif
stw r0, CPCSRCR0(r1)
mbar
isync

View File

@ -67,6 +67,11 @@ int elf_load_image_mmu(uint8_t *image, uint32_t image_sz, uintptr_t *pentry,
uint8_t *entry_off;
uint32_t ph_offset;
int is_elf32, is_le, i;
/* Cache for program headers:
* Allows safe in-place ELF loading (e.g. RAM boot) where segment
* copies via memmove could overwrite unread headers */
uint8_t ph_cache[ELF_MAX_PH * sizeof(elf64_program_header)];
uint32_t ph_table_sz;
#ifdef DEBUG_ELF
wolfBoot_printf("Loading elf at %p\r\n", (void*)image);
@ -119,6 +124,16 @@ int elf_load_image_mmu(uint8_t *image, uint32_t image_sz, uintptr_t *pentry,
}
entry_off = image + ph_offset;
/* Cache program headers on the stack so that in-place segment copies
* (memmove) cannot corrupt headers that have not been read yet.
* This is critical for RAM-boot where the ELF buffer address equals
* the target virtual address of the first LOAD segment. */
ph_table_sz = (uint32_t)entry_count * entry_size;
if (entry_count <= ELF_MAX_PH && ph_table_sz <= sizeof(ph_cache)) {
memcpy(ph_cache, entry_off, ph_table_sz);
entry_off = ph_cache;
}
#ifdef DEBUG_ELF
wolfBoot_printf("Program Headers %d (size %d)\r\n", entry_count, entry_size);
#endif

View File

@ -84,7 +84,6 @@ endif
MAIN_TARGET=loader_stage1.bin
TARGET_H_TEMPLATE:=../include/target.h.in
ASFLAGS:=$(CFLAGS)
BOOTLOADER_PARTITION_SIZE?=$$(( $(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET)))
ifeq ($(WOLFBOOT_STAGE1_SIZE),)
@ -99,8 +98,13 @@ CFLAGS+=\
-DWOLFBOOT_STAGE1_FLASH_ADDR=$(WOLFBOOT_STAGE1_FLASH_ADDR) \
-DWOLFBOOT_STAGE1_BASE_ADDR=$(WOLFBOOT_STAGE1_BASE_ADDR)
# ASFLAGS must be set after BUILD_LOADER_STAGE1 is added to CFLAGS,
# so assembly files see the same defines as C files.
ASFLAGS:=$(CFLAGS)
# For printf support (disable NO_PRINTF_UART) and increase WOLFBOOT_STAGE1_SIZE
ifeq ($(ARCH),PPC)
CFLAGS+=-g -gdwarf-4
CFLAGS+=-DNO_PRINTF_UART -DWOLFBOOT_NO_PRINTF
ifeq ($(NO_XIP),1)
# Use PIC (Position Independent Code) for first stage loader

View File

@ -488,6 +488,16 @@ ifeq ($(TARGET),nxp_t2080)
endif
ifeq ($(TARGET),nxp_t1024)
ifneq ($(SIGN),NONE)
APP_OBJS+=../src/keystore.o
endif
# PowerPC e5500
PPC64=1
endif
ifeq ($(TARGET),nxp_t1040)
ifneq ($(SIGN),NONE)
APP_OBJS+=../src/keystore.o
endif
# PowerPC e5500
PPC64=1
endif

View File

@ -5,7 +5,6 @@ ENTRY( _app_entry )
PHDRS
{
text PT_LOAD;
bss PT_LOAD;
}
SECTIONS

View File

@ -1,4 +1,6 @@
/* app_nxp_t1024.c
*
* Test bare-metal application for NXP T1024.
*
* Copyright (C) 2025 wolfSSL Inc.
*
@ -20,32 +22,160 @@
*/
#include <stdint.h>
#include "../hal/nxp_ppc.h"
#include "printf.h"
#include <string.h>
static const char* hex_lut = "0123456789abcdef";
#include "target.h"
#include "wolfboot/wolfboot.h"
/* wait_ticks: spin for r3 ticks using PPC timebase.
* Required by udelay() in nxp_ppc.c (linked via HAL). */
__asm__ (
".section .text.wait_ticks\n"
".global wait_ticks\n"
"wait_ticks:\n"
" mflr 8\n"
" mftbu 5\n"
" mftbl 4\n"
" addc 7, 4, 3\n"
" addze 6, 5\n"
"1: mftbu 5\n"
" mftbl 4\n"
" subfc 4, 4, 7\n"
" subfe. 5, 5, 6\n"
" bge 1b\n"
" mtlr 8\n"
" blr\n"
);
/* Assembly entry point: set stack pointer, enable FPU, and call main.
* The linker script defines _stack_top at the end of the stack region.
* PPC ABI: r1 = stack pointer, 16-byte aligned, back-chain to 0.
* FPU must be enabled because GCC's variadic function ABI (used by
* uart_printf/wolfBoot_printf) saves FP registers via stfd instructions.
* Without MSR[FP], this causes a Floating-Point Unavailable exception. */
__asm__ (
".section .text._app_entry\n"
".global _app_entry\n"
"_app_entry:\n"
" lis 1, _stack_top@ha\n"
" addi 1, 1, _stack_top@l\n"
" li 0, 0\n"
" stwu 0, -16(1)\n"
/* Enable FPU: set MSR[FP] (bit 18) = 0x2000 */
" mfmsr 0\n"
" ori 0, 0, 0x2000\n"
" mtmsr 0\n"
" isync\n"
" b main\n"
);
#include "printf.h"
#include "keystore.h"
#include "../hal/nxp_ppc.h"
static uint8_t boot_part_state = IMG_STATE_NEW;
static uint8_t update_part_state = IMG_STATE_NEW;
const char part_state_names[6][16] = {
"NEW",
"UPDATING",
"FFLAGS",
"TESTING",
"CONFIRMED",
"[Invalid state]"
};
static const char *part_state_name(uint8_t state)
{
switch(state) {
case IMG_STATE_NEW:
return part_state_names[0];
case IMG_STATE_UPDATING:
return part_state_names[1];
case IMG_STATE_FINAL_FLAGS:
return part_state_names[2];
case IMG_STATE_TESTING:
return part_state_names[3];
case IMG_STATE_SUCCESS:
return part_state_names[4];
default:
return part_state_names[5];
}
}
static int print_info(void)
{
int i, j;
uint32_t n_keys;
wolfBoot_get_partition_state(PART_BOOT, &boot_part_state);
wolfBoot_get_partition_state(PART_UPDATE, &update_part_state);
wolfBoot_printf("\r\n");
wolfBoot_printf("System information\r\n");
wolfBoot_printf("====================================\r\n");
wolfBoot_printf("Boot partition version: %lu\r\n",
wolfBoot_current_firmware_version());
wolfBoot_printf("Update partition version: %lu\r\n",
wolfBoot_update_firmware_version());
wolfBoot_printf("Current firmware state: %s\r\n",
part_state_name(boot_part_state));
wolfBoot_printf("Update state: %s\r\n",
part_state_name(update_part_state));
wolfBoot_printf("\r\n");
wolfBoot_printf("Bootloader keystore information\r\n");
wolfBoot_printf("====================================\r\n");
n_keys = keystore_num_pubkeys();
wolfBoot_printf("Number of public keys: %lu\r\n", n_keys);
for (i = 0; i < (int)n_keys; i++) {
uint32_t size = keystore_get_size(i);
uint32_t type = keystore_get_key_type(i);
uint32_t mask = keystore_get_mask(i);
uint8_t *keybuf = keystore_get_buffer(i);
wolfBoot_printf("\r\n");
wolfBoot_printf(" Public Key #%d: size %lu, type %lx, mask %08lx\r\n",
i, size, type, mask);
wolfBoot_printf(" ====================================\r\n ");
for (j = 0; j < (int)size; j++) {
wolfBoot_printf("%02X ", keybuf[j]);
if (j % 16 == 15) {
wolfBoot_printf("\r\n ");
}
}
wolfBoot_printf("\r\n");
}
return 0;
}
void main(void)
{
int i = 0;
int j = 0;
int k = 0;
char snum[8];
/* Zero BSS - required for bare-metal since there's no crt0 startup.
* Without this, static variables contain DDR garbage. */
extern char _start_bss[], _end_bss[];
{
char *p = _start_bss;
while (p < _end_bss)
*p++ = 0;
}
uart_init();
uart_write("Test App\n", 9);
wolfBoot_printf("========================\r\n");
wolfBoot_printf("NXP T1024 wolfBoot demo Application\r\n");
wolfBoot_printf("Copyright 2025 wolfSSL Inc\r\n");
wolfBoot_printf("GPL v3\r\n");
wolfBoot_printf("========================\r\n");
/* Wait for reboot */
print_info();
/* Mark boot partition as successful */
wolfBoot_success();
wolfBoot_printf("\r\nBoot partition marked successful\r\n");
wolfBoot_printf("Test App: idle loop\r\n");
while(1) {
for (j=0; j<1000000; j++)
;
i++;
uart_write("\r\n0x", 4);
for (k=0; k<8; k++) {
snum[7 - k] = hex_lut[(i >> 4*k) & 0xf];
}
uart_write(snum, 8);
/* Idle */
}
}

View File

@ -0,0 +1,181 @@
/* app_nxp_t1040.c
*
* Test bare-metal application for NXP T1040.
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include <string.h>
#include "target.h"
#include "wolfboot/wolfboot.h"
/* wait_ticks: spin for r3 ticks using PPC timebase.
* Required by udelay() in nxp_ppc.c (linked via HAL). */
__asm__ (
".section .text.wait_ticks\n"
".global wait_ticks\n"
"wait_ticks:\n"
" mflr 8\n"
" mftbu 5\n"
" mftbl 4\n"
" addc 7, 4, 3\n"
" addze 6, 5\n"
"1: mftbu 5\n"
" mftbl 4\n"
" subfc 4, 4, 7\n"
" subfe. 5, 5, 6\n"
" bge 1b\n"
" mtlr 8\n"
" blr\n"
);
/* Assembly entry point: set stack pointer, enable FPU, and call main.
* The linker script defines _stack_top at the end of the stack region.
* PPC ABI: r1 = stack pointer, 16-byte aligned, back-chain to 0.
* FPU must be enabled because GCC's variadic function ABI (used by
* uart_printf/wolfBoot_printf) saves FP registers via stfd instructions.
* Without MSR[FP], this causes a Floating-Point Unavailable exception. */
__asm__ (
".section .text._app_entry\n"
".global _app_entry\n"
"_app_entry:\n"
" lis 1, _stack_top@ha\n"
" addi 1, 1, _stack_top@l\n"
" li 0, 0\n"
" stwu 0, -16(1)\n"
/* Enable FPU: set MSR[FP] (bit 18) = 0x2000 */
" mfmsr 0\n"
" ori 0, 0, 0x2000\n"
" mtmsr 0\n"
" isync\n"
" b main\n"
);
#include "printf.h"
#include "keystore.h"
#include "../hal/nxp_ppc.h"
static uint8_t boot_part_state = IMG_STATE_NEW;
static uint8_t update_part_state = IMG_STATE_NEW;
const char part_state_names[6][16] = {
"NEW",
"UPDATING",
"FFLAGS",
"TESTING",
"CONFIRMED",
"[Invalid state]"
};
static const char *part_state_name(uint8_t state)
{
switch(state) {
case IMG_STATE_NEW:
return part_state_names[0];
case IMG_STATE_UPDATING:
return part_state_names[1];
case IMG_STATE_FINAL_FLAGS:
return part_state_names[2];
case IMG_STATE_TESTING:
return part_state_names[3];
case IMG_STATE_SUCCESS:
return part_state_names[4];
default:
return part_state_names[5];
}
}
static int print_info(void)
{
int i, j;
uint32_t n_keys;
wolfBoot_get_partition_state(PART_BOOT, &boot_part_state);
wolfBoot_get_partition_state(PART_UPDATE, &update_part_state);
wolfBoot_printf("\r\n");
wolfBoot_printf("System information\r\n");
wolfBoot_printf("====================================\r\n");
wolfBoot_printf("Boot partition version: %lu\r\n",
wolfBoot_current_firmware_version());
wolfBoot_printf("Update partition version: %lu\r\n",
wolfBoot_update_firmware_version());
wolfBoot_printf("Current firmware state: %s\r\n",
part_state_name(boot_part_state));
wolfBoot_printf("Update state: %s\r\n",
part_state_name(update_part_state));
wolfBoot_printf("\r\n");
wolfBoot_printf("Bootloader keystore information\r\n");
wolfBoot_printf("====================================\r\n");
n_keys = keystore_num_pubkeys();
wolfBoot_printf("Number of public keys: %lu\r\n", n_keys);
for (i = 0; i < (int)n_keys; i++) {
uint32_t size = keystore_get_size(i);
uint32_t type = keystore_get_key_type(i);
uint32_t mask = keystore_get_mask(i);
uint8_t *keybuf = keystore_get_buffer(i);
wolfBoot_printf("\r\n");
wolfBoot_printf(" Public Key #%d: size %lu, type %lx, mask %08lx\r\n",
i, size, type, mask);
wolfBoot_printf(" ====================================\r\n ");
for (j = 0; j < (int)size; j++) {
wolfBoot_printf("%02X ", keybuf[j]);
if (j % 16 == 15) {
wolfBoot_printf("\r\n ");
}
}
wolfBoot_printf("\r\n");
}
return 0;
}
void main(void)
{
/* Zero BSS - required for bare-metal since there's no crt0 startup.
* Without this, static variables contain DDR garbage. */
extern char _start_bss[], _end_bss[];
{
char *p = _start_bss;
while (p < _end_bss)
*p++ = 0;
}
uart_init();
wolfBoot_printf("========================\r\n");
wolfBoot_printf("NXP T1040 wolfBoot demo Application\r\n");
wolfBoot_printf("Copyright 2025 wolfSSL Inc\r\n");
wolfBoot_printf("GPL v3\r\n");
wolfBoot_printf("========================\r\n");
print_info();
/* Mark boot partition as successful */
wolfBoot_success();
wolfBoot_printf("\r\nBoot partition marked successful\r\n");
wolfBoot_printf("Test App: idle loop\r\n");
while(1) {
/* Idle */
}
}

View File

@ -0,0 +1,182 @@
; ------------------------------------------------------------------------------
; @Title: NXP T1040 wolfBoot Debug Script
; @Description:
; Brings up the T1040, loads wolfBoot ELF symbols, and sets breakpoints
; for source-level debugging. Stage1 runs XIP from NOR flash, then loads
; wolfBoot to DDR at 0x7FF00000 for execution.
; @Chip: T1040
; Based on demo scripts from Lauterbach
; ------------------------------------------------------------------------------
;
; Prerequisites:
; - wolfBoot must already be flashed to NOR (use t1040_flash.cmm)
; - wolfboot.elf must be built with debug symbols (DEBUG=1 recommended)
;
; Boot flow:
; 1. Reset vector (0xEFFFFFFC) -> Stage1 bootstrap TLB (0xEFFFF000)
; 2. Stage1 (0xEFFFC000 XIP) -> sets up DDR, copies wolfBoot to DDR
; 3. wolfBoot runs from DDR (0x7FF00000)
; ------------------------------------------------------------------------------
; Base directory for wolfBoot build output (adjust to match your build path)
&basedir="/home/davidgarske/GitHub/wolfboot-alt"
PRINT "========================================"
PRINT "T1040 wolfBoot Debug Session"
PRINT "========================================"
PRINT ""
; Reset everything
RESet
SYStem.RESet
SYStem.BdmClock 15.MHz
SYStem.CPU T1040
SYStem.DETECT CPU
CORE.ASSIGN 1.
SYStem.Option.FREEZE ON
SYStem.Option.IMASKASM ON
; Boot from flash — NO RCW override.
; The boot ROM loads RCW from NOR flash and initializes PLLs properly.
PRINT "Booting from flash (PLLs initialized by boot ROM)..."
SYStem.Up
PRINT "System up — CPU halted at first instruction"
; Allow non-intrusive run-time memory access
SYStem.MemAccess CPU
; --------------------------------------------------------------------------
; Set up LAWs for debugger access
; --------------------------------------------------------------------------
PRINT "Setting up LAW for CCSR access..."
Data.Set ANC:IOBASE()+0x00C00 %Long %BE 0x00000000 ; LAWBARH0 = 0
Data.Set ANC:IOBASE()+0x00C04 %Long %BE 0xFE000000 ; LAWBARL0 = 0xFE000000
Data.Set ANC:IOBASE()+0x00C08 %Long %BE 0x81E00017 ; LAWAR0 = enable|CORENET|16 MB
PRINT "Setting up LAW for flash access..."
Data.Set ANC:IOBASE()+0x00C10 %Long %BE 0x00000000 ; LAWBARH1 = 0 (32-bit)
Data.Set ANC:IOBASE()+0x00C14 %Long %BE 0xE8000000 ; LAWBARL1 = 0xE8000000
Data.Set ANC:IOBASE()+0x00C18 %Long %BE 0x81F0001A ; LAWAR1 = enable|IFC|128 MB
; --------------------------------------------------------------------------
; TLBs for debugger data access (high indices to avoid boot_ppc_start.S)
; --------------------------------------------------------------------------
; TLB for CCSR: Entry 10, 0xFE000000, 16 MB, I|G
MMU.TLB1.Set 10. 0xC0000700 0xFE00000A 0xFE000015 0x00000000 0x0
; TLB for Flash: Entry 11, 256 MB, I|G
MMU.TLB1.Set 11. 0xC0000900 0xE800000A 0xE8000015 0x00000000 0x0
; TLB for DDR: Entry 12, 0x00000000, 1 GB, M
MMU.TLB1.Set 12. 0xC0000A00 0x00000004 0x00000015 0x00000000 0x0
; TLB for DDR: Entry 13, 0x40000000, 1 GB, M (covers wolfBoot at 0x7FF00000)
MMU.TLB1.Set 13. 0xC0000A00 0x40000004 0x40000015 0x00000000 0x0
PRINT "TLBs configured (CCSR, Flash, DDR)"
; --------------------------------------------------------------------------
; Verify flash is accessible
; --------------------------------------------------------------------------
&rcw_preamble=Data.Long(D:0xE8000000)
PRINT "RCW preamble at 0xE8000000: &rcw_preamble"
IF &rcw_preamble!=0xAA55AA55
(
PRINT %WARNING "WARNING: Expected RCW preamble 0xAA55AA55, got &rcw_preamble"
)
; Verify stage1 code is present
&stage1_first=Data.Long(D:0xEFFFC000)
PRINT "Stage1 first word at 0xEFFFC000: &stage1_first"
IF &stage1_first==0xFFFFFFFF
(
PRINT %ERROR "ERROR: Stage1 region appears erased — run t1040_flash.cmm first"
STOP
)
PRINT ""
; --------------------------------------------------------------------------
; Load ELF symbols
; STRIPPART strips leading path components from DWARF source paths so
; SourcePATH can resolve them. Adjust the number if source doesn't resolve.
; --------------------------------------------------------------------------
PRINT "Loading symbols..."
; Load wolfBoot symbols FIRST (primary debug target, runs from DDR)
Data.LOAD.Elf "&basedir/wolfboot.elf" /NoCODE /StripPART "&basedir/"
PRINT " wolfBoot symbols loaded (DDR 0x7FF00000)"
; Load stage1 symbols (secondary, runs XIP from flash)
Data.LOAD.Elf "&basedir/stage1/loader_stage1.elf" /NoClear /NoCODE /StripPART "&basedir/"
PRINT " Stage1 symbols loaded (flash 0xEFFFC000)"
; Load test application symbols (if available)
IF OS.FILE("&basedir/test-app/image.elf")
(
Data.LOAD.Elf "&basedir/test-app/image.elf" /NoClear /NoCODE /StripPART "&basedir/"
PRINT " Test app symbols loaded"
)
; Set source search paths
sYmbol.SourcePATH.Set &basedir &basedir/src &basedir/hal &basedir/lib/wolfssl &basedir/test-app &basedir/stage1 &basedir/include
; Verify symbols loaded at correct addresses
PRINT ""
PRINT "Symbol verification:"
IF sYmbol.EXIST(hal_pcie_init)
PRINT " hal_pcie_init = " sYmbol.BEGIN(hal_pcie_init)
IF sYmbol.EXIST(hal_qe_init)
PRINT " hal_qe_init = " sYmbol.BEGIN(hal_qe_init)
IF sYmbol.EXIST(hal_fman_init)
PRINT " hal_fman_init = " sYmbol.BEGIN(hal_fman_init)
IF sYmbol.EXIST(hal_mp_init)
PRINT " hal_mp_init = " sYmbol.BEGIN(hal_mp_init)
; --------------------------------------------------------------------------
; Set breakpoints (e5500 has only 2 on-chip instruction BPs)
; Change these as needed for the current debug focus.
; --------------------------------------------------------------------------
PRINT ""
PRINT "Setting breakpoints (2 max on e5500)..."
Break.Delete /ALL
Break.Set hal_pcie_init /Program /Onchip
PRINT " BP: hal_pcie_init"
; Second BP: uncomment ONE of these as needed:
;Break.Set hal_qe_init /Program /Onchip
;Break.Set hal_fman_init /Program /Onchip
;Break.Set hal_mp_init /Program /Onchip
;Break.Set main /Program /Onchip
PRINT ""
PRINT "Current PC: " Register(PC)
PRINT ""
PRINT "========================================"
PRINT "wolfBoot Debug Ready (flash boot)"
PRINT "========================================"
PRINT ""
PRINT "Boot flow:"
PRINT " 0xEFFFFFFC: Reset vector -> 0xEFFFF000"
PRINT " 0xEFFFF000: Stage1 bootstrap TLB setup"
PRINT " 0xEFFFC000: Stage1 loader (XIP from flash)"
PRINT " - hal_early_init -> hal_ddr_init"
PRINT " - boot_entry_C copies .data to DDR"
PRINT " - Copies wolfBoot to DDR 0x7FF00000"
PRINT " - Jumps to wolfBoot"
PRINT " 0x7FF00000: wolfBoot (running from DDR)"
PRINT ""
PRINT "To change breakpoints:"
PRINT " Break.Delete /ALL"
PRINT " Break.Set <symbol_or_addr> /Program /Onchip"
PRINT ""
PRINT "Ready — press Go to start execution"
PRINT ""
ENDDO

View File

@ -0,0 +1,447 @@
; ------------------------------------------------------------------------------
; @Title: NXP T1040 NOR Flash Programming Script
; @Description:
; Uses CPC_SRAM for target-based NOR FLASH programming.
; Programs wolfBoot stage1, wolfBoot, signed application image, RCW, and
; FMAN microcode.
; @Chip: T1040
; Based on demo scripts from Lauterbach
; ------------------------------------------------------------------------------
;
; T1040D4RDB has 128MB NOR flash (JS28F00AM29EWHA) at 0xE8000000-0xEFFFFFFF.
; The CPLD supports virtual banking (VBANK) to remap 16MB zones within the
; 128MB space. With VBANK=000 (default), the flash is accessed normally.
;
; wolfBoot Flash Layout (128MB NOR):
; 0xE8000000: RCW (128 KB sector, 96 bytes actual)
; 0xE80F0000: Swap sector (128 KB)
; 0xE8800000: DTS boot (128 KB)
; 0xE8820000: DTS update (128 KB)
; 0xEE000000: Boot partition (15 MB)
; 0xEEF00000: Update partition (15 MB)
; 0xEFF00000: FMAN microcode (64 KB, ~32 KB actual)
; 0xEFF10000: QE microcode (64 KB, ~13 KB actual)
; 0xEFF40000: wolfBoot (768 KB)
; 0xEFFFC000: Stage 1 loader (16 KB, includes reset vector)
; ------------------------------------------------------------------------------
; Base directory for wolfBoot build output (adjust to match your build path)
&basedir="/home/davidgarske/GitHub/wolfboot-alt"
; Persistent backup directory (survives make clean)
&backupdir="/home/davidgarske/Projects/NXP/t1040rdb"
; FLASH Number of banks
; The JS28F00AM29EWHA is a single 128MB NOR chip. CPLD virtual banking
; presents two "virtual banks" but CFI reports 128MB for the single chip.
; Set to 1 so flashbase = 0xE8000000.
&flashBanks=1
; FLASH parameters
&waitstates=6
; PART 1: Set up MMU, IFC and CPC for target-based flash programming
; ------------------------------------------------------------------------------
PRINT "========================================"
PRINT "wolfBoot T1040 Flash Programming"
PRINT "========================================"
PRINT ""
SYStem.RESet
SYStem.BdmClock 15.MHz
SYStem.CPU T1040
SYStem.DETECT CPU
CORE.ASSIGN 1.
SYStem.Option.FREEZE OFF
; Use RCW override to prevent flash RCW from running before we are ready.
; This keeps the system halted for configuration.
PRINT "Initializing with temporary RCW override..."
SYStem.Mode.Prepare
SYStem.Option.HRCWOVerRide ON
; Load RCW (T1040D4RDB values extracted from factory flash)
Data.Set DBG:0x01000000 0x0c18000e
Data.Set DBG:0x01000001 0x0e000000
Data.Set DBG:0x01000002 0x00000000
Data.Set DBG:0x01000003 0x00000000
Data.Set DBG:0x01000004 0x66000002
Data.Set DBG:0x01000005 0x40000002
Data.Set DBG:0x01000006 0xec027000
Data.Set DBG:0x01000007 0x01000000
Data.Set DBG:0x01000008 0x00000000
Data.Set DBG:0x01000009 0x00000000
Data.Set DBG:0x0100000A 0x00000000
Data.Set DBG:0x0100000B 0x00030810
Data.Set DBG:0x0100000C 0x00000000
Data.Set DBG:0x0100000D 0x0342580f
Data.Set DBG:0x0100000E 0x00000000
Data.Set DBG:0x0100000F 0x00000000
SYStem.Up
SYStem.Option.HRCWOVerRide OFF
PRINT "System initialized (halted state with temporary RCW)"
; Set CCSRBAR to 0x40000000
Data.Set ANC:IOBASE()+0x00004 %Long 0x40000000
Data.Set ANC:IOBASE()+0x00008 %Long 0x80000000 ; commit
Data.Set ANC:IOBASE()+0x00008 %Long 0x00000000
; Set up local access window: 0xC0000000--0xFFFFFFFF
Data.Set ANC:IOBASE()+0x00C00 %Long %BE 0x00000000
Data.Set ANC:IOBASE()+0x00C04 %Long %BE 0xC0000000
Data.Set ANC:IOBASE()+0x00C08 %Long %BE 0x81F0001D
; Set up local access window: 0x10000000--0x1007FFFF (CPC memory complex 1)
Data.Set ANC:IOBASE()+0x00C10 %Long %BE 0x00000000
Data.Set ANC:IOBASE()+0x00C14 %Long %BE 0x10000000
Data.Set ANC:IOBASE()+0x00C18 %Long %BE 0x81000012
; Set up local access window: 0x10080000--0x100FFFFF (CPC memory complex 2)
Data.Set ANC:IOBASE()+0x00C20 %Long %BE 0x00000000
Data.Set ANC:IOBASE()+0x00C24 %Long %BE 0x10080000
Data.Set ANC:IOBASE()+0x00C28 %Long %BE 0x81100012
; Enable CoreNet Platform Cache (CPC) as SRAM
; Block 1, memory complex 1
Data.Set ANC:IOBASE()+0x10000 %Long %BE 0x80200000
Data.Set ANC:IOBASE()+0x10100 %Long %BE 0x00000000
Data.Set ANC:IOBASE()+0x10104 %Long %BE 0x10000009 ; 512 kB, start at 0x10000000
; Block 2, memory complex 2
Data.Set ANC:IOBASE()+0x11000 %Long %BE 0x80200000
Data.Set ANC:IOBASE()+0x11100 %Long %BE 0x00000000
Data.Set ANC:IOBASE()+0x11104 %Long %BE 0x10080009 ; 512 kB, start at 0x10080000
; TLB entry for FLASH 0xC0000000--0xFFFFFFFF (cache-inhibited, guarded)
; MAS1: V=1, IPROT=1, TSIZE=10 (1GB on e5500)
MMU.TLB1.Set 0. 0xC0000A00 0xC000000A 0xC0000015 0x00000000 0x0
; TLB entry for CPC-SRAM 0x10000000--0x100FFFFF
MMU.TLB1.Set 1. 0x80000500 0x10000002 0x10000015 0x00000000 0x0
; PART 2: FLASH setup (chip select and debugger)
; ------------------------------------------------------------------------------
; Initial FLASH base address (8 MB from end, for CFI probe)
&flashbase=0xEF800000
; End of flash region
&flashend=0xEFFFFFFF
; Set up initial chip select for FLASH memory
Data.Set ANC:IOBASE.ADDRESS()+0x00124010 %Long (Data.Long(ANC:IOBASE.ADDRESS()+0x00124010)&0x0000FFBF)|&flashbase
; Get port width
&portwidth=(Data.Long(ANC:IOBASE.ADDRESS()+0x00124010)>>7.)&0x00000003
IF &portwidth==1
&flashwidth="BYTE"
ELSE IF &portwidth==2
&flashwidth="WORD"
ELSE
(
PRINT %ERROR "ERROR: invalid IFC_CS0 port width"
STOP
)
; Get FLASH size
&flashsize=FLASH.CFI.SIZE(ANC:&flashbase,&flashwidth)
IF (&flashsize==0)
(
PRINT %ERROR "ERROR: FLASH module could not be detected"
STOP
)
&cfisizemb=FORMAT.Decimal(0,&flashsize>>20.)
PRINT "CFI reported flash size: &cfisizemb MB (raw), flashBanks=&flashBanks"
; Adjust for dual-bank devices (if CFI reports more than physical size)
&flashsize=&flashsize/&flashBanks
; Calculate real FLASH base address
&flashbase=(&flashend+1)-&flashsize
; Set up true chip select for FLASH memory
Data.Set ANC:IOBASE.ADDRESS()+0x00124010 %Long (Data.Long(ANC:IOBASE.ADDRESS()+0x00124010)&0x0000FFFF)|&flashbase
; Declare FLASH
FLASH.RESet
; Flash target: code at 0x10000000, data at 0x10002000, buffer 0x4000
FLASH.CFI &flashbase &flashwidth /TARGET 0x10000000 0x10002000 0x4000 /DualPort
&sizemb=FORMAT.Decimal(0,&flashsize>>20.)
PRINT "Configured Flash at address &flashbase, &sizemb MBytes."
; Verify expected flash base
IF &flashbase!=0xE8000000
(
PRINT %WARNING "WARNING: Expected flash base 0xE8000000, got &flashbase"
PRINT " Check &flashBanks setting (currently &flashBanks)"
)
; ============================================================================
; PART 3: Interactive Flash Programming Options
; ============================================================================
PRINT ""
PRINT "========================================"
PRINT "Flash Programming Options"
PRINT "========================================"
PRINT ""
; ============================================================================
; Option 1: Flash wolfBoot components (most common operation)
; ============================================================================
DIALOG.YESNO "Flash wolfBoot components (RCW + FMAN + wolfBoot + stage1 + test app)?"
ENTRY &flashwolfboot
IF &flashwolfboot
(
PRINT ""
PRINT "========================================"
PRINT "Flashing wolfBoot Components"
PRINT "========================================"
PRINT ""
; --------------------------------------------------------------------------
; 1. RCW (Reset Configuration Word) - CRITICAL for boot
; --------------------------------------------------------------------------
PRINT "1. Programming RCW (Reset Configuration Word)..."
PRINT " Source: &backupdir/t1040_rcw.bin"
PRINT " Address: 0xE8000000 (128 KB sector)"
FLASH.UNLOCK 0xE8000000--0xE801FFFF
FLASH.ReProgram 0xE8000000--0xE801FFFF /Erase
Data.LOAD.binary &backupdir/t1040_rcw.bin 0xE8000000
FLASH.ReProgram.off
Data.LOAD.binary &backupdir/t1040_rcw.bin 0xE8000000 /Verify
PRINT " RCW programmed and verified"
PRINT ""
; --------------------------------------------------------------------------
; 2. FMAN + QE Microcode (share same 128KB erase sector 0xEFF00000-0xEFF1FFFF)
; Must be programmed together to avoid erasing one when writing the other.
; --------------------------------------------------------------------------
PRINT "2. Programming FMAN + QE microcode..."
PRINT " FMAN: &backupdir/t1040_fman.bin -> 0xEFF00000 (~32 KB)"
PRINT " QE: &backupdir/t1040_qe.bin -> 0xEFF10000 (~13 KB)"
FLASH.UNLOCK 0xEFF00000--0xEFF1FFFF
FLASH.ReProgram 0xEFF00000--0xEFF1FFFF /Erase
Data.LOAD.binary &backupdir/t1040_fman.bin 0xEFF00000
Data.LOAD.binary &backupdir/t1040_qe.bin 0xEFF10000
FLASH.ReProgram.off
Data.LOAD.binary &backupdir/t1040_fman.bin 0xEFF00000 /Verify
Data.LOAD.binary &backupdir/t1040_qe.bin 0xEFF10000 /Verify
PRINT " FMAN + QE microcode programmed and verified"
PRINT ""
; --------------------------------------------------------------------------
; 3. wolfBoot Bootloader (768 KB at 0xEFF40000)
; --------------------------------------------------------------------------
PRINT "3. Programming wolfBoot bootloader..."
PRINT " Source: &basedir/wolfboot.bin"
PRINT " Address: 0xEFF40000 (768 KB)"
FLASH.UNLOCK 0xEFF40000--0xEFFBFFFF
FLASH.ReProgram 0xEFF40000--0xEFFBFFFF /Erase
Data.LOAD.binary &basedir/wolfboot.bin 0xEFF40000
FLASH.ReProgram.off
Data.LOAD.binary &basedir/wolfboot.bin 0xEFF40000 /Verify
PRINT " wolfBoot programmed and verified"
PRINT ""
; --------------------------------------------------------------------------
; 4. Stage 1 Loader (16 KB at 0xEFFFC000, includes reset vector)
; --------------------------------------------------------------------------
PRINT "4. Programming stage 1 loader..."
PRINT " Source: &basedir/stage1/loader_stage1.bin"
PRINT " Address: 0xEFFFC000 (16 KB, reset vector at 0xEFFFFFFC)"
FLASH.UNLOCK 0xEFFFC000--0xEFFFFFFF
FLASH.ReProgram 0xEFFFC000--0xEFFFFFFF /Erase
Data.LOAD.binary &basedir/stage1/loader_stage1.bin 0xEFFFC000
FLASH.ReProgram.off
Data.LOAD.binary &basedir/stage1/loader_stage1.bin 0xEFFFC000 /Verify
PRINT " Stage 1 loader programmed and verified"
PRINT ""
; --------------------------------------------------------------------------
; 5. Test Application (Boot Partition at 0xEE000000)
; Only erase/program sectors needed for the actual image size,
; not the full 15 MB partition.
; --------------------------------------------------------------------------
PRINT "5. Programming test application..."
PRINT " Source: &basedir/test-app/image_v1_signed.bin"
&appsize=OS.FILE.SIZE(&basedir/test-app/image_v1_signed.bin)
; Round up to next 128 KB sector boundary
&append=0xEE000000+((&appsize+0x1FFFF)&~0x1FFFF)-1
&appsizemb=FORMAT.Decimal(0,&appsize>>10.)
PRINT " Address: 0xEE000000, image size &appsizemb KB, erasing to &append"
FLASH.UNLOCK 0xEE000000--&append
FLASH.ReProgram 0xEE000000--&append /Erase
Data.LOAD.binary &basedir/test-app/image_v1_signed.bin 0xEE000000
FLASH.ReProgram.off
Data.LOAD.binary &basedir/test-app/image_v1_signed.bin 0xEE000000 /Verify
PRINT " Test application programmed and verified"
PRINT ""
PRINT ""
PRINT "========================================"
PRINT "wolfBoot Flash Programming Complete!"
PRINT "========================================"
PRINT ""
PRINT "Flash Layout:"
PRINT " 0xE8000000: RCW (128 KB sector)"
PRINT " 0xEE000000: Test Application (boot partition, 15 MB)"
PRINT " 0xEEEFFFFF: End of boot partition"
PRINT " 0xEFF00000: FMAN Microcode (64 KB, ~32 KB actual)"
PRINT " 0xEFF10000: QE Microcode (64 KB, ~13 KB actual)"
PRINT " 0xEFF40000: wolfBoot (768 KB)"
PRINT " 0xEFFBFFFF: End of wolfBoot"
PRINT " 0xEFFFC000: Stage 1 Loader (16 KB)"
PRINT " 0xEFFFFFFC: Reset vector"
PRINT ""
PRINT "Verification - First bytes of each component:"
PRINT ""
PRINT "RCW at 0xE8000000 (should be AA 55 AA 55):"
Data.dump 0xE8000000++0x3F /Long
PRINT ""
PRINT "FMAN at 0xEFF00000 (should show QEF header):"
Data.dump 0xEFF00000++0x3F /Long
PRINT ""
PRINT "QE at 0xEFF10000 (should show QEF header):"
Data.dump 0xEFF10000++0x3F /Long
PRINT ""
PRINT "wolfBoot at 0xEFF40000:"
Data.dump 0xEFF40000++0x3F /Long
PRINT ""
PRINT "Stage1 at 0xEFFFC000:"
Data.dump 0xEFFFC000++0x3F /Long
PRINT ""
PRINT "Reset vector at 0xEFFFFFFC:"
Data.dump 0xEFFFFFFC++0x03 /Long
PRINT ""
PRINT "Test app at 0xEE000000 (should be WOLF header):"
Data.dump 0xEE000000++0x3F /Long
PRINT ""
GOTO flash_complete
)
ELSE
(
PRINT ""
PRINT "Skipping wolfBoot component flashing"
PRINT ""
)
; ============================================================================
; Option 2: Backup current flash bank
; ============================================================================
PRINT ""
PRINT "========================================"
PRINT "Optional: Backup Current Flash Bank"
PRINT "========================================"
PRINT ""
DIALOG.YESNO "Backup current flash to &backupdir/t1040_backup.bin (128 MB)?"
ENTRY &dobackup
IF &dobackup
(
PRINT ""
PRINT "========================================"
PRINT "Backing Up Flash"
PRINT "========================================"
PRINT ""
PRINT "Saving to: &backupdir/t1040_backup.bin"
PRINT "Saving flash (128 MB) - this will take several minutes..."
PRINT ""
Data.SAVE.Binary &backupdir/t1040_backup.bin 0xE8000000--0xEFFFFFFF
PRINT "Flash backup saved to: &backupdir/t1040_backup.bin"
PRINT ""
PRINT "First 64 bytes at 0xE8000000 (RCW area):"
Data.dump 0xE8000000++0x3F /Long
PRINT ""
PRINT "========================================"
PRINT "Backup Complete!"
PRINT "========================================"
PRINT ""
PRINT "Verify with: hexdump -C t1040_backup.bin | head -n 8"
PRINT "Valid flash should start with 'AA 55 AA 55' (RCW preamble)"
PRINT ""
GOTO flash_complete
)
ELSE
(
PRINT ""
PRINT "Skipping flash backup"
PRINT ""
)
; ============================================================================
; Option 3: Restore full backup (t1040_backup.bin)
; ============================================================================
DIALOG.YESNO "Restore full backup from &backupdir/t1040_backup.bin (128 MB)?"
ENTRY &restorebackup
IF &restorebackup
(
PRINT ""
PRINT "========================================"
PRINT "Restoring Full Flash Backup"
PRINT "========================================"
PRINT ""
PRINT "Source: &backupdir/t1040_backup.bin"
PRINT "Target: 0xE8000000--0xEFFFFFFF (128 MB)"
PRINT "This will take several minutes..."
PRINT ""
PRINT "Unlocking flash..."
FLASH.UNLOCK 0xE8000000--0xEFFFFFFF
FLASH.ReProgram 0xE8000000--0xEFFFFFFF /Erase
Data.LOAD.binary &backupdir/t1040_backup.bin 0xE8000000
FLASH.ReProgram.off
PRINT ""
PRINT "Verifying restored backup..."
Data.LOAD.binary &backupdir/t1040_backup.bin 0xE8000000 /Verify
PRINT ""
PRINT "Full backup restored and verified"
PRINT ""
PRINT "RCW at 0xE8000000 (should be AA 55 AA 55):"
Data.dump 0xE8000000++0x3F /Long
PRINT ""
GOTO flash_complete
)
ELSE
(
PRINT ""
PRINT "No flash operation selected"
PRINT ""
)
flash_complete:
PRINT ""
PRINT "========================================"
PRINT "Script Complete!"
PRINT "========================================"
PRINT ""
PRINT "Next steps:"
PRINT " 1. Disconnect Lauterbach"
PRINT " 2. Power cycle the board (or toggle reset via Pi4 GPIO 21)"
PRINT " 3. Monitor UART (GENERIC_UART_ttyUSB4) for boot output"
PRINT ""
PRINT "Expected UART output after wolfBoot flash:"
PRINT " Stage1 loader sets up DDR, copies wolfBoot to 0x7FF00000"
PRINT " wolfBoot init"
PRINT ""
ENDDO