Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,12 @@ jobs:
arch: arm
config-file: ./config/examples/nxp-s32k148.config

nxp_mcxe247_test:
uses: ./.github/workflows/test-build.yml
with:
arch: arm
config-file: ./config/examples/mcxe247.config

max32666_test:
uses: ./.github/workflows/test-build.yml
with:
Expand Down
75 changes: 75 additions & 0 deletions config/examples/mcxe247.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# wolfBoot configuration for NXP MCX E247 (FRDM-MCXE247)
#
# MCXE247: Cortex-M4F, 2MB flash (1.5MB Program Flash + 512KB FlexNVM), 256KB
# SRAM. It is register compatible with the S32K148 and uses the s32k1xx HAL.
# Default: RUN mode at 48 MHz (FIRC - internal RC oscillator)
#
# Build: cp config/examples/mcxe247.config .config && make

ARCH?=ARM
CORTEX_M4?=1
NO_MPU=1
TARGET?=s32k1xx
SIGN?=ECC256
HASH?=SHA256
VTOR?=1
NO_ASM?=0
EXT_FLASH?=0
SPI_FLASH?=0
ALLOW_DOWNGRADE?=0

# Flash can be programmed only once between erases
NVM_FLASH_WRITEONCE?=1

WOLFBOOT_VERSION?=0
V?=0
SPMATH?=1
RAM_CODE?=1
DUALBANK_SWAP?=0

# Select the MCXE247 variant. SRAM is ECC protected and holds no valid ECC after
# power-on. WOLFBOOT_RAM_ECC_INIT clears the SRAM the bootloader uses
# (0x1FFFC000-0x20002FFF) at reset so its ECC is valid. The rest of SRAM is the
# application's to initialize.
CFLAGS_EXTRA+=-DMCXE247 -DWOLFBOOT_RAM_ECC_INIT

# 4KB sectors
WOLFBOOT_SECTOR_SIZE?=0x1000

# Memory layout (Program Flash 0x00000000 - 0x0017FFFF):
# Bootloader: 0x00000000 - 0x0000BFFF (48 KB)
# Boot Partition: 0x0000C000 - 0x000C3FFF (736 KB)
# Update Partition: 0x000C4000 - 0x0017BFFF (736 KB)
# Swap Sector: 0x0017C000 - 0x0017CFFF (4 KB)
WOLFBOOT_PARTITION_SIZE?=0xB8000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xC000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xC4000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x17C000

# Console on the MCU-Link VCOM port: LPUART2, PTE12 (TX) and PTD17 (RX), ALT3
CFLAGS_EXTRA+=-DDEBUG_UART_NUM=2
CFLAGS_EXTRA+=-DDEBUG_UART_TX_PORT=S32K_PORT_E -DDEBUG_UART_TX_PIN=12
CFLAGS_EXTRA+=-DDEBUG_UART_TX_MUX=PORT_PCR_MUX_ALT3
CFLAGS_EXTRA+=-DDEBUG_UART_RX_PORT=S32K_PORT_D -DDEBUG_UART_RX_PIN=17
CFLAGS_EXTRA+=-DDEBUG_UART_RX_MUX=PORT_PCR_MUX_ALT3

# wolfIP network test in the test-app (optional)
# Adds the "network" console command. Needs a wolfIP checkout and an MCUXpresso
# SDK (for the fsl_enet driver).
ENABLE_WOLFIP?=0
WOLFBOOT_LIB_WOLFIP?=../lib/wolfip
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk
# Without WOLFBOOT_TEST_TFTP the command only acquires a DHCP lease. The file
# must fit the 40 KB receive buffer.
WOLFBOOT_TEST_TFTP?=1
CFLAGS_EXTRA+=-DHOST_IP_STR='"192.168.50.1"' -DTFTP_FILENAME='"wolfip_test.bin"'
# WOLFIP_SPEED_TEST=1 makes the command run a TCP throughput server on port 9
# instead (it never returns; reset the board to stop it). WOLFBOOT_TEST_TFTP
# overrides it: with both set to 1 the command runs the TFTP fetch and the speed
# server is never started.
WOLFIP_SPEED_TEST?=0

# Debugging options
DEBUG?=0
DEBUG_SYMBOLS?=0
DEBUG_UART?=1
16 changes: 8 additions & 8 deletions config/examples/nxp-s32k148.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# wolfBoot configuration for NXP S32K148
#
# S32K148: Cortex-M4F, 2MB Flash, 256KB SRAM
# S32K148: Cortex-M4F, 2MB flash (1.5MB Program Flash + 512KB FlexNVM), 256KB SRAM
# Flash sector size: 4KB (larger flash variants use 4KB sectors)
# Default: RUN mode at 48 MHz (FIRC - internal RC oscillator)
#
Expand Down Expand Up @@ -34,15 +34,15 @@ CFLAGS_EXTRA+=-DS32K148
# 4KB sectors (S32K144/146/148 with 512KB+ flash)
WOLFBOOT_SECTOR_SIZE?=0x1000

# Memory layout for S32K148 (2MB Flash):
# Memory layout for S32K148 (Program Flash 0x00000000 - 0x0017FFFF):
# Bootloader: 0x00000000 - 0x0000BFFF (48 KB)
# Boot Partition: 0x0000C000 - 0x000FBFFF (960 KB)
# Update Partition: 0x000FC000 - 0x001EBFFF (960 KB)
# Swap Sector: 0x001EC000 - 0x001ECFFF (4 KB)
WOLFBOOT_PARTITION_SIZE?=0xF0000
# Boot Partition: 0x0000C000 - 0x000C3FFF (736 KB)
# Update Partition: 0x000C4000 - 0x0017BFFF (736 KB)
# Swap Sector: 0x0017C000 - 0x0017CFFF (4 KB)
WOLFBOOT_PARTITION_SIZE?=0xB8000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xC000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xFC000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x1EC000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xC4000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x17C000

# Clock mode: Default is RUN mode with FIRC (48 MHz internal RC)
# To enable HSRUN mode (112 MHz), uncomment below (requires SOSC + SPLL, not fully implemented):
Expand Down
115 changes: 114 additions & 1 deletion docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ This README describes configuration of supported targets.
* [NXP MCXN947](#nxp-mcxn947)
* [NXP RW612](#nxp-rw612)
* [NXP S32K1XX](#nxp-s32k1xx)
* [NXP MCXE247](#nxp-mcxe247)
* [NXP P1021 PPC](#nxp-qoriq-p1021-ppc)
* [NXP T10xx PPC (T1024 / T1040)](#nxp-qoriq-t10xx-ppc-t1024--t1040)
* [NXP T2080 PPC](#nxp-qoriq-t2080-ppc)
Expand Down Expand Up @@ -7130,7 +7131,7 @@ Example configuration files:
- [/config/examples/nxp-s32k142.config](/config/examples/nxp-s32k142.config) - S32K142 (256KB Flash, 32KB SRAM)
- [/config/examples/nxp-s32k144.config](/config/examples/nxp-s32k144.config) - S32K144 (512KB Flash, 64KB SRAM)
- [/config/examples/nxp-s32k146.config](/config/examples/nxp-s32k146.config) - S32K146 (1MB Flash, 128KB SRAM)
- [/config/examples/nxp-s32k148.config](/config/examples/nxp-s32k148.config) - S32K148 (2MB Flash, 256KB SRAM)
- [/config/examples/nxp-s32k148.config](/config/examples/nxp-s32k148.config) - S32K148 (1.5MB Program Flash + 512KB FlexNVM, 256KB SRAM)

```sh
# Copy configuration (example for S32K142)
Expand Down Expand Up @@ -7314,6 +7315,118 @@ cmd>
- [ ] **CAN/LIN bootloader**: Add firmware update over CAN or LIN bus for automotive applications


## NXP MCXE247

The NXP MCX E247 is a Cortex-M4F microcontroller that is register compatible
with the S32K148 (NXP AN14731), so it uses the bare-metal `s32k1xx` HAL with the
`MCXE247` variant. No SDK is needed. The port targets the FRDM-MCXE247 board.

The 2 MB of flash is not contiguous: 1.5 MB of Program Flash is at `0x00000000`
and the remaining 512 KB is FlexNVM at `0x10000000`. Only the Program Flash is
used. The system runs at 48 MHz (FIRC). Flash cannot be programmed in HSRUN.

### NXP MCXE247: Memory Layout

| Region | Address Range | Size |
|--------|---------------|------|
| Bootloader | 0x00000000 - 0x0000BFFF | 48 KB |
| Boot Partition | 0x0000C000 - 0x000C3FFF | 736 KB |
| Update Partition | 0x000C4000 - 0x0017BFFF | 736 KB |
| Swap Sector | 0x0017C000 - 0x0017CFFF | 4 KB |

### NXP MCXE247: Building

```sh
cp config/examples/mcxe247.config .config
make
```

The console is on the MCU-Link VCOM port (LPUART2, PTE12 TX, PTD17 RX, 115200
8N1). The test application shows green on the RGB LED for version 1 and blue
for later versions, and has the same console as the
[S32K1xx test application](#nxp-s32k1xx-test-application).

### NXP MCXE247: Configuration Options

The [S32K1xx configuration options](#nxp-s32k1xx-configuration-options) also
apply to the MCXE247, with these differences:

- Select the variant with `MCXE247` instead of `S32K144`, `S32K146` or `S32K148`.
- The console is on LPUART2, not LPUART1. `mcxe247.config` selects it with
`DEBUG_UART_NUM=2` and the `DEBUG_UART_TX_*` and `DEBUG_UART_RX_*` pin
settings.
- `mcxe247.config` also sets `WOLFBOOT_RAM_ECC_INIT`. The bootloader then
clears the SRAM it uses (the S32K142 layout of `hal/s32k1xx.ld`) at reset,
so the ECC of that RAM is valid. It does not clear
the rest of the 252 KB, so an application that enables ERM interrupts must
write its RAM before reading it. The network test app clears all of SRAM_U at
reset (`APP_RAM_ECC_INIT`).

### NXP MCXE247: Network test

The test application can run a wolfIP DHCP and TFTP test over the board's
Ethernet port. This is optional and is the only part of the port that needs the
MCUXpresso SDK, which provides the `fsl_enet` driver. Set `ENABLE_WOLFIP=1` in
`mcxe247.config`, check the wolfIP and SDK paths, then set the TFTP server and
file:

```sh
ENABLE_WOLFIP?=1
WOLFBOOT_LIB_WOLFIP?=../lib/wolfip
MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk
WOLFBOOT_TEST_TFTP?=1
CFLAGS_EXTRA+=-DHOST_IP_STR='"192.168.50.1"' -DTFTP_FILENAME='"wolfip_test.bin"'
```

Type `network` on the console to run the test. It acquires a DHCP lease, fetches
the file into RAM (40 KB at most), and prints its size and checksum followed by
`WOLFIP_TEST: PASS` or `WOLFIP_TEST: FAIL`.

To measure throughput instead, set `WOLFBOOT_TEST_TFTP=0` and
`WOLFIP_SPEED_TEST=1`. After the DHCP lease, the `network` command runs a TCP
server on port 9 that discards what it receives and sends data whenever the
connection can take it. It prints the receive and transmit rates when the
connection closes. Drive it from the PC with `<ip>` set to the address the board
printed:

```sh
# board receives
dd if=/dev/zero bs=1460 count=10000 | nc <ip> 9
# board sends
nc <ip> 9 </dev/null | pv -r >/dev/null
```

The server never returns to the console; reset the board to stop it.
`WOLFBOOT_TEST_TFTP` takes priority: with both options set to 1, the command
runs the TFTP fetch and the speed server is never started.

### NXP MCXE247: Programming with Lauterbach TRACE32

Connect the 10-pin debug cable to J14 and short JP4 to disable the onboard
MCU-Link SWD. If TRACE32 has no MCXE247 entry, use `SYStem.CPU S32K148`.
Program `factory.bin` at `0x00000000`.

Scripts for this are in `tools/scripts/mcxe247`. They find the build output
relative to their own location, so run them from the wolfBoot checkout, for
example `DO <wolfBoot>/tools/scripts/mcxe247/e247_flash_factory_bin.cmm`:

| Script | Purpose |
|--------|---------|
| `e247_debug.cmm` | Reset and halt the CPU, then load the `wolfboot.elf` and `test-app/image.elf` symbols. Takes the MCUXpresso SDK path as an optional argument, used to find the ENET driver sources (default: `../NXP/mcuxpresso-sdk/mcuxsdk` next to the checkout) |
| `e247_flash_factory_bin.cmm` | Program `factory.bin`, erase the update partition and swap sector, then reset and detach |
| `e247_flash_update.cmm` | Program `test-app/image_v2_signed.bin` into the update partition, then reset and detach |

Each script writes a log to the TRACE32 system directory (`~~`).

`factory.bin` includes the Flash Configuration Field at `0x400`. Its security
byte at `0x40C` must be programmed to `0xFE`: an erased byte secures the chip
at the next reset, and only a mass erase recovers it.

While TRACE32 is attached, it halts the CPU at the reset vector on every reset.
Detach with `SYStem.Down` before testing an update, which relies on a software
reset.


## TI Hercules TMS570LC435

See [/config/examples/ti-tms570lc435.config](/config/examples/ti-tms570lc435.config) for example configuration.
Expand Down
15 changes: 8 additions & 7 deletions hal/s32k1xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*
* HAL for NXP S32K1xx (S32K142, S32K144, S32K146, S32K148)
* HAL for NXP S32K1xx (S32K142, S32K144, S32K146, S32K148) and the register
* compatible NXP MCX E247.
* Tested on S32K142: Cortex-M4F, 256KB Flash, 32KB SRAM
*/

Expand Down Expand Up @@ -304,9 +305,9 @@ void uart_init(void)
/* Transmit a single byte (raw, no conversion) - RAMFUNCTION for use during flash ops */
void RAMFUNCTION uart_tx(uint8_t byte)
{
while (!(LPUART1_STAT & LPUART_STAT_TDRE)) {}
LPUART1_DATA = byte;
while (!(LPUART1_STAT & LPUART_STAT_TC)) {}
while (!(LPUART_STAT & LPUART_STAT_TDRE)) {}
LPUART_DATA = byte;
while (!(LPUART_STAT & LPUART_STAT_TC)) {}
}

/* Used for sending ASCII and CRLF conversions */
Expand All @@ -330,16 +331,16 @@ void uart_write(const char* buf, unsigned int sz)
*/
int RAMFUNCTION uart_read(char* c)
{
uint32_t stat = LPUART1_STAT;
uint32_t stat = LPUART_STAT;

/* Clear any error flags first */
if (stat & (LPUART_STAT_OR | LPUART_STAT_NF | LPUART_STAT_FE | LPUART_STAT_PF)) {
LPUART1_STAT = stat; /* Write 1 to clear flags */
LPUART_STAT = stat; /* Write 1 to clear flags */
}

/* Check if data available - read even if there was an error */
if (stat & LPUART_STAT_RDRF) {
*c = (char)(LPUART1_DATA & 0xFF);
*c = (char)(LPUART_DATA & 0xFF);
return 1;
}

Expand Down
Loading
Loading