From dd96a88fad6576df44d6a4dd37fbaf9f99e6ab59 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 23 Oct 2026 20:32:40 -0700 Subject: [PATCH] Add wolfCrypt test and benchmark for Infineon PSOC Edge E8 --- .github/workflows/infineon-psoc-e8.yml | 82 ++++++ .github/workflows/nightly.yml | 6 + README.md | 11 + embedded/infineon_psoc_e8/.gitignore | 4 + embedded/infineon_psoc_e8/Makefile | 121 +++++++++ embedded/infineon_psoc_e8/README.md | 47 ++++ embedded/infineon_psoc_e8/board.c | 237 ++++++++++++++++++ embedded/infineon_psoc_e8/board.h | 32 +++ .../infineon_psoc_e8/cy_device_headers_s.h | 15 ++ embedded/infineon_psoc_e8/linker.ld | 94 +++++++ embedded/infineon_psoc_e8/main.c | 57 +++++ embedded/infineon_psoc_e8/startup.c | 87 +++++++ embedded/infineon_psoc_e8/tools/flash.sh | 35 +++ .../infineon_psoc_e8/tools/mcuboot_wrap.py | 45 ++++ embedded/infineon_psoc_e8/user_settings.h | 105 ++++++++ 15 files changed, 978 insertions(+) create mode 100644 .github/workflows/infineon-psoc-e8.yml create mode 100644 embedded/infineon_psoc_e8/.gitignore create mode 100644 embedded/infineon_psoc_e8/Makefile create mode 100644 embedded/infineon_psoc_e8/README.md create mode 100644 embedded/infineon_psoc_e8/board.c create mode 100644 embedded/infineon_psoc_e8/board.h create mode 100644 embedded/infineon_psoc_e8/cy_device_headers_s.h create mode 100644 embedded/infineon_psoc_e8/linker.ld create mode 100644 embedded/infineon_psoc_e8/main.c create mode 100644 embedded/infineon_psoc_e8/startup.c create mode 100755 embedded/infineon_psoc_e8/tools/flash.sh create mode 100755 embedded/infineon_psoc_e8/tools/mcuboot_wrap.py create mode 100644 embedded/infineon_psoc_e8/user_settings.h diff --git a/.github/workflows/infineon-psoc-e8.yml b/.github/workflows/infineon-psoc-e8.yml new file mode 100644 index 000000000..d3cecd780 --- /dev/null +++ b/.github/workflows/infineon-psoc-e8.yml @@ -0,0 +1,82 @@ +name: Infineon PSOC Edge E8 + +on: + push: + branches: [master] + paths: + - 'embedded/infineon_psoc_e8/**' + - '.github/workflows/infineon-psoc-e8.yml' + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - 'embedded/infineon_psoc_e8/**' + - '.github/workflows/infineon-psoc-e8.yml' + # No cron: nightly.yml calls this, so the nightly stays one run and one triage writer + workflow_call: + inputs: + caller_run_id: + description: 'run id of the calling workflow; keeps a called run in its own concurrency group' + type: string + default: '' + workflow_dispatch: + +# github.workflow is the CALLER's name in a called workflow, so hardcode ours +concurrency: + group: ${{ inputs.caller_run_id && format('psoc-e8-call-{0}', inputs.caller_run_id) || format('psoc-e8-{0}', github.ref) }} + cancel-in-progress: ${{ !inputs.caller_run_id }} + +permissions: + contents: read + +jobs: + psoc_e8: + name: Build / infineon_psoc_e8 (arm-none-eabi) wolfSSL master + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v5 + + - uses: ./.github/actions/apt-update + - name: Install toolchain + run: | + set -euo pipefail + sudo apt-get install -y --no-install-recommends \ + gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential + + # The Infineon device support is pinned to the releases the example was + # validated with; see embedded/infineon_psoc_e8/README.md. + - name: Fetch wolfSSL and Infineon device support + run: | + set -euo pipefail + clone() { bash "$GITHUB_WORKSPACE/.github/scripts/git-clone-retry.sh" -q --depth 1 --branch "$1" "$2" "$3"; } + clone master https://github.com/wolfSSL/wolfssl /tmp/wolfssl + clone release-v1.8.0 https://github.com/Infineon/mtb-dsl-pse8xxgp /tmp/mtb-dsl-pse8xxgp + clone release-v1.5.0 https://github.com/Infineon/mtb-template-pse8xxgp /tmp/mtb-template-pse8xxgp + clone release-v1.8.0 https://github.com/Infineon/core-lib /tmp/core-lib + clone v6.4.0 https://github.com/ARM-software/CMSIS_6 /tmp/CMSIS_6 + + - name: Build (crypto engine, engine ECDSA verify, software only) + run: | + set -euo pipefail + cd embedded/infineon_psoc_e8 + args="WOLFSSL_ROOT=/tmp/wolfssl PSE84_DSL=/tmp/mtb-dsl-pse8xxgp \ + PSE84_TEMPLATE=/tmp/mtb-template-pse8xxgp CORE_LIB=/tmp/core-lib \ + CMSIS=/tmp/CMSIS_6" + make $args + make $args PSOC_CRYPTO_ECC=1 + make $args PSOC_CRYPTO=0 + + - name: Assert it really cross-compiled + run: | + set -euo pipefail + cd embedded/infineon_psoc_e8 + for elf in Build/wolfcrypt_test.elf Build-ecc/wolfcrypt_test.elf \ + Build-sw/wolfcrypt_bench.elf; do + arch=$(readelf -h "$elf" | awk -F: '/Machine:/ {print $2}' | xargs) + echo "$elf: $arch" + case "$arch" in + *ARM*) ;; + *) echo "FAIL: not an ARM binary: $arch"; exit 1 ;; + esac + done diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 97e567944..36c618fc2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -79,6 +79,12 @@ jobs: with: caller_run_id: ${{ github.run_id }} + infineon-psoc-e8: + needs: [refs] + uses: ./.github/workflows/infineon-psoc-e8.yml + with: + caller_run_id: ${{ github.run_id }} + mynewt: needs: [refs] uses: ./.github/workflows/mynewt.yml diff --git a/README.md b/README.md index 343aa8f37..662146757 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,17 @@ Please see the [riot-os-posix-lwip/README.md](riot-os-posix-lwip/README.md) for further usage and details. +
+ +#### Infineon PSOC Edge E8 (KIT_PSE84_AI) + +This directory contains a bare-metal wolfCrypt test and benchmark for the +PSOC Edge E84 Cortex-M33, using the on-chip crypto engine for SHA and AES, +and its TRNG to seed the DRBG. + +Please see the [embedded/infineon_psoc_e8/README.md](embedded/infineon_psoc_e8/README.md) for further usage and details. + +
#### RT1060 (i.MX RT1060-EVK) diff --git a/embedded/infineon_psoc_e8/.gitignore b/embedded/infineon_psoc_e8/.gitignore new file mode 100644 index 000000000..816ff0b61 --- /dev/null +++ b/embedded/infineon_psoc_e8/.gitignore @@ -0,0 +1,4 @@ +Build/ +Build-sw/ +Build-ecc/ +Build-sw-ecc/ diff --git a/embedded/infineon_psoc_e8/Makefile b/embedded/infineon_psoc_e8/Makefile new file mode 100644 index 000000000..f2f0c516c --- /dev/null +++ b/embedded/infineon_psoc_e8/Makefile @@ -0,0 +1,121 @@ +# Makefile for the wolfCrypt test and benchmark on Infineon PSOC Edge E8 +# +# Target: KIT_PSE84_AI (PSE846GPS2DBZC4A), CM33 Secure, run in place from QSPI +# Usage: make - build wolfcrypt_test and wolfcrypt_bench +# make PSOC_CRYPTO=0 - software only, for comparison +# make PSOC_CRYPTO_ECC=1 - ECDSA verify on the engine as well +# make clean +# +# Copyright (C) 2006-2026 wolfSSL Inc. + +TOOLCHAIN ?= arm-none-eabi- +CC = $(TOOLCHAIN)gcc +OBJCOPY = $(TOOLCHAIN)objcopy +SIZE = $(TOOLCHAIN)size + +WOLFSSL_ROOT ?= ../../../wolfssl + +# Infineon device support, from github.com/Infineon (see README.md). +PSE84_DSL ?= ../../../mtb-dsl-pse8xxgp +PSE84_TEMPLATE ?= ../../../mtb-template-pse8xxgp +CORE_LIB ?= ../../../core-lib +CMSIS ?= ../../../CMSIS_6 +PSE84_PART ?= pse846gps2dbzc4a + +PSOC_CRYPTO ?= 1 +PSOC_CRYPTO_ECC ?= 0 + +BUILD_DIR ?= ./Build$(if $(filter 0,$(PSOC_CRYPTO)),-sw)$(if $(filter 1,$(PSOC_CRYPTO_ECC)),-ecc) + +ARCHFLAGS = -mcpu=cortex-m33 -mthumb -mabi=aapcs + +CFLAGS = $(ARCHFLAGS) -std=gnu99 -Wall -O2 -g +CFLAGS += -ffunction-sections -fdata-sections +CFLAGS += -DWOLFSSL_USER_SETTINGS -DWOLFSSL_IGNORE_FILE_WARN +CFLAGS += -DCOMPONENT_CM33 -DCORE_NAME_CM33_0 -DCOMPONENT_SECURE_DEVICE +CFLAGS += -D$(shell echo $(PSE84_PART) | tr a-z A-Z) +CFLAGS += -DPSE84_PART_HEADER='"$(PSE84_PART)_s.h"' +CFLAGS += -I. -I$(WOLFSSL_ROOT) +CFLAGS += -I$(PSE84_DSL)/pdl/drivers/include +CFLAGS += -I$(PSE84_DSL)/pdl/drivers/third_party/ethernet/include +CFLAGS += -I$(PSE84_DSL)/pdl/devices/include +CFLAGS += -I$(PSE84_DSL)/pdl/devices/include/ip +CFLAGS += -I$(PSE84_TEMPLATE)/files +CFLAGS += -I$(PSE84_TEMPLATE)/files/devices/include +CFLAGS += -I$(CORE_LIB)/include +CFLAGS += -I$(CMSIS)/CMSIS/Core/Include +ifeq ($(PSOC_CRYPTO),1) +CFLAGS += -DWOLFSSL_PSOC6_CRYPTO +endif +ifneq ($(PSOC_CRYPTO_ECC),1) +CFLAGS += -DNO_PSOC6_CRYPTO_ECC +endif + +LDFLAGS = $(ARCHFLAGS) --specs=nano.specs -nostartfiles +LDFLAGS += -Wl,--gc-sections -T./linker.ld +LIBS = -lm + +WOLF = $(WOLFSSL_ROOT)/wolfcrypt/src +SRC_WOLF = $(WOLF)/aes.c $(WOLF)/ecc.c $(WOLF)/error.c $(WOLF)/hash.c \ + $(WOLF)/hmac.c $(WOLF)/logging.c $(WOLF)/memory.c $(WOLF)/misc.c \ + $(WOLF)/random.c $(WOLF)/sha.c $(WOLF)/sha256.c $(WOLF)/sha512.c \ + $(WOLF)/sha3.c $(WOLF)/sp_int.c $(WOLF)/sp_cortexm.c $(WOLF)/wc_port.c \ + $(WOLF)/wolfmath.c $(WOLF)/asn.c $(WOLF)/coding.c $(WOLF)/kdf.c \ + $(WOLF)/wc_encrypt.c $(WOLF)/signature.c \ + $(WOLF)/port/cypress/psoc6_crypto.c + +# PDL crypto core drivers: the engine, its TRNG, and the ECC drivers when +# ECDSA verify runs on the engine. +PDL = $(PSE84_DSL)/pdl/drivers/source +SRC_PDL = $(PDL)/cy_crypto_core_hw.c $(PDL)/cy_crypto_core_mem_v2.c \ + $(PDL)/cy_crypto_core_sha_v2.c $(PDL)/cy_crypto_core_aes_v2.c \ + $(PDL)/cy_crypto_core_vu.c $(PDL)/cy_crypto_core_trng.c +ifeq ($(PSOC_CRYPTO_ECC),1) +SRC_PDL += $(PDL)/cy_crypto_core_ecc_domain_params.c \ + $(PDL)/cy_crypto_core_ecc_nist_p.c $(PDL)/cy_crypto_core_ecc_ecdsa.c \ + $(PDL)/cy_crypto_core_ecc_key_gen.c $(PDL)/cy_crypto_core_ecc_ec25519.c +endif + +SRC_TEST = $(WOLFSSL_ROOT)/wolfcrypt/test/test.c +SRC_BENCH = $(WOLFSSL_ROOT)/wolfcrypt/benchmark/benchmark.c + +objs = $(addprefix $(BUILD_DIR)/$(1)/, $(notdir $(2:.c=.o))) +OBJS_COMMON = $(call objs,common,$(SRC_WOLF) $(SRC_PDL) startup.c board.c) +OBJS_TEST = $(OBJS_COMMON) $(call objs,test,main.c $(SRC_TEST)) +OBJS_BENCH = $(OBJS_COMMON) $(call objs,bench,main.c $(SRC_BENCH)) + +vpath %.c . $(sort $(dir $(SRC_WOLF) $(SRC_PDL) $(SRC_TEST) $(SRC_BENCH))) + +.PHONY: all clean check-deps + +all: check-deps $(BUILD_DIR)/wolfcrypt_test.bin $(BUILD_DIR)/wolfcrypt_bench.bin + $(SIZE) $(BUILD_DIR)/wolfcrypt_test.elf $(BUILD_DIR)/wolfcrypt_bench.elf + +check-deps: + @for d in $(WOLFSSL_ROOT)/wolfcrypt $(PSE84_DSL)/pdl \ + $(PSE84_TEMPLATE)/files $(CORE_LIB)/include $(CMSIS)/CMSIS; do \ + test -d $$d || { echo "missing $$d (see README.md)"; exit 1; }; done + +$(BUILD_DIR)/common/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/test/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD_DIR)/bench/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -DBENCH_APP -c -o $@ $< + +$(BUILD_DIR)/wolfcrypt_test.elf: $(OBJS_TEST) + $(CC) $(LDFLAGS) -Wl,-Map=$(@:.elf=.map) -o $@ $^ $(LIBS) + +$(BUILD_DIR)/wolfcrypt_bench.elf: $(OBJS_BENCH) + $(CC) $(LDFLAGS) -Wl,-Map=$(@:.elf=.map) -o $@ $^ $(LIBS) + +$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf + $(OBJCOPY) -O binary $< $@ + +clean: + rm -rf ./Build ./Build-sw ./Build-ecc ./Build-sw-ecc diff --git a/embedded/infineon_psoc_e8/README.md b/embedded/infineon_psoc_e8/README.md new file mode 100644 index 000000000..41067e0df --- /dev/null +++ b/embedded/infineon_psoc_e8/README.md @@ -0,0 +1,47 @@ +# wolfCrypt on Infineon PSOC Edge E8 + +Bare-metal wolfCrypt test and benchmark for the PSOC Edge E84 Cortex-M33 on the KIT_PSE84_AI board. The example runs in the Secure state as the first CM33 image Infineon's extended boot launches, in place from QSPI. It uses the on-chip crypto engine (MXCRYPTO) through wolfSSL's `WOLFSSL_PSOC6_CRYPTO` port for SHA-1/2/3 and AES (ECB, CBC, CFB, GCM), and seeds the Hash-DRBG from the engine's TRNG. + +## Requirements + +- `arm-none-eabi-gcc` with newlib +- wolfSSL, with PSOC Edge support in the `WOLFSSL_PSOC6_CRYPTO` port +- Infineon device support and CMSIS, at the releases this example was tested with: + +```sh +git clone --depth 1 -b release-v1.8.0 https://github.com/Infineon/mtb-dsl-pse8xxgp +git clone --depth 1 -b release-v1.5.0 https://github.com/Infineon/mtb-template-pse8xxgp +git clone --depth 1 -b release-v1.8.0 https://github.com/Infineon/core-lib +git clone --depth 1 -b v6.4.0 https://github.com/ARM-software/CMSIS_6 +``` + +- ModusToolbox Programming Tools, for OpenOCD and the KitProg3 QSPI flash loader + +## Building + +The Makefile expects wolfSSL and the four repositories above next to `wolfssl-examples`. Override `WOLFSSL_ROOT`, `PSE84_DSL`, `PSE84_TEMPLATE`, `CORE_LIB` and `CMSIS` to point elsewhere. + +```sh +make # Build/wolfcrypt_test.bin and Build/wolfcrypt_bench.bin +make PSOC_CRYPTO=0 # software only, in Build-sw/ +make PSOC_CRYPTO_ECC=1 # ECDSA verify on the engine too, in Build-ecc/ +``` + +Only the PDL crypto core drivers are compiled, so no ModusToolbox project or BSP is needed. `PSE84_PART` selects the part header (default `pse846gps2dbzc4a`). + +## Running + +```sh +tools/flash.sh Build/wolfcrypt_test.bin +tools/flash.sh Build/wolfcrypt_bench.bin +``` + +`tools/flash.sh` wraps the image in the MCUboot-format header that extended boot expects (`tools/mcuboot_wrap.py`) and programs it to QSPI `0x60100000` through the kit's KitProg3. Set `MTB_PROGTOOLS` if the tools are not in `/opt/Tools/ModusToolboxProgtools-1.6`, and `KITPROG_SERIAL` if several probes are attached. Output appears on the KitProg3 COM port at 115200 baud. + +This replaces the factory CM33 image, so read QSPI back first to keep the stock demo. + +## Notes + +- The clocks are left as extended boot sets them: the CM33 at 200 MHz and the console's peripheral clock at 100 MHz. Benchmark timing uses the DWT cycle counter. +- Code and constants run from QSPI through the Secure code-bus alias. The port translates such addresses for the crypto engine, which reads memory over the system bus. +- ECC runs in software with wolfSSL's SP math assembly, which verifies faster than the engine; `PSOC_CRYPTO_ECC=1` moves ECDSA verify to the engine. `WOLFSSL_SP_SMALL` is set because the full-size SP tables are slow to read from XIP flash. diff --git a/embedded/infineon_psoc_e8/board.c b/embedded/infineon_psoc_e8/board.c new file mode 100644 index 000000000..15b1a98c1 --- /dev/null +++ b/embedded/infineon_psoc_e8/board.c @@ -0,0 +1,237 @@ +/* board.c + * + * KIT_PSE84_AI board support: console UART, benchmark time base, TRNG seed + * and heap for the wolfCrypt test and benchmark. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 +#include +#include +#include + +#include "cy_crypto_core.h" +#include "board.h" + +/* Extended boot leaves the clocks running and this example does not change + * them: CLK_HF0 (CM33) at 200 MHz and CLK_HF10 (peripheral group 1) at + * 100 MHz. */ +#ifndef BOARD_CPU_HZ +#define BOARD_CPU_HZ 200000000UL +#endif +#ifndef BOARD_PCLK_HZ +#define BOARD_PCLK_HZ 100000000UL +#endif +#define BOARD_UART_BAUD 115200UL +#define BOARD_UART_OVS 8UL + +/* Console: SCB2 on P6.5 (RX) / P6.7 (TX), the KitProg3 COM port. */ +#define SCB2_BASE 0x529A0000UL +#define UART_PORT 6 +#define UART_RX_PIN 5 +#define UART_TX_PIN 7 +#define UART_HSIOM_SEL 20UL +#define UART_PCLK_GR 1UL /* PCLK_SCB2_CLOCK_SCB_EN = 0x101 */ +#define UART_PCLK_IDX 1UL +#define UART_PCLK_DIV 0UL + +#define REG(a) (*(volatile uint32_t *)(a)) + +#define PERI0_GR_SL_CTL(g) REG(0x52004010UL + ((g) * 0x40UL)) +#define PERI0_GR_SL_CTL2(g) REG(0x52004014UL + ((g) * 0x40UL)) +#define PCLK_GR(g) (0x52040000UL + ((g) * 0x2000UL)) +#define PCLK_DIV_CMD(g) REG(PCLK_GR(g)) +#define PCLK_CLOCK_CTL(g,i) REG(PCLK_GR(g) + 0xC00UL + ((i) * 4UL)) +#define PCLK_DIV_16_5(g,d) REG(PCLK_GR(g) + 0x1800UL + ((d) * 4UL)) +#define HSIOM_PORT_SEL(p,n) REG(0x52800000UL + ((p) * 0x10UL) + \ + (((n) < 4) ? 0x0UL : 0x4UL)) +#define HSIOM_NSMASK(p) REG(0x52801000UL + ((p) * 0x10UL)) +#define GPIO_CFG(p) REG(0x52810000UL + ((p) * 0x80UL) + 0x44UL) + +#define UART_CTRL(b) REG((b) + 0x000UL) +#define UART_UART_CTRL(b) REG((b) + 0x040UL) +#define UART_UART_TX_CTRL(b) REG((b) + 0x044UL) +#define UART_UART_RX_CTRL(b) REG((b) + 0x048UL) +#define UART_TX_CTRL(b) REG((b) + 0x200UL) +#define UART_TX_FIFO_CTRL(b) REG((b) + 0x204UL) +#define UART_TX_FIFO_STAT(b) REG((b) + 0x208UL) +#define UART_TX_FIFO_WR(b) REG((b) + 0x240UL) +#define UART_RX_CTRL(b) REG((b) + 0x300UL) +#define UART_RX_FIFO_CTRL(b) REG((b) + 0x304UL) + +#define DEMCR REG(0xE000EDFCUL) +#define DWT_CTRL REG(0xE0001000UL) +#define DWT_CYCCNT REG(0xE0001004UL) + +static int uart_ready; + +static void pin_setup(uint32_t port, uint32_t pin, uint32_t drive) +{ + uint32_t sh = (pin & 3U) * 8U; + + /* Secure writes to a pin marked non-secure are ignored. */ + HSIOM_NSMASK(port) &= ~(1UL << pin); + HSIOM_PORT_SEL(port, pin) = (HSIOM_PORT_SEL(port, pin) & + ~(0xFFUL << sh)) | (UART_HSIOM_SEL << sh); + GPIO_CFG(port) = (GPIO_CFG(port) & ~(0xFUL << (pin * 4U))) | + (drive << (pin * 4U)); +} + +static void uart_init(void) +{ + uint32_t scaled = (uint32_t)(((uint64_t)BOARD_PCLK_HZ * 32U) / + (BOARD_UART_BAUD * BOARD_UART_OVS)); + uint32_t timeout = 1000000; + + /* PERI0 group 1 holds the SCBs and is partly gated out of extended boot. */ + PERI0_GR_SL_CTL2(1) = 0; + PERI0_GR_SL_CTL(1) = 0xFFFFFFFFUL; + + pin_setup(UART_PORT, UART_RX_PIN, 0x8UL); /* high-Z input */ + pin_setup(UART_PORT, UART_TX_PIN, 0x6UL); /* strong drive */ + + /* 16.5 fractional divider: pclk / (int + 1 + frac / 32). */ + PCLK_DIV_16_5(UART_PCLK_GR, UART_PCLK_DIV) = + (((scaled / 32U) - 1U) << 8) | ((scaled % 32U) << 3); + PCLK_CLOCK_CTL(UART_PCLK_GR, UART_PCLK_IDX) = (2UL << 8) | UART_PCLK_DIV; + PCLK_DIV_CMD(UART_PCLK_GR) = (1UL << 31) | (3UL << 24) | (0xFFUL << 16) | + (2UL << 8) | UART_PCLK_DIV; + while (((PCLK_DIV_16_5(UART_PCLK_GR, UART_PCLK_DIV) & 1U) == 0) && + (timeout > 0)) + timeout--; + if (timeout == 0) + return; /* an unclocked SCB bus-faults, so stay silent */ + + UART_CTRL(SCB2_BASE) = 0; + UART_UART_CTRL(SCB2_BASE) = 0; + UART_UART_TX_CTRL(SCB2_BASE) = 1; + UART_UART_RX_CTRL(SCB2_BASE) = 1; + UART_TX_CTRL(SCB2_BASE) = 7; /* 8 data bits */ + UART_RX_CTRL(SCB2_BASE) = 7; + UART_TX_FIFO_CTRL(SCB2_BASE) = 0x3F; + UART_RX_FIFO_CTRL(SCB2_BASE) = 0x3F; + UART_CTRL(SCB2_BASE) = (1UL << 31) | (2UL << 24) | (BOARD_UART_OVS - 1U); + uart_ready = 1; +} + +static void uart_putc(char c) +{ + uint32_t timeout = 1000000; + + if (!uart_ready) + return; + while (((UART_TX_FIFO_STAT(SCB2_BASE) & 0x1FFU) >= 8U) && (timeout > 0)) + timeout--; + UART_TX_FIFO_WR(SCB2_BASE) = (uint32_t)(uint8_t)c; +} + +void board_init(void) +{ + uart_init(); + DEMCR |= (1UL << 24); /* TRCENA */ + DWT_CYCCNT = 0; + DWT_CTRL |= 1UL; /* CYCCNTENA */ + (void)Cy_Crypto_Core_Enable(CRYPTO); +} + +/* DWT cycle counter extended to 64 bits. It wraps every ~21 s, and each read + * recovers one wrap, which the benchmark's timing windows stay well inside. */ +static uint64_t cycles(void) +{ + static uint64_t hi; + static uint32_t last; + uint32_t now = DWT_CYCCNT; + + if (now < last) + hi += 0x100000000ULL; + last = now; + return hi + now; +} + +double current_time(int reset) +{ + (void)reset; + return (double)cycles() / (double)BOARD_CPU_HZ; +} + +unsigned long board_time(unsigned long *t) +{ + unsigned long s = (unsigned long)(cycles() / BOARD_CPU_HZ); + + if (t != NULL) + *t = s; + return s; +} + +/* Seed the Hash-DRBG from the crypto engine's TRNG, one 32-bit word at a + * time. */ +int board_rng_seed(unsigned char *out, unsigned int sz) +{ + uint32_t rnd; + unsigned int i; + + if (!Cy_Crypto_Core_IsEnabled(CRYPTO) && + (Cy_Crypto_Core_Enable(CRYPTO) != CY_CRYPTO_SUCCESS)) + return -1; + for (i = 0; i < sz; i++) { + if ((i & 3U) == 0U) { + if (Cy_Crypto_Core_Trng_Ext(CRYPTO, 32U, &rnd) != + CY_CRYPTO_SUCCESS) + return -1; + } + out[i] = (unsigned char)(rnd >> ((i & 3U) * 8U)); + } + return 0; +} + +/* newlib hooks: console output, and a heap bounded below the stack. */ +int _write(int fd, const char *buf, int len) +{ + int i; + + (void)fd; + for (i = 0; i < len; i++) { + if (buf[i] == '\n') + uart_putc('\r'); + uart_putc(buf[i]); + } + return len; +} + +void *_sbrk(ptrdiff_t incr) +{ + extern char end; + extern char _heap_limit; + static char *brk = &end; + char *prev = brk; + + if ((brk + incr) > &_heap_limit) { + errno = ENOMEM; + return (void *)-1; + } + brk += incr; + return prev; +} + +int _close(int fd) { (void)fd; return -1; } +int _fstat(int fd, struct stat *st) { (void)fd; st->st_mode = S_IFCHR; return 0; } +int _isatty(int fd) { (void)fd; return 1; } +int _lseek(int fd, int off, int dir) { (void)fd; (void)off; (void)dir; return 0; } +int _read(int fd, char *buf, int len) { (void)fd; (void)buf; (void)len; return 0; } diff --git a/embedded/infineon_psoc_e8/board.h b/embedded/infineon_psoc_e8/board.h new file mode 100644 index 000000000..0dcaf0b4f --- /dev/null +++ b/embedded/infineon_psoc_e8/board.h @@ -0,0 +1,32 @@ +/* board.h + * + * KIT_PSE84_AI board support for the wolfCrypt test and benchmark. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + */ + +#ifndef BOARD_H +#define BOARD_H + +void board_init(void); +double current_time(int reset); +unsigned long board_time(unsigned long *t); +int board_rng_seed(unsigned char *out, unsigned int sz); + +#endif diff --git a/embedded/infineon_psoc_e8/cy_device_headers_s.h b/embedded/infineon_psoc_e8/cy_device_headers_s.h new file mode 100644 index 000000000..19afb3f06 --- /dev/null +++ b/embedded/infineon_psoc_e8/cy_device_headers_s.h @@ -0,0 +1,15 @@ +/* cy_device_headers_s.h + * + * The PSE84 template's cy_device_headers.h includes this file for a Secure + * build; it selects the part header. PSE84_PART_HEADER is set by the + * Makefile. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + */ + +#ifndef CY_DEVICE_HEADERS_S_H +#define CY_DEVICE_HEADERS_S_H + +#include PSE84_PART_HEADER + +#endif diff --git a/embedded/infineon_psoc_e8/linker.ld b/embedded/infineon_psoc_e8/linker.ld new file mode 100644 index 000000000..be9ff0cf6 --- /dev/null +++ b/embedded/infineon_psoc_e8/linker.ld @@ -0,0 +1,94 @@ +/* linker.ld + * + * PSOC Edge E8 CM33 Secure image, run in place from QSPI. + * + * Extended boot launches the image at QSPI 0x60100000 after its 0x400-byte + * MCUboot header, through the Secure code-bus alias 0x18100400. SRAM below + * 0x34002000 is reserved for extended boot and the Secure Enclave. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x18100400, LENGTH = 0x001FFC00 + RAM (rwx) : ORIGIN = 0x34002000, LENGTH = 0x00056000 +} + +_Min_Stack_Size = 0x8000; + +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } > FLASH + + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + KEEP(*(.init)) + KEEP(*(.fini)) + . = ALIGN(4); + } > FLASH + + .ARM.exidx : + { + *(.ARM.exidx*) + } > FLASH + + .preinit_array : + { + PROVIDE_HIDDEN(__preinit_array_start = .); + KEEP(*(.preinit_array*)) + PROVIDE_HIDDEN(__preinit_array_end = .); + } > FLASH + .init_array : + { + PROVIDE_HIDDEN(__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array*)) + PROVIDE_HIDDEN(__init_array_end = .); + } > FLASH + .fini_array : + { + PROVIDE_HIDDEN(__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array*)) + PROVIDE_HIDDEN(__fini_array_end = .); + } > FLASH + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data*) + . = ALIGN(4); + _edata = .; + } > RAM AT > FLASH + + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } > RAM + + /* Heap from here up to the stack. */ + . = ALIGN(8); + PROVIDE(end = .); + PROVIDE(_end = .); + + _estack = ORIGIN(RAM) + LENGTH(RAM); + _heap_limit = _estack - _Min_Stack_Size; + ASSERT(end < _heap_limit, "no room left for the heap") +} diff --git a/embedded/infineon_psoc_e8/main.c b/embedded/infineon_psoc_e8/main.c new file mode 100644 index 000000000..ec908c929 --- /dev/null +++ b/embedded/infineon_psoc_e8/main.c @@ -0,0 +1,57 @@ +/* main.c + * + * wolfCrypt test or benchmark on the PSOC Edge E8 CM33. + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + +#include +#include +#include +#include + +#include "board.h" + +int main(void) +{ + int ret; + + board_init(); + printf("\nwolfCrypt on PSOC Edge E8 (CM33), crypto engine %s\n", +#ifdef WOLFSSL_PSOC6_CRYPTO + "enabled" +#else + "disabled" +#endif + ); + + ret = wolfCrypt_Init(); + if (ret == 0) { +#ifdef BENCH_APP + ret = benchmark_test(NULL); +#else + ret = wolfcrypt_test(NULL); +#endif + wolfCrypt_Cleanup(); + } + printf("%s: %d\n", (ret == 0) ? "Done" : "Failed", ret); + return ret; +} diff --git a/embedded/infineon_psoc_e8/startup.c b/embedded/infineon_psoc_e8/startup.c new file mode 100644 index 000000000..764ecb0a9 --- /dev/null +++ b/embedded/infineon_psoc_e8/startup.c @@ -0,0 +1,87 @@ +/* startup.c + * + * Vector table and reset handler for the PSOC Edge E8 CM33 (Secure). + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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 + +extern uint32_t _estack; +extern uint32_t _sidata, _sdata, _edata; +extern uint32_t _sbss, _ebss; +extern void __libc_init_array(void); +extern int main(void); + +void Reset_Handler(void); +void Default_Handler(void); +void HardFault_Handler(void); + +/* Extended boot has already set VTOR to this table and left the clocks + * running, so the reset handler only has to set up the C runtime. */ +void Reset_Handler(void) +{ + uint32_t *src = &_sidata; + uint32_t *dst; + + for (dst = &_sdata; dst < &_edata; dst++) + *dst = *src++; + for (dst = &_sbss; dst < &_ebss; dst++) + *dst = 0; + + __libc_init_array(); + (void)main(); + while (1) + ; +} + +/* Called by __libc_init_array; nothing to do without crt0. */ +void _init(void) {} +void _fini(void) {} + +void Default_Handler(void) +{ + while (1) + ; +} + +void HardFault_Handler(void) +{ + while (1) + ; +} + +/* Exceptions only; the example uses no interrupts. */ +__attribute__((section(".isr_vector"), used)) +void (* const g_pfnVectors[16])(void) = { + (void (*)(void))&_estack, + Reset_Handler, + Default_Handler, /* NMI */ + HardFault_Handler, + Default_Handler, /* MemManage */ + Default_Handler, /* BusFault */ + Default_Handler, /* UsageFault */ + Default_Handler, /* SecureFault */ + 0, 0, 0, + Default_Handler, /* SVCall */ + Default_Handler, /* DebugMonitor */ + 0, + Default_Handler, /* PendSV */ + Default_Handler, /* SysTick */ +}; diff --git a/embedded/infineon_psoc_e8/tools/flash.sh b/embedded/infineon_psoc_e8/tools/flash.sh new file mode 100755 index 000000000..8dcfb71c3 --- /dev/null +++ b/embedded/infineon_psoc_e8/tools/flash.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Wrap an image with the extended-boot header and program it to QSPI +# 0x60100000 on KIT_PSE84_AI through the on-board KitProg3. +# +# Usage: tools/flash.sh Build/wolfcrypt_test.bin +# +# Environment: MTB_PROGTOOLS (default /opt/Tools/ModusToolboxProgtools-1.6), +# KITPROG_SERIAL to pick the probe when several are attached. + +set -e + +IMG=${1:?usage: $0 image.bin} +MTB_PROGTOOLS=${MTB_PROGTOOLS:-/opt/Tools/ModusToolboxProgtools-1.6} +OCD=$MTB_PROGTOOLS/openocd +SCRIPTS=$MTB_PROGTOOLS/mtb-programmer/scripts +HERE=$(cd "$(dirname "$0")" && pwd) + +WRAPPED=$(mktemp --suffix=.bin) +trap 'rm -f "$WRAPPED"' EXIT +python3 "$HERE/mcuboot_wrap.py" "$IMG" "$WRAPPED" + +SERIAL_ARGS=() +if [ -n "$KITPROG_SERIAL" ]; then + SERIAL_ARGS=(-c "adapter serial $KITPROG_SERIAL") +fi + +# "reset run" would leave the part in KitProg3 acquire mode. +"$OCD/bin/openocd" -s "$OCD/scripts" -s "$SCRIPTS" \ + -c "set SCRIPTS_DIR $SCRIPTS" \ + -f interface/kitprog3.cfg "${SERIAL_ARGS[@]}" -c "transport select swd" \ + -f CAT1D/kit_PSE84_AI_external.cfg \ + -c "init; reset init" \ + -c "flash write_image erase $WRAPPED 0x60100000 bin" \ + -c "verify_image $WRAPPED 0x60100000 bin" \ + -c "reset halt; resume; shutdown" diff --git a/embedded/infineon_psoc_e8/tools/mcuboot_wrap.py b/embedded/infineon_psoc_e8/tools/mcuboot_wrap.py new file mode 100755 index 000000000..2ad772752 --- /dev/null +++ b/embedded/infineon_psoc_e8/tools/mcuboot_wrap.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Wrap an image for the PSOC Edge E8 extended boot. + +Extended boot expects the first CM33 image in MCUboot format: a 0x400-byte +header, the image, and a TLV area with the SHA-256 of both. No key is used. +The output matches the factory image byte for byte. + +Usage: mcuboot_wrap.py image.bin image_mcuboot.bin +""" + +import hashlib +import struct +import sys + +IMAGE_MAGIC = 0x96F3B83D +TLV_INFO_MAGIC = 0x6907 +TLV_SHA256 = 0x10 +HDR_SIZE = 0x400 + + +def wrap(img): + # magic, load_addr, hdr_size, protect_tlv_size, img_size, flags, + # version (major, minor, revision, build), pad + hdr = struct.pack('