Skip to content
Open
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
74 changes: 74 additions & 0 deletions config/examples/mcxe247.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 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. Clearing it at reset keeps the ECC valid, so the ERM records no
# errors and its interrupts can be enabled safely.
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
111 changes: 110 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,114 @@ 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`, which clears SRAM at reset
so its ECC is valid.

### 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
60 changes: 51 additions & 9 deletions hal/s32k1xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
#define PCC_LPUART0 (*(volatile uint32_t *)(PCC_BASE + 0x1A8UL))
#define PCC_LPUART1 (*(volatile uint32_t *)(PCC_BASE + 0x1ACUL))
#define PCC_LPUART2 (*(volatile uint32_t *)(PCC_BASE + 0x1B0UL))
#define PCC_FTFC (*(volatile uint32_t *)(PCC_BASE + 0x0B0UL))
#define PCC_FTFC (*(volatile uint32_t *)(PCC_BASE + 0x080UL))

#define PCC_CGC (1UL << 30) /* Clock Gate Control */
#define PCC_PCS_SHIFT 24
Expand Down Expand Up @@ -242,10 +242,46 @@
#define PORT_PCR_MUX_ALT6 (6UL << PORT_PCR_MUX_SHIFT) /* Alternate function 6 */
#define PORT_PCR_MUX_ALT7 (7UL << PORT_PCR_MUX_SHIFT) /* Alternate function 7 */

/* S32K142EVB LED pins (accent RGB LED accent accent accent accent LED accent accent accent-low accent LED) */
#define LED_PIN_BLUE 0 /* PTD0 - Blue LED (active low) */
#define LED_PIN_RED 15 /* PTD15 - Red LED (active low) */
#define LED_PIN_GREEN 16 /* PTD16 - Green LED (active low) */
/* GPIO port base addresses */
#define GPIOB_BASE (0x400FF040UL)
#define GPIOC_BASE (0x400FF080UL)

/* GPIO registers by port base address */
#define GPIO_PSOR(base) (*(volatile uint32_t *)((base) + 0x04UL))
#define GPIO_PCOR(base) (*(volatile uint32_t *)((base) + 0x08UL))
#define GPIO_PTOR(base) (*(volatile uint32_t *)((base) + 0x0CUL))
#define GPIO_PDDR(base) (*(volatile uint32_t *)((base) + 0x14UL))

/* RGB LED pins (all active low) */
#ifdef MCXE247
/* FRDM-MCXE247 D1: PTC12 blue, PTC13 red, PTB11 green */
#define LED_PIN_BLUE 12
#define LED_PIN_RED 13
#define LED_PIN_GREEN 11
#define LED_BLUE_GPIO GPIOC_BASE
#define LED_RED_GPIO GPIOC_BASE
#define LED_GREEN_GPIO GPIOB_BASE
#define LED_BLUE_PCC PCC_PORTC
#define LED_RED_PCC PCC_PORTC
#define LED_GREEN_PCC PCC_PORTB
#define LED_BLUE_PCR PORTC_PCR(LED_PIN_BLUE)
#define LED_RED_PCR PORTC_PCR(LED_PIN_RED)
#define LED_GREEN_PCR PORTB_PCR(LED_PIN_GREEN)
#else
/* S32K142EVB: PTD0 blue, PTD15 red, PTD16 green */
#define LED_PIN_BLUE 0
#define LED_PIN_RED 15
#define LED_PIN_GREEN 16
#define LED_BLUE_GPIO GPIOD_BASE
#define LED_RED_GPIO GPIOD_BASE
#define LED_GREEN_GPIO GPIOD_BASE
#define LED_BLUE_PCC PCC_PORTD
#define LED_RED_PCC PCC_PORTD
#define LED_GREEN_PCC PCC_PORTD
#define LED_BLUE_PCR PORTD_PCR(LED_PIN_BLUE)
#define LED_RED_PCR PORTD_PCR(LED_PIN_RED)
#define LED_GREEN_PCR PORTD_PCR(LED_PIN_GREEN)
#endif

/* ============== LPUART Registers ============== */

Expand Down Expand Up @@ -350,18 +386,21 @@
#define LPUART_CTRL LPUART0_CTRL
#define LPUART_DATA LPUART0_DATA
#define PCC_LPUART PCC_LPUART0
#define LPUART_IRQn LPUART0_IRQn
#elif DEBUG_UART_NUM == 2
#define LPUART_BAUD LPUART2_BAUD
#define LPUART_STAT LPUART2_STAT
#define LPUART_CTRL LPUART2_CTRL
#define LPUART_DATA LPUART2_DATA
#define PCC_LPUART PCC_LPUART2
#define LPUART_IRQn LPUART2_IRQn
#else /* DEBUG_UART_NUM == 1 (default) */
#define LPUART_BAUD LPUART1_BAUD
#define LPUART_STAT LPUART1_STAT
#define LPUART_CTRL LPUART1_CTRL
#define LPUART_DATA LPUART1_DATA
#define PCC_LPUART PCC_LPUART1
#define LPUART_IRQn LPUART1_IRQn
#endif

/* Port identifier values for preprocessor comparisons */
Expand Down Expand Up @@ -508,16 +547,19 @@
* S32K142: 256KB Flash (0x00000 - 0x3FFFF), 32KB SRAM, 2KB sectors
* S32K144: 512KB Flash (0x00000 - 0x7FFFF), 64KB SRAM, 4KB sectors
* S32K146: 1MB Flash (0x00000 - 0xFFFFF), 128KB SRAM, 4KB sectors
* S32K148: 2MB Flash (0x00000 - 0x1FFFFF), 256KB SRAM, 4KB sectors
* S32K148: 1.5MB Program Flash (0x00000 - 0x17FFFF), 256KB SRAM, 4KB sectors
* MCXE247: Same memory as the S32K148 and register compatible (NXP AN14731).
* The other 512KB of the 2MB on both parts is FlexNVM at 0x10000000
* and is not used here.
*
* IMPORTANT: Flash sector size depends on total flash size:
* - 256KB Flash (S32K142): 2KB sectors
* - 512KB+ Flash (S32K144/146/148): 4KB sectors
* - 512KB+ Flash (S32K144/146/148, MCXE247): 4KB sectors
*
* All variants use 8-byte phrase programming.
*/
#if defined(S32K148)
#define FLASH_SIZE (2048 * 1024) /* 2MB */
#if defined(S32K148) || defined(MCXE247)
#define FLASH_SIZE (1536 * 1024) /* 1.5MB Program Flash */
#define SRAM_SIZE (256 * 1024) /* 256KB */
#define FLASH_SECTOR_SIZE 4096 /* 4KB sectors */
#elif defined(S32K146)
Expand Down
Loading
Loading