diff --git a/.github/workflows/examples-k32w.yaml b/.github/workflows/examples-k32w.yaml
index 0a79f70a125b72..1f9c2f5871c8b6 100644
--- a/.github/workflows/examples-k32w.yaml
+++ b/.github/workflows/examples-k32w.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-name: Build example - K32W with SE051
+name: Build example - K32W
on:
push:
@@ -37,7 +37,7 @@ jobs:
if: github.actor != 'restyled-io[bot]'
container:
- image: ghcr.io/project-chip/chip-build-k32w:5
+ image: ghcr.io/project-chip/chip-build-k32w:6
volumes:
- "/tmp/bloat_reports:/tmp/bloat_reports"
steps:
@@ -46,7 +46,7 @@ jobs:
- name: Checkout submodules & Bootstrap
uses: ./.github/actions/checkout-submodules-and-bootstrap
with:
- platform: k32w0
+ platform: k32w
- name: Set up environment for size reports
uses: ./.github/actions/setup-size-reports
@@ -58,12 +58,14 @@ jobs:
run: |
scripts/run_in_build_env.sh "\
./scripts/build/build_examples.py \
- --target k32w-light-crypto-platform-tokenizer \
- --target k32w-lock-crypto-platform-tokenizer \
- --target k32w-lock-crypto-platform-low-power-nologs \
- --target k32w-contact-crypto-platform-tokenizer \
- --target k32w-contact-crypto-platform-low-power-nologs \
- --target k32w-shell-crypto-platform \
+ --target k32w-k32w0-light-crypto-platform-tokenizer \
+ --target k32w-k32w0-lock-crypto-platform-tokenizer \
+ --target k32w-k32w0-lock-crypto-platform-low-power-nologs \
+ --target k32w-k32w0-contact-crypto-platform-tokenizer \
+ --target k32w-k32w0-contact-crypto-platform-low-power-nologs \
+ --target k32w-k32w0-shell-crypto-platform \
+ --target k32w-k32w1-light-crypto-platform-openthread-ftd \
+ --target k32w-k32w1-contact-crypto-platform-low-power-nologs \
build \
--copy-artifacts-to out/artifacts \
"
@@ -71,19 +73,27 @@ jobs:
run: |
.environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
k32w k32w0+release light \
- out/artifacts/k32w-light-crypto-platform-tokenizer/chip-k32w0x-light-example \
+ out/artifacts/k32w-k32w0-light-crypto-platform-tokenizer/chip-k32w0x-light-example.elf \
+ /tmp/bloat_reports/
+ .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+ k32w k32w1+release light \
+ out/artifacts/k32w-k32w1-light-crypto-platform-openthread-ftd/chip-k32w1-light-example.elf \
/tmp/bloat_reports/
- name: Get lock size stats
run: |
.environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
k32w k32w0+release lock \
- out/artifacts/k32w-lock-crypto-platform-tokenizer/chip-k32w0x-lock-example \
+ out/artifacts/k32w-k32w0-lock-crypto-platform-tokenizer/chip-k32w0x-lock-example.elf \
/tmp/bloat_reports/
- name: Get contact size stats
run: |
.environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
k32w k32w0+release contact \
- out/artifacts/k32w-contact-crypto-platform-tokenizer/chip-k32w0x-contact-example \
+ out/artifacts/k32w-k32w0-contact-crypto-platform-tokenizer/chip-k32w0x-contact-example.elf \
+ /tmp/bloat_reports/
+ .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+ k32w k32w1+release contact \
+ out/artifacts/k32w-k32w1-contact-crypto-platform-low-power-nologs/chip-k32w1-contact-example.elf \
/tmp/bloat_reports/
- name: Uploading Size Reports
uses: ./.github/actions/upload-size-reports
diff --git a/.gitmodules b/.gitmodules
index b5d7c5dc253ca2..6ebfd6dbad7141 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -54,16 +54,16 @@
path = third_party/freertos/repo
url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git
branch = V10.3.1-kernel-only
- platforms = ameba,cc13xx_26xx,bouffalolab,efr32,esp32,k32w0,infineon,qpg,cc32xx,silabs_docker
+ platforms = ameba,cc13xx_26xx,bouffalolab,efr32,esp32,k32w,infineon,qpg,cc32xx,silabs_docker
[submodule "simw-top-mini"]
path = third_party/simw-top-mini/repo
url = https://github.com/NXP/plug-and-trust.git
branch = int/CHIPSE_Release
- platforms = k32w0
+ platforms = k32w
[submodule "third_party/openthread/ot-nxp"]
path = third_party/openthread/ot-nxp
url = https://github.com/openthread/ot-nxp.git
- platforms = k32w0
+ platforms = k32w
[submodule "third_party/openthread/ot-qorvo"]
path = third_party/openthread/ot-qorvo
url = https://github.com/openthread/ot-qorvo.git
diff --git a/build_overrides/k32w1_sdk.gni b/build_overrides/k32w1_sdk.gni
new file mode 100644
index 00000000000000..2f4f2320937360
--- /dev/null
+++ b/build_overrides/k32w1_sdk.gni
@@ -0,0 +1,18 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+ # Root directory for K32W SDK build files.
+ k32w1_sdk_build_root = "//third_party/nxp/k32w1_sdk"
+}
diff --git a/examples/build_overrides/k32w1_sdk.gni b/examples/build_overrides/k32w1_sdk.gni
new file mode 100644
index 00000000000000..ab4655d7717f9a
--- /dev/null
+++ b/examples/build_overrides/k32w1_sdk.gni
@@ -0,0 +1,19 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+ # Root directory for k32w SDK.
+ k32w1_sdk_build_root =
+ "//third_party/connectedhomeip/third_party/nxp/k32w1_sdk"
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/.gn b/examples/contact-sensor-app/nxp/k32w/k32w1/.gn
new file mode 100644
index 00000000000000..dec954b4b9ff69
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020-2023 Project CHIP Authors
+# Copyright (c) 2023 NXP
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+
+ import("//args.gni")
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn
new file mode 100644
index 00000000000000..1404ad8dd36a1c
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn
@@ -0,0 +1,136 @@
+# Copyright (c) 2021-2023 Project CHIP Authors
+# Copyright (c) 2023 NXP
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/k32w1_sdk.gni")
+import("//build_overrides/openthread.gni")
+
+import("${k32w1_sdk_build_root}/k32w1_executable.gni")
+import("${k32w1_sdk_build_root}/k32w1_sdk.gni")
+
+import("${chip_root}/src/crypto/crypto.gni")
+import("${chip_root}/src/lib/core/core.gni")
+import("${chip_root}/src/platform/device.gni")
+
+declare_args() {
+ chip_software_version = 0
+}
+
+assert(current_os == "freertos")
+
+k32w1_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w1"
+k32w1_sdk_root = getenv("NXP_K32W1_SDK_ROOT")
+
+k32w1_sdk("sdk") {
+ sources = [
+ "${k32w1_platform_dir}/app/project_include/OpenThreadConfig.h",
+ "include/CHIPProjectConfig.h",
+ "include/FreeRTOSConfig.h",
+ "main/include/app_config.h",
+ ]
+
+ public_deps =
+ [ "${chip_root}/third_party/openthread/platforms:libopenthread-platform" ]
+
+ include_dirs = [
+ "main/include",
+ "main",
+ "include",
+ "${k32w1_platform_dir}/app/project_include",
+ "${k32w1_platform_dir}/app/support",
+ "${k32w1_platform_dir}/util/include",
+ ]
+
+ defines = []
+ if (is_debug) {
+ defines += [ "BUILD_RELEASE=0" ]
+ } else {
+ defines += [ "BUILD_RELEASE=1" ]
+ }
+
+ if (chip_software_version != 0) {
+ defines += [
+ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}",
+ ]
+ }
+}
+
+k32w1_executable("contact_sensor_app") {
+ output_name = "chip-k32w1-contact-example"
+
+ sources = [
+ "${k32w1_platform_dir}/util/LEDWidget.cpp",
+ "${k32w1_platform_dir}/util/include/LEDWidget.h",
+ "main/AppTask.cpp",
+ "main/ContactSensorManager.cpp",
+ "main/ZclCallbacks.cpp",
+ "main/include/AppEvent.h",
+ "main/include/AppTask.h",
+ "main/include/ContactSensorManager.h",
+ "main/main.cpp",
+ ]
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/common/QRCode",
+ "${chip_root}/examples/contact-sensor-app/contact-sensor-common",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/platform:syscalls_stub",
+ "${chip_root}/third_party/mbedtls:mbedtls",
+ "${k32w1_platform_dir}/app/support:freertos_mbedtls_utils",
+ ]
+
+ if (chip_openthread_ftd) {
+ deps += [
+ "${chip_root}/third_party/openthread/repo:libopenthread-cli-ftd",
+ "${chip_root}/third_party/openthread/repo:libopenthread-ftd",
+ ]
+ } else {
+ deps += [
+ "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
+ "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
+ ]
+ }
+
+ cflags = [ "-Wconversion" ]
+
+ output_dir = root_out_dir
+
+ ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [
+ "-Wl,--defsym=__heap_size__=0",
+ "-Wl,--defsym=__stack_size__=0x480",
+ "-Wl,--defsym=gNvmSectors=8",
+ "-Wl,--defsym=lp_ram_lower_limit=0x04000000",
+ "-Wl,--defsym=lp_ram_upper_limit=0x2001C000",
+ "-Wl,-print-memory-usage",
+ "-Wl,--no-warn-rwx-segments",
+ "-T" + rebase_path(ldscript, root_build_dir),
+ ]
+
+ output_dir = root_out_dir
+}
+
+group("k32w1") {
+ deps = [ ":contact_sensor_app" ]
+}
+
+group("default") {
+ deps = [ ":k32w1" ]
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/README.md b/examples/contact-sensor-app/nxp/k32w/k32w1/README.md
new file mode 100644
index 00000000000000..da6e3eb00f2f66
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/README.md
@@ -0,0 +1,414 @@
+# Matter K32W1 Contact Sensor Example Application
+
+Matter K32W1 Contact Sensor Example uses buttons to test changing the lock and
+device states and LEDs to show the state of these changes. You can use this
+example as a reference for creating your own application.
+
+The example is based on
+[Matter](https://github.com/project-chip/connectedhomeip) and the NXP K32W1 SDK,
+and a simulated contact sensor over a low-power, 802.15.4 Thread network.
+
+The example behaves as a Matter accessory, that is a device that can be paired
+into an existing Matter network and can be controlled by this network.
+
+
+
+- [Matter K32W1 Contact Sensor Example Application](#matter-k32w1-contact-sensor-example-application)
+- [Introduction](#introduction)
+ - [Bluetooth LE Advertising](#bluetooth-le-advertising)
+ - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous)
+- [Device UI](#device-ui)
+- [Building](#building)
+- [Flashing](#flashing)
+ - [Flashing the NBU image](#flashing-the-nbu-image)
+ - [Flashing the host image](#flashing-the-host-image)
+- [Debugging](#debugging)
+- [OTA](#ota)
+ - [Convert srec into sb3 file](#convert-srec-into-sb3-file)
+ - [Convert sb3 into ota file](#convert-sb3-into-ota-file)
+ - [Running OTA](#running-ota)
+ - [Known issues](#known-issues)
+- [Low power](#low-power)
+
+
+
+## Introduction
+
+
+
+The K32W1 contact sensor example application provides a working demonstration of
+a connected contact sensor device, built using the Matter codebase and the NXP
+K32W1 SDK. The example supports remote access (e.g.: using CHIP Tool from a
+mobile phone) and control of a simulated contact sensor over a low-power,
+802.15.4 Thread network. It is capable of being paired into an existing Matter
+network along with other Matter-enabled devices.
+
+The Matter device that runs the contact sensor application is controlled by the
+Matter controller device over the Thread protocol. By default, the Matter device
+has Thread disabled, and it should be paired over Bluetooth LE with the Matter
+controller and obtain configuration from it. The actions required before
+establishing full communication are described below.
+
+### Bluetooth LE Advertising
+
+In this example, to commission the device onto a Matter network, it must be
+discoverable over Bluetooth LE. For security reasons, you must start Bluetooth
+LE advertising manually after powering up the device by pressing Button SW2.
+
+### Bluetooth LE Rendezvous
+
+In this example, the commissioning procedure (called rendezvous) is done over
+Bluetooth LE between a Matter device and the Matter controller, where the
+controller has the commissioner role.
+
+To start the rendezvous, the controller must get the commissioning information
+from the Matter device. The data payload is encoded within a QR code, or printed
+to the UART console.
+
+### Thread Provisioning
+
+## Device UI
+
+The example application provides a simple UI that depicts the state of the
+device and offers basic user control. This UI is implemented via the
+general-purpose LEDs and buttons built in the K32W1 EVK board.
+
+**LED 2** shows the overall state of the device and its connectivity. Four
+states are depicted:
+
+- _Short Flash On (50ms on/950ms off)_ — The device is in an
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+* _Rapid Even Flashing (100ms on/100ms off)_ — The device is in an
+ unprovisioned state and a commissioning application is connected via BLE.
+
+- _Short Flash Off (950ms on/50ms off)_ — The device is full
+ provisioned, but does not yet have full network (Thread) or service
+ connectivity.
+
+* _Solid On_ — The device is fully provisioned and has full network and
+ service connectivity.
+
+NOTE: LED2 will be disabled when CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR is
+enabled. On K32W1 EVK board, `PTB0` is wired to LED2 also is wired to CS (Chip
+Select) External Flash Memory. OTA image is stored in external memory because of
+it's size. If LED2 is enabled then it will affect External Memory CS and OTA
+will not work.
+
+**RGB LED** shows the state of the simulated contact sensor. when the LED is
+lit, the sensor is contacted, when not lit, the sensor is non-contacted.
+
+**Button SW2** can be used to start BLE advertising. A SHORT press of the button
+will enable Bluetooth LE advertising for a predefined period of time. A LONG
+Press Button SW2 initiates a factory reset. After an initial period of 3
+seconds, LED 2 and RGB LED will flash in unison to signal the pending reset.
+After 6 seconds will cause the device to reset its persistent configuration and
+initiate a reboot. The reset action can be cancelled by press SW2 button at any
+point before the 6 second limit.
+
+**Button SW3** can be used to change the state of the simulated contact sensor.
+The button behaves as a toggle, swapping the state every time it is pressed.
+
+## Building
+
+In order to build the Matter example, we recommend using a Linux distribution
+(the demo-application was compiled on Ubuntu 20.04).
+
+- Download [K32W1 SDK for Matter](https://mcuxpresso.nxp.com/). Creating an
+ nxp.com account is required before being able to download the SDK. Once the
+ account is created, login and follow the steps for downloading K32W1 SDK.
+ The SDK Builder UI selection should be similar with the one from the image
+ below.
+ 
+
+```
+user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W1_SDK_ROOT=/home/user/Desktop/SDK_K32W1/
+user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
+user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w1
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w1$ gn gen out/debug --args="chip_with_ot_cli=0 is_debug=false chip_openthread_ftd=false chip_crypto=\"platform\""
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w1$ ninja -C out/debug
+```
+
+In case that Openthread CLI is needed, chip_with_ot_cli build argument must be
+set to 1.
+
+After a successful build, the `elf` and `srec` files are found in `out/debug/` -
+`see the files prefixed with chip-k32w1-contact-example`.
+
+## Flashing
+
+Two images must be written to the board: one for the host (CM33) and one for the
+`NBU` (CM3).
+
+The image needed on the host side is the one generated in `out/debug/` while the
+one needed on the `NBU` side can be found in the downloaded NXP-SDK package at
+path -
+`middleware\wireless\ieee-802.15.4\bin\k32w1\k32w1_nbu_ble_15_4_dyn_matter_$version.sb3`.
+
+### Flashing the `NBU` image
+
+`NBU` image should be written only when a new NXP-SDK is released.
+
+[K32W148 board quick start guide](https://www.nxp.com/document/guide/getting-started-with-the-k32w148-development-platform:GS-K32W148EVK)
+can be used for updating the `NBU/radio` core:
+
+- Section 2.4 – Get Software – install `SPSDK` (Secure Provisioning Command
+ Line Tool)
+- Section 3.3 – Updating `NBU` for Wireless examples - use the corresponding
+ `.sb3` file found in the SDK package at path
+ `middleware\wireless\ieee-802.15.4\bin\k32w1\`
+
+### Flashing the host image
+
+Host image is the one found under `out/debug/`. It should be written after each
+build process.
+
+If debugging is needed then jump directly to the [Debugging](#debugging)
+section. Otherwise, if only flashing is needed then
+[JLink 7.84b](https://www.segger.com/downloads/jlink/) can be used:
+
+- Plug K32W1 to the USB port (no need to keep the SW4 button pressed while
+ doing this)
+
+- Create a new file, `commands_script`, with the following content (change
+ application name accordingly):
+
+```bash
+reset
+halt
+loadfile chip-k32w1-contact-example.srec
+reset
+go
+quit
+```
+
+- copy the application and `commands_script` in the same folder that JLink
+ executable is placed. Execute:
+
+```bash
+$ jlink -device K32W1480 -if SWD -speed 4000 -autoconnect 1 -CommanderScript commands_script
+```
+
+## Debugging
+
+One option for debugging would be to use MCUXpresso IDE.
+
+- Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs"
+ tab:
+
+
+
+- Import any demo application from the installed SDK:
+
+```
+Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish
+```
+
+
+
+- Flash the previously imported demo application on the board:
+
+```
+Right click on the application (from Project Explorer) -> Debug as -> JLink/CMSIS-DAP
+```
+
+After this step, a debug configuration specific for the K32W1 board was created.
+This debug configuration will be used later on for debugging the application
+resulted after ot-nxp compilation.
+
+- Import Matter repo in MCUXpresso IDE as Makefile Project. Use _none_ as
+ _Toolchain for Indexer Settings_:
+
+```
+File -> Import -> C/C++ -> Existing Code as Makefile Project
+```
+
+
+
+- Replace the path of the existing demo application with the path of the K32W1
+ application:
+
+```
+Run -> Debug Configurations... -> C/C++ Application
+```
+
+
+
+## OTA
+
+### Convert `srec` into `sb3` file
+
+The OTA image files must be encrypted using Over The Air Programming Tool
+([OTAP](https://www.nxp.com/design/microcontrollers-developer-resources/connectivity-tool-suite:CONNECTIVITY-TOOL-SUITE?#downloads)).
+Bootloader will load the new OTA image only if it detects that the file was
+encrypted with the `OTAP` correct keys.
+
+`.srec` file is input for Over The air Programming (`OTAP`) application
+(unencrypted) and it's converted to `.sb3` format (encrypted).
+
+In `OTAP` application
+
+- select OTA protocol => `OTAP` Matter
+- Browse File
+- follow default options (KW45/K32W148, Preserve NVM)
+- image information: will update "Application Core (MCU)" - this will generate
+ the image only for the CM33 core
+- keep other settings at default values
+
+### Convert sb3 into ota file
+
+In order to build an OTA image, use NXP wrapper over the standard tool
+`src/app/ota_image_tool.py`:
+
+- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py` The tool can be
+ used to generate an OTA image with the following format:
+ `| OTA image header | TLV1 | TLV2 | ... | TLVn |` where each TLV is in the
+ form `|tag|length|value|`
+
+Note that "standard" TLV format is used. Matter TLV format is only used for
+factory data TLV value.
+
+Please see more in the
+[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md).
+
+Here is an example that generates an OTA image with application update TLV from
+a sb3 file:
+
+```
+./scripts/tools/nxp/ota/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 43033 -vs "1.0" -da sha256 --app-input-file ~/binaries/chip-k32w1-43033.sb3 ~/binaries/chip-k32w1-43033.ota
+
+```
+
+A note regarding OTA image header version (`-vn` option). An application binary
+has its own software version (given by
+`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION`, which can be overwritten). For
+having a correct OTA process, the OTA header version should be the same as the
+binary embedded software version. A user can set a custom software version in
+the gn build args by setting `chip_software_version` to the wanted version.
+
+### Running OTA
+
+The OTA topology used for OTA testing is illustrated in the figure below.
+Topology is similar with the one used for Matter Test Events.
+
+
+
+The concept for OTA is the next one:
+
+- there is an OTA Provider Application that holds the OTA image. In our case,
+ this is a Linux application running on an Ubuntu based-system;
+- the OTA Requestor functionality is embedded inside the Contact Sensor
+ Application. It will be used for requesting OTA blocks from the OTA
+ Provider;
+- the controller (a linux application called chip-tool) will be used for
+ commissioning both the device and the OTA Provider App. The device will be
+ commissioned using the standard Matter flow (BLE + IEEE 802.15.4) while the
+ OTA Provider Application will be commissioned using the _onnetwork_ option
+ of chip-tool;
+- during commissioning, each device is assigned a node id by the chip-tool
+ (can be specified manually by the user). Using the node id of the device and
+ of the contact sensor application, chip-tool triggers the OTA transfer by
+ invoking the _announce-ota-provider_ command - basically, the OTA Requestor
+ is informed of the node id of the OTA Provider Application.
+
+_Computer #1_ can be any system running an Ubuntu distribution. We recommand
+using CSA official instructions from
+[here](https://groups.csa-iot.org/wg/matter-csg/document/28566), where RPi 4 are
+proposed. Also, CSA official instructions document point to the OS/Docker images
+that should be used on the RPis. For compatibility reasons, we recommand
+compiling chip-tool and OTA Provider applications with the same commit id that
+was used for compiling the Contact Sensor Application. Also, please note that
+there is a single controller (chip-tool) running on Computer #1 which is used
+for commissioning both the device and the OTA Provider Application. If needed,
+[these instructions](https://itsfoss.com/connect-wifi-terminal-ubuntu/) could be
+used for connecting the RPis to WiFi.
+
+Build the Linux OTA provider application:
+
+```
+user@computer1:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false
+```
+
+Build Linux chip-tool:
+
+```
+user@computer1:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/chip-tool out/chip-tool-app
+```
+
+Start the OTA Provider Application:
+
+```
+user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_*
+user@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w1-43033.ota
+```
+
+Provision the OTA provider application and assign node id _1_. Also, grant ACL
+entries to allow OTA requestors:
+
+```
+user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_*
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing onnetwork 1 20202021
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0
+```
+
+Provision the device and assign node id _2_:
+
+```
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing ble-thread 2 hex: 20202021 3840
+```
+
+Start the OTA process:
+
+```
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-ota-provider 1 0 0 0 2 0
+```
+
+## Low power
+
+The example also offers the possibility to run in low power mode. This means
+that the board will go in deep sleep most of the time and the power consumption
+will be very low.
+
+In order to build with low power support, the `chip_with_low_power=1` must be
+provided to the build system. In this case, please note that the GN build
+arguments `chip_openthread_ftd` and `chip_with_ot_cli` must be set to `false/0`
+and `chip_logging` must be set to `false` to disable logging.
+
+In order to maintain a low power consumption, the LEDs showing the state of the
+contact sensor and the internal state are disabled. Console logs can be used
+instead. Also, please note that once the board is flashed with MCUXpresso the
+debugger disconnects because the board enters low power.
+
+### Known issues
+
+- SRP cache on the openthread border router needs to flushed each time a new
+ commissioning process is attempted. For this, factory reset the device, then
+ execute _ot-ctl server disable_ followed by _ot-ctl server enable_. After
+ this step, the commissioning process of the device can start;
+- Due to some MDNS issues, the commissioning of the OTA Provider Application
+ may fail. Please make sure that the SRP cache is disabled (_ot-ctl srp
+ server disable_) on the openthread border router while commissioning the OTA
+ Provider Application;
+- No other Docker image should be running (e.g.: Docker image needed by Test
+ Harness) except the OTBR one. A docker image can be killed using the
+ command:
+
+```
+user@computer1:~/connectedhomeip$ : sudo docker kill $container_id
+```
+
+- In order to avoid MDNS issues, only one interface should be active at one
+ time. E.g.: if WiFi is used then disable the Ethernet interface and also
+ disable multicast on that interface:
+
+```
+user@computer1:~/connectedhomeip$ sudo ip link set dev eth0 down
+user@computer1:~/connectedhomeip$ sudo ifconfig eth0 -multicast
+```
+
+- If OTBR Docker image is used, then the "-B" parameter should point to the
+ interface used for the backbone.
+
+- If Wi-Fi is used on a RPI4, then a 5Ghz network should be selected.
+ Otherwise, issues related to BLE-WiFi combo may appear.
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni b/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni
new file mode 100644
index 00000000000000..c0497aa27421d2
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni
@@ -0,0 +1,25 @@
+# Copyright (c) 2020-2023 Project CHIP Authors
+# Copyright (c) 2023 NXP
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/examples/platform/nxp/k32w/k32w1/args.gni")
+
+# SDK target. This is overridden to add our SDK app_config.h & defines.
+k32w1_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_stack_lock_tracking = "fatal"
+chip_enable_ble = true
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides b/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides
new file mode 120000
index 00000000000000..ad07557834803a
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/build_overrides
@@ -0,0 +1 @@
+../../../../build_overrides/
\ No newline at end of file
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..af3a7067c99e1a
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2020-2023 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8006
+
+// Use a default setup PIN code if one hasn't been provisioned in flash.
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS"
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in CHIP NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8006
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100
+
+#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ *
+ * A string identifying the software version running on the device.
+ * CHIP currently expects the software version to be in the format
+ * {MAJOR_VERSION}.0d{MINOR_VERSION}
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8"
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors"
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT
+ *
+ * The amount of time in miliseconds after which BLE should change his advertisements
+ * from fast interval to slow interval.
+ *
+ * 30000 (30 secondes).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000)
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT
+ *
+ * The amount of time in miliseconds after which BLE advertisement should be disabled, counting
+ * from the moment of slow advertisement commencement.
+ *
+ * Defaults to 9000000 (15 minutes).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000)
+
+/**
+ * CONFIG_CHIP_NFC_COMMISSIONING, CHIP_DEVICE_CONFIG_ENABLE_NFC
+ *
+ * NFC commissioning is not supported on K32W1
+ */
+#define CONFIG_CHIP_NFC_COMMISSIONING 0
+#define CHIP_DEVICE_CONFIG_ENABLE_NFC 0
+
+/**
+ * @def CHIP_CONFIG_MAX_FABRICS
+ *
+ * @brief
+ * Maximum number of fabrics the device can participate in. Each fabric can
+ * provision the device with its unique operational credentials and manage
+ * its own access control lists.
+ */
+#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics
+
+#define CHIP_DEVICE_CONFIG_ENABLE_SED 1
+#define CHIP_DEVICE_CONFIG_SED_IDLE_INTERVAL 1000_ms32
+#define CHIP_DEVICE_CONFIG_SED_ACTIVE_INTERVAL 100_ms32
+
+/**
+ * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER
+ *
+ * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2
+
+/**
+ * @def CHIP_IM_MAX_NUM_WRITE_HANDLER
+ *
+ * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE
+ *
+ * For a development build, set the default importance of events to be logged as Debug.
+ * Since debug is the lowest importance level, this means all standard, critical, info and
+ * debug importance level vi events get logged.
+ */
+#if BUILD_RELEASE
+#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production
+#else
+#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug
+#endif // BUILD_RELEASE
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h
new file mode 100644
index 00000000000000..a4e204700672a3
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h
@@ -0,0 +1,207 @@
+/*
+ * FreeRTOS Kernel V10.2.0
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * Copyright (c) 2023 NXP
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+#pragma once
+
+/* Ensure stdint is only used by the compiler, and not the assembler. */
+#if defined(__ICCARM__) || defined(__ARMCC_VERSION) || defined(__GNUC__)
+#include
+extern uint32_t SystemCoreClock;
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION 1
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+#define configUSE_TICKLESS_IDLE 1
+#else
+#define configUSE_TICKLESS_IDLE 0
+#endif
+
+#define configCPU_CLOCK_HZ (SystemCoreClock)
+#define configTICK_RATE_HZ ((TickType_t) 100)
+#define configMAX_PRIORITIES (8)
+
+#if defined(configUSE_TICKLESS_IDLE) && (configUSE_TICKLESS_IDLE == 1)
+#define configMINIMAL_STACK_SIZE ((unsigned short) 610)
+#else
+#define configMINIMAL_STACK_SIZE ((unsigned short) 450)
+#endif
+
+#define configMAX_TASK_NAME_LEN 20
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
+#define configQUEUE_REGISTRY_SIZE 8
+#define configUSE_QUEUE_SETS 0
+/* make sure that Thread task can interrupt lengthy Matter
+ * processing in case priority inversion occurs
+ */
+#define configUSE_TIME_SLICING 1
+#define configUSE_NEWLIB_REENTRANT 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
+
+/* Tasks.c additions (e.g. Thread Aware Debug capability) */
+#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
+
+/* Used memory allocation (heap_x.c) */
+#define configFRTOS_MEMORY_SCHEME 4
+
+/* Memory allocation related definitions. */
+#define configSUPPORT_STATIC_ALLOCATION 0
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
+#define configTOTAL_HEAP_SIZE ((size_t) (gTotalHeapSize_c))
+#define configAPPLICATION_ALLOCATED_HEAP 1
+
+/* Hook function related definitions. */
+#ifndef configUSE_IDLE_HOOK
+#define configUSE_IDLE_HOOK 1
+#endif
+#define configUSE_TICK_HOOK 0
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#ifndef configUSE_MALLOC_FAILED_HOOK
+#define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+/* Task aware debugging. */
+#define configRECORD_STACK_HIGH_ADDRESS 1
+
+/* Co-routine related definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES 2
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
+#define configTIMER_QUEUE_LENGTH 10
+#define configTIMER_TASK_STACK_DEPTH (360)
+
+/* Define to trap errors during development. */
+#if defined gLoggingActive_d && (gLoggingActive_d != 0)
+#include "dbg_logging.h"
+#define configASSERT(x) \
+ if ((x) == 0) \
+ { \
+ taskDISABLE_INTERRUPTS(); \
+ DbgLogDump(1); \
+ }
+#else
+#define configASSERT(x) \
+ if ((x) == 0) \
+ { \
+ taskDISABLE_INTERRUPTS(); \
+ for (;;) \
+ ; \
+ }
+#endif
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_xResumeFromISR 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_eTaskGetState 0
+#define INCLUDE_xEventGroupSetBitFromISR 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 0
+#define INCLUDE_xTaskGetHandle 0
+#define INCLUDE_xTaskResumeFromISR 1
+#define INCLUDE_xQueueGetMutexHolder 1
+
+/* Interrupt nesting behaviour configuration. Cortex-M specific. */
+#ifdef __NVIC_PRIO_BITS
+/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+#define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+#define configPRIO_BITS 3
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+
+#ifndef configENABLE_FPU
+#define configENABLE_FPU 0
+#endif
+#ifndef configENABLE_MPU
+#define configENABLE_MPU 0
+#endif
+#ifndef configENABLE_TRUSTZONE
+#define configENABLE_TRUSTZONE 0
+#endif
+#ifndef configRUN_FREERTOS_SECURE_ONLY
+#define configRUN_FREERTOS_SECURE_ONLY 1
+#endif
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp
new file mode 100644
index 00000000000000..bce7374d7ea7ef
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp
@@ -0,0 +1,812 @@
+/*
+ *
+ * Copyright (c) 2022-2023 Project CHIP Authors
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "AppTask.h"
+#include "AppEvent.h"
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/* OTA related includes */
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+#include "OtaSupport.h"
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#include "K32W1PersistentStorageOpKeystore.h"
+
+#include "LEDWidget.h"
+#include "app.h"
+#include "app_config.h"
+#include "fsl_component_button.h"
+#include "fwk_platform.h"
+
+#define FACTORY_RESET_TRIGGER_TIMEOUT 6000
+#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+
+TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer.
+
+static QueueHandle_t sAppEventQueue;
+
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+/*
+ * The status LED and the external flash CS pin are wired together.
+ * The OTA image writing may fail if used together.
+ */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+static LEDWidget sStatusLED;
+#endif
+static LEDWidget sContactSensorLED;
+#endif
+
+static bool sIsThreadProvisioned = false;
+static bool sHaveBLEConnections = false;
+
+static uint32_t eventMask = 0;
+
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+extern "C" void otPlatUartProcess(void);
+#endif
+
+extern "C" void PWR_DisallowDeviceToSleep(void);
+extern "C" void PWR_AllowDeviceToSleep(void);
+
+using namespace ::chip::Credentials;
+using namespace ::chip::DeviceLayer;
+using namespace chip;
+using namespace chip::app;
+
+AppTask AppTask::sAppTask;
+
+static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop,
+ Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator };
+
+/* OTA related variables */
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+static DefaultOTARequestor gRequestorCore __attribute__((section(".data")));
+static DefaultOTARequestorStorage gRequestorStorage __attribute__((section(".data")));
+static DeviceLayer::DefaultOTARequestorDriver gRequestorUser __attribute__((section(".data")));
+static BDXDownloader gDownloader __attribute__((section(".data")));
+
+constexpr uint16_t requestedOtaBlockSize = 1024;
+#endif
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent));
+ if (sAppEventQueue == NULL)
+ {
+ err = APP_ERROR_EVENT_QUEUE_FAILED;
+ K32W_LOG("Failed to allocate app event queue");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ return err;
+}
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (ContactSensorMgr().Init() != 0)
+ {
+ K32W_LOG("ContactSensorMgr().Init() failed");
+ assert(status == 0);
+ }
+
+ PlatformMgr().AddEventHandler(MatterEventHandler, 0);
+
+ // Init ZCL Data Model and start server
+ PlatformMgr().ScheduleWork(InitServer, 0);
+
+ // Initialize device attestation config
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+
+ // QR code will be used with CHIP Tool
+ AppTask::PrintOnboardingInfo();
+
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+ /* start with all LEDS turnedd off */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Init(SYSTEM_STATE_LED, false);
+#endif
+
+ sContactSensorLED.Init(CONTACT_SENSOR_STATE_LED, false);
+ sContactSensorLED.Set(ContactSensorMgr().IsContactClosed());
+#endif
+
+ UpdateDeviceState();
+
+ /* intialize the Keyboard and button press callback */
+ BUTTON_InstallCallback((button_handle_t) g_buttonHandle[0], KBD_Callback, (void *) BLE_BUTTON);
+ BUTTON_InstallCallback((button_handle_t) g_buttonHandle[1], KBD_Callback, (void *) CONTACT_SENSOR_BUTTON);
+
+ // Create FreeRTOS sw timer for Function Selection.
+ sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = app task obj context
+ TimerEventHandler // timer callback handler
+ );
+ if (sFunctionTimer == NULL)
+ {
+ err = APP_ERROR_CREATE_TIMER_FAILED;
+ K32W_LOG("app_timer_create() failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ ContactSensorMgr().SetCallback(OnStateChanged);
+
+ // Print the current software version
+ char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 };
+ err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer));
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Get version error");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ uint32_t currentVersion;
+ err = ConfigurationMgr().GetSoftwareVersion(currentVersion);
+
+ K32W_LOG("Current Software Version: %s, %d", currentSoftwareVer, currentVersion);
+
+ return err;
+}
+
+void LockOpenThreadTask(void)
+{
+ PWR_DisallowDeviceToSleep();
+ chip::DeviceLayer::ThreadStackMgr().LockThreadStack();
+}
+
+void UnlockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack();
+ PWR_AllowDeviceToSleep();
+}
+
+void AppTask::InitServer(intptr_t arg)
+{
+ static chip::CommonCaseDeviceServerInitParams initParams;
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+
+#if CHIP_CRYPTO_PLATFORM
+ static chip::K32W1PersistentStorageOpKeystore sK32W1PersistentStorageOpKeystore;
+ VerifyOrDie((sK32W1PersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR);
+ initParams.operationalKeystore = &sK32W1PersistentStorageOpKeystore;
+#endif
+
+ // Init ZCL Data Model and start server
+ chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
+ nativeParams.lockCb = LockOpenThreadTask;
+ nativeParams.unlockCb = UnlockOpenThreadTask;
+ nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
+ initParams.endpointNativeParams = static_cast(&nativeParams);
+ VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR);
+}
+
+void AppTask::PrintOnboardingInfo()
+{
+ chip::PayloadContents payload;
+ CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format());
+ }
+ payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired;
+ PrintOnboardingCodes(payload);
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+void AppTask::InitOTA(intptr_t arg)
+{
+ // Initialize and interconnect the Requestor and Image Processor objects -- START
+ SetRequestorInstance(&gRequestorCore);
+
+ gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage());
+ gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader);
+ gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize);
+ auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance();
+ gRequestorUser.Init(&gRequestorCore, &imageProcessor);
+ CHIP_ERROR err = imageProcessor.Init(&gDownloader);
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Image processor init failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ // Connect the gDownloader and Image Processor objects
+ gDownloader.SetImageProcessorDelegate(&imageProcessor);
+ // Initialize and interconnect the Requestor and Image Processor objects -- END
+}
+#endif
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("AppTask.Init() failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ while (true)
+ {
+ TickType_t xTicksToWait = pdMS_TO_TICKS(10);
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+ xTicksToWait = portMAX_DELAY;
+#endif
+
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, xTicksToWait);
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+
+ // Collect connectivity and configuration state from the CHIP stack. Because the
+ // CHIP event loop is being run in a separate task, the stack must be locked
+ // while these values are queried. However we use a non-blocking lock request
+ // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP
+ // task is busy (e.g. with a long crypto operation).
+ if (PlatformMgr().TryLockChipStack())
+ {
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+ otPlatUartProcess();
+#endif
+
+ sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0);
+ PlatformMgr().UnlockChipStack();
+ }
+
+ // Update the status LED if factory reset or identify process have not been initiated.
+ //
+ // If system has "full connectivity", keep the LED On constantly.
+ //
+ // If thread and service provisioned, but not attached to the thread network yet OR no
+ // connectivity to the service OR subscriptions are not fully established
+ // THEN blink the LED Off for a short period of time.
+ //
+ // If the system has ble connection(s) uptill the stage above, THEN blink the LEDs at an even
+ // rate of 100ms.
+ //
+ // Otherwise, blink the LED ON for a very short time.
+
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (sAppTask.mFunction != Function::kFactoryReset && sAppTask.mFunction != Function::kIdentify)
+ {
+ if (sIsThreadProvisioned)
+ {
+ sStatusLED.Blink(950, 50);
+ }
+ else if (sHaveBLEConnections)
+ {
+ sStatusLED.Blink(100, 100);
+ }
+ else
+ {
+ sStatusLED.Blink(50, 950);
+ }
+ }
+
+ sStatusLED.Animate();
+#endif
+
+ sContactSensorLED.Animate();
+#endif
+ }
+}
+
+void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action)
+{
+ if ((pin_no != RESET_BUTTON) && (pin_no != CONTACT_SENSOR_BUTTON) && (pin_no != OTA_BUTTON) && (pin_no != BLE_BUTTON))
+ {
+ return;
+ }
+
+ AppEvent button_event;
+ button_event.Type = AppEvent::kButton;
+ button_event.ButtonEvent.PinNo = pin_no;
+ button_event.ButtonEvent.Action = button_action;
+
+ if (pin_no == RESET_BUTTON)
+ {
+ button_event.Handler = ResetActionEventHandler;
+ }
+ else if (pin_no == CONTACT_SENSOR_BUTTON)
+ {
+ button_event.Handler = ContactActionEventHandler;
+ }
+ else if (pin_no == OTA_BUTTON)
+ {
+ // Starting OTA by button functionality is not used.
+ // button_event.Handler = OTAHandler;
+ }
+ else if (pin_no == BLE_BUTTON)
+ {
+ button_event.Handler = BleHandler;
+
+ if (button_action == RESET_BUTTON_PUSH)
+ {
+ button_event.Handler = ResetActionEventHandler;
+ }
+ }
+
+ sAppTask.PostEvent(&button_event);
+}
+
+button_status_t AppTask::KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam)
+{
+ uint32_t pinNb = (uint32_t) callbackParam;
+ switch (message->event)
+ {
+ case kBUTTON_EventOneClick:
+ case kBUTTON_EventShortPress:
+ switch (pinNb)
+ {
+ case BLE_BUTTON:
+ K32W_LOG("pb1 short press");
+ if (sAppTask.mResetTimerActive)
+ {
+ ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH);
+ }
+ else
+ {
+ ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH);
+ }
+ break;
+
+ case CONTACT_SENSOR_BUTTON:
+ K32W_LOG("pb2 short press");
+ ButtonEventHandler(CONTACT_SENSOR_BUTTON, CONTACT_SENSOR_BUTTON_PUSH);
+ break;
+ }
+ break;
+
+ case kBUTTON_EventLongPress:
+ switch (pinNb)
+ {
+ case BLE_BUTTON:
+ K32W_LOG("pb1 long press");
+ ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH);
+ break;
+
+ case CONTACT_SENSOR_BUTTON:
+ K32W_LOG("pb2 long press");
+ ButtonEventHandler(OTA_BUTTON, OTA_BUTTON_PUSH);
+ break;
+ }
+ break;
+
+ default:
+ /* No action required */
+ break;
+ }
+ return kStatus_BUTTON_Success;
+}
+
+void AppTask::TimerEventHandler(TimerHandle_t xTimer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kTimer;
+ event.TimerEvent.Context = (void *) xTimer;
+ event.Handler = FunctionTimerEventHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::FunctionTimerEventHandler(void * aGenericEvent)
+{
+ AppEvent * aEvent = (AppEvent *) aGenericEvent;
+
+ if (aEvent->Type != AppEvent::kTimer)
+ return;
+
+ K32W_LOG("Device will factory reset...");
+
+ // Actually trigger Factory Reset
+ chip::Server::GetInstance().ScheduleFactoryReset();
+}
+
+void AppTask::ResetActionEventHandler(void * aGenericEvent)
+{
+ AppEvent * aEvent = (AppEvent *) aGenericEvent;
+
+ if (aEvent->ButtonEvent.PinNo != RESET_BUTTON && aEvent->ButtonEvent.PinNo != BLE_BUTTON)
+ return;
+
+ if (sAppTask.mResetTimerActive)
+ {
+ sAppTask.CancelTimer();
+ sAppTask.mFunction = Function::kNoneSelected;
+
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+ /* restore initial state for the LED indicating contact state */
+ if (!ContactSensorMgr().IsContactClosed())
+ {
+ sContactSensorLED.Set(false);
+ }
+ else
+ {
+ sContactSensorLED.Set(true);
+ }
+#endif
+
+ K32W_LOG("Factory Reset was cancelled!");
+ }
+ else
+ {
+ uint32_t resetTimeout = FACTORY_RESET_TRIGGER_TIMEOUT;
+
+ if (sAppTask.mFunction != Function::kNoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate Factory Reset!");
+ return;
+ }
+
+ K32W_LOG("Factory Reset Triggered. Push the RESET button within %lu ms to cancel!", resetTimeout);
+ sAppTask.mFunction = Function::kFactoryReset;
+
+ /* LEDs will start blinking to signal that a Factory Reset was scheduled */
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Set(false);
+ sStatusLED.Blink(500);
+#endif
+ sContactSensorLED.Set(false);
+ sContactSensorLED.Blink(500);
+#endif
+
+ sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+ }
+}
+
+void AppTask::ContactActionEventHandler(void * aGenericEvent)
+{
+ AppEvent * aEvent = (AppEvent *) aGenericEvent;
+ ContactSensorManager::Action action = ContactSensorManager::Action::kInvalid;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ bool state_changed = false;
+
+ if (sAppTask.mFunction != Function::kNoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not change contact state.");
+ return;
+ }
+
+ if (aEvent->Type == AppEvent::kContact)
+ {
+ action = static_cast(aEvent->ContactEvent.Action);
+ }
+ else if (aEvent->Type == AppEvent::kButton)
+ {
+ if (ContactSensorMgr().IsContactClosed())
+ {
+ action = ContactSensorManager::Action::kSignalLost;
+ }
+ else
+ {
+ action = ContactSensorManager::Action::kSignalDetected;
+ }
+
+ sAppTask.SetSyncClusterToButtonAction(true);
+ }
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ action = ContactSensorManager::Action::kInvalid;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ ContactSensorMgr().InitiateAction(action);
+ }
+}
+
+void AppTask::OTAHandler(void * aGenericEvent)
+{
+ AppEvent * aEvent = (AppEvent *) aGenericEvent;
+ if (aEvent->ButtonEvent.PinNo != OTA_BUTTON)
+ return;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (sAppTask.mFunction != Function::kNoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate OTA!");
+ return;
+ }
+
+ PlatformMgr().ScheduleWork(StartOTAQuery, 0);
+#endif
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+void AppTask::StartOTAQuery(intptr_t arg)
+{
+ GetRequestorInstance()->TriggerImmediateQuery();
+}
+#endif
+
+void AppTask::BleHandler(void * aGenericEvent)
+{
+ AppEvent * aEvent = (AppEvent *) aGenericEvent;
+
+ if (aEvent->ButtonEvent.PinNo != BLE_BUTTON)
+ return;
+
+ if (sAppTask.mFunction != Function::kNoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not toggle BLE state!");
+ return;
+ }
+ PlatformMgr().ScheduleWork(AppTask::BleStartAdvertising, 0);
+}
+
+void AppTask::BleStartAdvertising(intptr_t arg)
+{
+ if (ConnectivityMgr().IsBLEAdvertisingEnabled())
+ {
+ ConnectivityMgr().SetBLEAdvertisingEnabled(false);
+ K32W_LOG("Stopped BLE Advertising!");
+ }
+ else
+ {
+ ConnectivityMgr().SetBLEAdvertisingEnabled(true);
+
+ if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR)
+ {
+ K32W_LOG("Started BLE Advertising!");
+ }
+ else
+ {
+ K32W_LOG("OpenBasicCommissioningWindow() failed");
+ }
+ }
+}
+
+void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t)
+{
+ if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned)
+ {
+ if (event->ServiceProvisioningChange.IsServiceProvisioned)
+ {
+ sIsThreadProvisioned = TRUE;
+ }
+ else
+ {
+ sIsThreadProvisioned = FALSE;
+ }
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (event->Type == DeviceEventType::kDnssdInitialized)
+ {
+ K32W_LOG("Dnssd platform initialized.");
+ PlatformMgr().ScheduleWork(InitOTA, 0);
+ }
+#endif
+}
+
+void AppTask::CancelTimer()
+{
+ if (xTimerStop(sFunctionTimer, 0) == pdFAIL)
+ {
+ K32W_LOG("app timer stop() failed");
+ }
+
+ mResetTimerActive = false;
+}
+
+void AppTask::StartTimer(uint32_t aTimeoutInMs)
+{
+ if (xTimerIsTimerActive(sFunctionTimer))
+ {
+ K32W_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+ {
+ K32W_LOG("app timer start() failed");
+ }
+
+ mResetTimerActive = true;
+}
+
+void AppTask::OnStateChanged(ContactSensorManager::State aState)
+{
+ // If the contact state was changed, update LED state and cluster state (only if button was pressed).
+ // - turn on the contact LED if contact sensor is in closed state.
+ // - turn off the lock LED if contact sensor is in opened state.
+ if (ContactSensorManager::State::kContactClosed == aState)
+ {
+ K32W_LOG("Contact state changed to closed.")
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+ sContactSensorLED.Set(true);
+#endif
+ }
+ else if (ContactSensorManager::State::kContactOpened == aState)
+ {
+ K32W_LOG("Contact state changed to opened.")
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+ sContactSensorLED.Set(false);
+#endif
+ }
+
+ if (sAppTask.IsSyncClusterToButtonAction())
+ {
+ sAppTask.UpdateClusterState();
+ }
+
+ sAppTask.mFunction = Function::kNoneSelected;
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ if (Clusters::Identify::EffectIdentifierEnum::kBlink == identify->mCurrentEffectIdentifier)
+ {
+ if (Function::kNoneSelected != sAppTask.mFunction)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate Identify process!");
+ return;
+ }
+ K32W_LOG("Identify process has started. Status LED should blink every 0.5 seconds.");
+ sAppTask.mFunction = Function::kIdentify;
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Set(false);
+ sStatusLED.Blink(500);
+#endif
+#endif
+ }
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ if (Clusters::Identify::EffectIdentifierEnum::kBlink == identify->mCurrentEffectIdentifier)
+ {
+ K32W_LOG("Identify process has stopped.");
+ sAppTask.mFunction = Function::kNoneSelected;
+ }
+}
+
+void AppTask::PostContactActionRequest(ContactSensorManager::Action aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kContact;
+ event.ContactEvent.Action = static_cast(aAction);
+ event.Handler = ContactActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::PostEvent(const AppEvent * aEvent)
+{
+ portBASE_TYPE taskToWake = pdFALSE;
+ if (sAppEventQueue != NULL)
+ {
+ if (__get_IPSR())
+ {
+ if (!xQueueSendToFrontFromISR(sAppEventQueue, aEvent, &taskToWake))
+ {
+ K32W_LOG("Failed to post event to app task event queue");
+ }
+ if (taskToWake)
+ {
+ portYIELD_FROM_ISR(taskToWake);
+ }
+ }
+ else if (!xQueueSend(sAppEventQueue, aEvent, 0))
+ {
+ K32W_LOG("Failed to post event to app task event queue");
+ }
+ }
+}
+
+void AppTask::DispatchEvent(AppEvent * aEvent)
+{
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+ /* specific processing for events sent from App_PostCallbackMessage (see main.cpp) */
+ if (aEvent->Type == AppEvent::kEventType_Lp)
+ {
+ aEvent->Handler(aEvent->param);
+ }
+ else
+#endif
+
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ K32W_LOG("Event received with no handler. Dropping event.");
+ }
+}
+
+void AppTask::UpdateClusterState(void)
+{
+ PlatformMgr().ScheduleWork(UpdateClusterStateInternal, 0);
+}
+extern void logBooleanStateEvent(bool state);
+void AppTask::UpdateClusterStateInternal(intptr_t arg)
+{
+ uint8_t newValue = ContactSensorMgr().IsContactClosed();
+
+ // write the new on/off value
+ EmberAfStatus status = app::Clusters::BooleanState::Attributes::StateValue::Set(1, newValue);
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ ChipLogError(NotSpecified, "ERR: updating boolean status value %x", status);
+ }
+ logBooleanStateEvent(newValue);
+}
+
+void AppTask::UpdateDeviceState(void)
+{
+ PlatformMgr().ScheduleWork(UpdateDeviceStateInternal, 0);
+}
+
+void AppTask::UpdateDeviceStateInternal(intptr_t arg)
+{
+ bool stateValueAttrValue = 0;
+
+ /* get onoff attribute value */
+ (void) app::Clusters::BooleanState::Attributes::StateValue::Get(1, &stateValueAttrValue);
+
+#if !defined(chip_with_low_power) || (chip_with_low_power == 0)
+ /* set the device state */
+ sContactSensorLED.Set(stateValueAttrValue);
+#endif
+}
+
+extern "C" void OTAIdleActivities(void)
+{
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ OTA_TransactionResume();
+#endif
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp
new file mode 100644
index 00000000000000..9e0a665cbb5aa9
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ContactSensorManager.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2022-2023 Project CHIP Authors
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ContactSensorManager.h"
+
+#include "AppTask.h"
+#include "FreeRTOS.h"
+
+#include "app_config.h"
+
+ContactSensorManager ContactSensorManager::sContactSensor;
+
+int ContactSensorManager::Init()
+{
+ int err = 0;
+
+ mState = State::kContactOpened;
+ mCallbackStateChanged = nullptr;
+
+ return err;
+}
+
+void ContactSensorManager::SetCallback(CallbackStateChanged aCallbackStateChanged)
+{
+ mCallbackStateChanged = aCallbackStateChanged;
+}
+
+bool ContactSensorManager::IsContactClosed()
+{
+ return mState == State::kContactClosed;
+}
+
+void ContactSensorManager::InitiateAction(Action aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kContact;
+ event.ContactEvent.Action = static_cast(aAction);
+ event.Handler = HandleAction;
+ GetAppTask().PostEvent(&event);
+}
+
+void ContactSensorManager::HandleAction(void * aGenericEvent)
+{
+ AppEvent * event = static_cast(aGenericEvent);
+ Action action = static_cast(event->ContactEvent.Action);
+ // Change current state based on action:
+ // - if state is closed and action is signal lost, change state to opened
+ // - if state is opened and action is signal detected, change state to closed
+ // - else, the state/action combination does not change the state.
+ if (State::kContactClosed == sContactSensor.mState && Action::kSignalLost == action)
+ {
+ sContactSensor.mState = State::kContactOpened;
+ }
+ else if (State::kContactOpened == sContactSensor.mState && Action::kSignalDetected == action)
+ {
+ sContactSensor.mState = State::kContactClosed;
+ }
+
+ if (sContactSensor.mCallbackStateChanged != nullptr)
+ {
+ sContactSensor.mCallbackStateChanged(sContactSensor.mState);
+ }
+ else
+ {
+ K32W_LOG("Callback for state change was not set. Please set an appropriate callback.");
+ }
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..e1e35b4cb4ec7e
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp
@@ -0,0 +1,98 @@
+/*
+ *
+ * Copyright (c) 2022-2023 Project CHIP Authors
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "AppTask.h"
+#include "ContactSensorManager.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app;
+using namespace ::chip::app::Clusters;
+using namespace ::chip::app::Clusters::BooleanState;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value)
+{
+ ChipLogProgress(Zcl, "MatterPostAttributeChangeCallback, value:%d\n", *value);
+ if (path.mClusterId != BooleanState::Id)
+ {
+ ChipLogProgress(Zcl, "Unknown cluster ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mClusterId));
+ return;
+ }
+
+ if (path.mAttributeId != BooleanState::Attributes::StateValue::Id)
+ {
+ ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId));
+ return;
+ }
+
+ AppTask & task = GetAppTask();
+ // If the callback is called after the cluster attribute was changed due to pressing a button,
+ // set the sync value to false. Both LED and attribute were updated at this point.
+ // On the other hand, if the cluster attribute was changed due to a cluster command,
+ // forward the request to AppTask in order to update the LED state.
+ if (task.IsSyncClusterToButtonAction())
+ {
+ task.SetSyncClusterToButtonAction(false);
+ }
+ else
+ {
+ task.PostContactActionRequest(*value ? ContactSensorManager::Action::kSignalDetected
+ : ContactSensorManager::Action::kSignalLost);
+ }
+}
+
+/** @brief OnOff Cluster Init
+ *
+ * This function is called when a specific cluster is initialized. It gives the
+ * application an opportunity to take care of cluster initialization procedures.
+ * It is called exactly once for each endpoint where cluster is present.
+ *
+ * @param endpoint Ver.: always
+ *
+ * TODO Issue #3841
+ * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster
+ * attributes to the default value.
+ * The logic here expects something similar to the deprecated Plugins callback
+ * emberAfPluginOnOffClusterServerPostInitCallback.
+ *
+ */
+void emberAfBooleanStateClusterInitCallback(EndpointId endpoint)
+{
+ ChipLogProgress(Zcl, "emberAfBooleanStateClusterInitCallback\n");
+ GetAppTask().UpdateClusterState();
+}
+
+void logBooleanStateEvent(bool state)
+{
+ EventNumber eventNumber;
+ Events::StateChange::Type event{ state };
+ if (CHIP_NO_ERROR != LogEvent(event, 1, eventNumber))
+ {
+ ChipLogProgress(Zcl, "booleanstate: failed to reacord state-change event");
+ }
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h
new file mode 100644
index 00000000000000..f3e0d729abe2e7
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppEvent.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright (c) 2022 Nest Labs, Inc.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct AppEvent;
+typedef void (*EventHandler)(void *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kButton = 0,
+ kTimer,
+ kContact,
+ kInstall,
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+ kEventType_Lp,
+#endif
+ kOTAResume,
+ };
+
+ AppEventTypes Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t PinNo;
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ } ContactEvent;
+ };
+
+ EventHandler Handler;
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+ void * param;
+#endif
+};
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h
new file mode 100644
index 00000000000000..47b644769cfb63
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h
@@ -0,0 +1,129 @@
+/*
+ *
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "ContactSensorManager.h"
+
+#include "CHIPProjectConfig.h"
+
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "fsl_component_button.h"
+#include "timers.h"
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+class AppTask
+{
+public:
+ CHIP_ERROR StartAppTask();
+ static void AppTaskMain(void * pvParameter);
+
+ void PostContactActionRequest(ContactSensorManager::Action aAction);
+ void PostEvent(const AppEvent * event);
+
+ void UpdateClusterState(void);
+ void UpdateDeviceState(void);
+
+ bool IsSyncClusterToButtonAction();
+ void SetSyncClusterToButtonAction(bool value);
+ // Identify cluster callbacks.
+ static void OnIdentifyStart(Identify * identify);
+ static void OnIdentifyStop(Identify * identify);
+
+private:
+ friend AppTask & GetAppTask(void);
+
+ CHIP_ERROR Init();
+
+ static void OnStateChanged(ContactSensorManager::State aState);
+
+ void CancelTimer(void);
+
+ void DispatchEvent(AppEvent * event);
+
+ static void FunctionTimerEventHandler(void * aGenericEvent);
+ static button_status_t KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam);
+ static void HandleKeyboard(void);
+ static void OTAHandler(void * aGenericEvent);
+ static void BleHandler(void * aGenericEvent);
+ static void BleStartAdvertising(intptr_t arg);
+ static void ContactActionEventHandler(void * aGenericEvent);
+ static void ResetActionEventHandler(void * aGenericEvent);
+ static void InstallEventHandler(void * aGenericEvent);
+
+ static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action);
+ static void TimerEventHandler(TimerHandle_t xTimer);
+
+ static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+ void StartTimer(uint32_t aTimeoutInMs);
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ static void InitOTA(intptr_t arg);
+ static void StartOTAQuery(intptr_t arg);
+#endif
+
+ static void UpdateClusterStateInternal(intptr_t arg);
+ static void UpdateDeviceStateInternal(intptr_t arg);
+ static void InitServer(intptr_t arg);
+ static void PrintOnboardingInfo();
+
+ enum class Function : uint8_t
+ {
+ kNoneSelected = 0,
+ kFactoryReset,
+ kContact,
+ kIdentify,
+ kInvalid
+ };
+
+ Function mFunction = Function::kNoneSelected;
+ bool mResetTimerActive = false;
+ bool mSyncClusterToButtonAction = false;
+
+ static AppTask sAppTask;
+};
+
+inline AppTask & GetAppTask(void)
+{
+ return AppTask::sAppTask;
+}
+
+inline bool AppTask::IsSyncClusterToButtonAction()
+{
+ return mSyncClusterToButtonAction;
+}
+
+inline void AppTask::SetSyncClusterToButtonAction(bool value)
+{
+ mSyncClusterToButtonAction = value;
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h
new file mode 100644
index 00000000000000..69a71ee14ee344
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/ContactSensorManager.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+
+class ContactSensorManager
+{
+public:
+ enum class Action : uint8_t
+ {
+ kSignalDetected = 0,
+ kSignalLost,
+ kInvalid
+ };
+
+ enum class State : uint8_t
+ {
+ kContactClosed = 0,
+ kContactOpened,
+ kInvalid
+ };
+
+ int Init();
+ bool IsContactClosed();
+ void InitiateAction(Action aAction);
+
+ typedef void (*CallbackStateChanged)(State aState);
+ void SetCallback(CallbackStateChanged aCallbackStateChanged);
+
+ static void HandleAction(void * aGenericEvent);
+
+private:
+ friend ContactSensorManager & ContactSensorMgr(void);
+ State mState;
+ CallbackStateChanged mCallbackStateChanged;
+ static ContactSensorManager sContactSensor;
+};
+
+inline ContactSensorManager & ContactSensorMgr(void)
+{
+ return ContactSensorManager::sContactSensor;
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h
new file mode 100644
index 00000000000000..b62ce79567e8db
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ---- Contact Example App Config ----
+
+#define RESET_BUTTON 1
+#define CONTACT_SENSOR_BUTTON 2
+#define OTA_BUTTON 3
+#define BLE_BUTTON 4
+
+#define RESET_BUTTON_PUSH 1
+#define CONTACT_SENSOR_BUTTON_PUSH 2
+#define OTA_BUTTON_PUSH 3
+#define BLE_BUTTON_PUSH 4
+
+#define APP_BUTTON_PUSH 1
+
+#define CONTACT_SENSOR_STATE_LED 1
+#define SYSTEM_STATE_LED 0
+
+// ---- Contact Example SWU Config ----
+#define SWU_INTERVAl_WINDOW_MIN_MS (23 * 60 * 60 * 1000) // 23 hours
+#define SWU_INTERVAl_WINDOW_MAX_MS (24 * 60 * 60 * 1000) // 24 hours
+
+// ---- Thread Polling Config ----
+// #define THREAD_ACTIVE_POLLING_INTERVAL_MS 100
+// #define THREAD_INACTIVE_POLLING_INTERVAL_MS 1000
+
+#if K32W_LOG_ENABLED
+#define K32W_LOG(...) otPlatLog(OT_LOG_LEVEL_NONE, OT_LOG_REGION_API, ##__VA_ARGS__);
+#else
+#define K32W_LOG(...)
+#endif
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp
new file mode 100644
index 00000000000000..700bbc5ad9356c
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/main.cpp
@@ -0,0 +1,143 @@
+/*
+ *
+ * Copyright (c) 2022 Google LLC.
+ * Copyright (c) 2023 NXP
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ================================================================================
+// Main Code
+// ================================================================================
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "FreeRtosHooks.h"
+#include "app_config.h"
+#include "openthread/platform/logging.h"
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Logging;
+
+#include
+
+typedef void (*InitFunc)(void);
+extern InitFunc __init_array_start;
+extern InitFunc __init_array_end;
+
+extern "C" void main_task(void const * argument)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ /* Call C++ constructors */
+ InitFunc * pFunc = &__init_array_start;
+ for (; pFunc < &__init_array_end; ++pFunc)
+ {
+ (*pFunc)();
+ }
+
+ mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
+
+ err = PlatformMgrImpl().InitBoardFwk();
+ if (err != CHIP_NO_ERROR)
+ {
+ return;
+ }
+
+ /* Used for HW initializations */
+ otSysInit(0, NULL);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ return;
+ }
+
+ K32W_LOG("Welcome to NXP Contact Sensor Demo App");
+
+ /* Mbedtls Threading support is needed because both
+ * Thread and Matter tasks are using it */
+ freertos_mbedtls_mutex_init();
+
+ // Init Chip memory management before the stack
+ chip::Platform::MemoryInit();
+
+ err = PlatformMgr().InitChipStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during PlatformMgr().InitMatterStack()");
+ goto exit;
+ }
+
+ err = ThreadStackMgr().InitThreadStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during ThreadStackMgr().InitThreadStack()");
+ goto exit;
+ }
+
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice);
+ if (err != CHIP_NO_ERROR)
+ {
+ goto exit;
+ }
+
+ // Start OpenThread task
+ err = ThreadStackMgrImpl().StartThreadTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during ThreadStackMgrImpl().StartThreadTask()");
+ goto exit;
+ }
+
+ err = GetAppTask().StartAppTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during GetAppTask().StartAppTask()");
+ goto exit;
+ }
+
+ err = PlatformMgr().StartEventLoopTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during PlatformMgr().StartEventLoopTask();");
+ goto exit;
+ }
+
+ GetAppTask().AppTaskMain(NULL);
+
+exit:
+ return;
+}
+
+/**
+ * Glue function called directly by the OpenThread stack
+ * when system event processing work is pending.
+ */
+extern "C" void otSysEventSignalPending(void)
+{
+ BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+ portYIELD_FROM_ISR(yieldRequired);
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip
new file mode 120000
index 00000000000000..305f2077ffe860
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w/k32w1/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../../..
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w1/.gn b/examples/lighting-app/nxp/k32w/k32w1/.gn
new file mode 100644
index 00000000000000..3d48789e30ab3d
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+
+ import("//args.gni")
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn
new file mode 100644
index 00000000000000..fd095a2cb197c5
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn
@@ -0,0 +1,141 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/k32w1_sdk.gni")
+import("//build_overrides/openthread.gni")
+
+import("${k32w1_sdk_build_root}/k32w1_executable.gni")
+import("${k32w1_sdk_build_root}/k32w1_sdk.gni")
+
+import("${chip_root}/src/crypto/crypto.gni")
+import("${chip_root}/src/lib/core/core.gni")
+import("${chip_root}/src/platform/device.gni")
+
+declare_args() {
+ chip_software_version = 0
+}
+
+assert(current_os == "freertos")
+
+k32w1_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w1"
+k32w1_sdk_root = getenv("NXP_K32W1_SDK_ROOT")
+
+k32w1_sdk("sdk") {
+ sources = [
+ "${k32w1_platform_dir}/app/project_include/OpenThreadConfig.h",
+ "include/CHIPProjectConfig.h",
+ "include/FreeRTOSConfig.h",
+ "main/include/app_config.h",
+ ]
+
+ public_deps =
+ [ "${chip_root}/third_party/openthread/platforms:libopenthread-platform" ]
+
+ include_dirs = [
+ "main/include",
+ "main",
+ "include",
+ "${k32w1_platform_dir}/app/project_include",
+ "${k32w1_platform_dir}/app/support",
+ "${k32w1_platform_dir}/app/ldscripts",
+ "${k32w1_platform_dir}/util/include",
+ ]
+
+ defines = []
+ if (is_debug) {
+ defines += [ "BUILD_RELEASE=0" ]
+ } else {
+ defines += [ "BUILD_RELEASE=1" ]
+ }
+
+ if (chip_software_version != 0) {
+ defines += [
+ "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${chip_software_version}",
+ ]
+ }
+}
+
+k32w1_executable("light_app") {
+ output_name = "chip-k32w1-light-example"
+
+ sources = [
+ "${k32w1_platform_dir}/util/LEDWidget.cpp",
+ "${k32w1_platform_dir}/util/include/LEDWidget.h",
+ "main/AppTask.cpp",
+ "main/LightingManager.cpp",
+ "main/ZclCallbacks.cpp",
+ "main/include/AppEvent.h",
+ "main/include/AppTask.h",
+ "main/include/LightingManager.h",
+ "main/main.cpp",
+ ]
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/common/QRCode",
+ "${chip_root}/examples/lighting-app/nxp/zap/",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/platform:syscalls_stub",
+ "${chip_root}/third_party/mbedtls:mbedtls",
+ "${k32w1_platform_dir}/app/support:freertos_mbedtls_utils",
+ ]
+
+ if (chip_openthread_ftd) {
+ deps += [
+ "${chip_root}/third_party/openthread/repo:libopenthread-cli-ftd",
+ "${chip_root}/third_party/openthread/repo:libopenthread-ftd",
+ ]
+ } else {
+ deps += [
+ "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
+ "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
+ ]
+ }
+
+ cflags = [ "-Wconversion" ]
+
+ if (use_smu2_as_system_memory) {
+ ldscript = "${k32w1_platform_dir}/app/ldscripts/k32w1_app.ld"
+ base_ldscript_dir = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc"
+ } else {
+ ldscript = "${k32w1_sdk_root}/middleware/wireless/framework/Common/devices/kw45_k32w1/gcc/connectivity.ld"
+ }
+
+ inputs = [ ldscript ]
+
+ ldflags = [
+ "-Wl,--defsym=__heap_size__=0",
+ "-Wl,--defsym=__stack_size__=0x480",
+ "-Wl,--defsym=gNvmSectors=8",
+ "-Wl,-print-memory-usage",
+ "-Wl,--no-warn-rwx-segments",
+ "-T" + rebase_path(ldscript, root_build_dir),
+ ]
+
+ if (use_smu2_as_system_memory) {
+ ldflags += [ "-L" + rebase_path(base_ldscript_dir, root_build_dir) ]
+ }
+
+ output_dir = root_out_dir
+}
+
+group("k32w1") {
+ deps = [ ":light_app" ]
+}
+
+group("default") {
+ deps = [ ":k32w1" ]
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/README.md b/examples/lighting-app/nxp/k32w/k32w1/README.md
new file mode 100644
index 00000000000000..92dca287111449
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/README.md
@@ -0,0 +1,425 @@
+# Matter K32W1 Lighting Example Application
+
+Matter K32W1 Lighting Example demonstrates how to remotely control a light bulb.
+The light bulb is simulated using one of the LEDs from the expansion board. It
+uses buttons to test turn on/turn off of the light bulb. You can use this
+example as a reference for creating your own application.
+
+The example is based on
+[Matter](https://github.com/project-chip/connectedhomeip) and the NXP K32W1 SDK,
+and supports remote access and control of a light bulb over a low-power,
+802.15.4 Thread network.
+
+The example behaves as a Matter accessory, that is a device that can be paired
+into an existing Matter network and can be controlled by this network.
+
+
+
+- [Matter K32W1 Lighting Example Application](#matter-k32w1-lighting-example-application)
+- [Introduction](#introduction)
+ - [Bluetooth LE Advertising](#bluetooth-le-advertising)
+ - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous)
+- [Device UI](#device-ui)
+- [Building](#building)
+ - [SMU2](#smu2-memory)
+- [Flashing](#flashing)
+ - [Flashing the NBU image](#flashing-the-nbu-image)
+ - [Flashing the host image](#flashing-the-host-image)
+- [Debugging](#debugging)
+- [OTA](#ota)
+
+ - [Convert srec into sb3 file](#convert-srec-into-sb3-file)
+ - [Convert sb3 into ota file](#convert-sb3-into-ota-file)
+ - [Running OTA](#running-ota)
+ - [Known issues](#known-issues)
+
+
+
+## Introduction
+
+
+
+The K32W1 lighting example application provides a working demonstration of a
+light bulb device, built using the Matter codebase and the NXP K32W1 SDK. The
+example supports remote access (e.g.: using CHIP Tool from a mobile phone) and
+control of a light bulb over a low-power, 802.15.4 Thread network. It is capable
+of being paired into an existing Matter network along with other Matter-enabled
+devices.
+
+The Matter device that runs the lighting application is controlled by the Matter
+controller device over the Thread protocol. By default, the Matter device has
+Thread disabled, and it should be paired over Bluetooth LE with the Matter
+controller and obtain configuration from it. The actions required before
+establishing full communication are described below.
+
+### Bluetooth LE Advertising
+
+In this example, to commission the device onto a Matter network, it must be
+discoverable over Bluetooth LE. For security reasons, you must start Bluetooth
+LE advertising manually after powering up the device by pressing Button SW2.
+
+### Bluetooth LE Rendezvous
+
+In this example, the commissioning procedure (called rendezvous) is done over
+Bluetooth LE between a Matter device and the Matter controller, where the
+controller has the commissioner role.
+
+To start the rendezvous, the controller must get the commissioning information
+from the Matter device. The data payload is encoded within a QR code, or printed
+to the UART console.
+
+### Thread Provisioning
+
+## Device UI
+
+The example application provides a simple UI that depicts the state of the
+device and offers basic user control. This UI is implemented via the
+general-purpose LEDs and buttons built in the K32W1 EVK board.
+
+**LED 2** shows the overall state of the device and its connectivity. Four
+states are depicted:
+
+- _Short Flash On (50ms on/950ms off)_ — The device is in an
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+* _Rapid Even Flashing (100ms on/100ms off)_ — The device is in an
+ unprovisioned state and a commissioning application is connected via BLE.
+
+- _Short Flash Off (950ms on/50ms off)_ — The device is full
+ provisioned, but does not yet have full network (Thread) or service
+ connectivity.
+
+* _Solid On_ — The device is fully provisioned and has full network and
+ service connectivity.
+
+NOTE: LED2 will be disabled when CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR is
+enabled. On K32W1 EVK board, `PTB0` is wired to LED2 also is wired to CS (Chip
+Select) External Flash Memory. OTA image is stored in external memory because of
+it's size. If LED2 is enabled then it will affect External Memory CS and OTA
+will not work.
+
+**RGB LED** shows the state of the simulated light bulb. When the LED is lit the
+light bulb is on; when not lit, the light bulb is off.
+
+**Button SW2** can be used to start BLE advertising. A SHORT press of the button
+will enable Bluetooth LE advertising for a predefined period of time. A LONG
+Press Button SW2 initiates a factory reset. After an initial period of 3
+seconds, LED 2 and RGB LED will flash in unison to signal the pending reset.
+After 6 seconds will cause the device to reset its persistent configuration and
+initiate a reboot. The reset action can be cancelled by press SW2 button at any
+point before the 6 second limit.
+
+**Button SW3** can be used to change the state of the simulated light bulb. This
+can be used to mimic a user manually operating a switch. The button behaves as a
+toggle, swapping the state every time it is pressed.
+
+## Building
+
+In order to build the Matter example, we recommend using a Linux distribution
+(the demo-application was compiled on Ubuntu 20.04).
+
+- Download [K32W1 SDK for Matter](https://mcuxpresso.nxp.com/). Creating an
+ nxp.com account is required before being able to download the SDK. Once the
+ account is created, login and follow the steps for downloading K32W148-EVK
+ MCUXpresso SDK. The SDK Builder UI selection should be similar with the one
+ from the image below.
+
+ 
+
+ Please refer to Matter release notes for getting the latest released SDK.
+
+```
+user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W1_SDK_ROOT=/home/user/Desktop/SDK_K32W1/
+user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
+user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w1
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w1$ gn gen out/debug --args="chip_with_ot_cli=0 is_debug=false chip_openthread_ftd=true chip_crypto=\"platform\""
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w1$ ninja -C out/debug
+```
+
+In case that Openthread CLI is needed, `chip_with_ot_cli` build argument must be
+set to 1.
+
+After a successful build, the `elf` and `srec` files are found in `out/debug/` -
+see the files prefixed with `chip-k32w1-light-example`.
+
+### `SMU2` Memory
+
+Some Matter instances and global variables can be placed in the `NBU` `SMU2`
+memory. When compiling with OpenThread FTD support (`chip_openthread_ftd=true`)
+and with `use_smu2_as_system_memory=true`, the following components are placed
+in `SMU2` memory:
+
+- `gImageProcessor` from `OTAImageProcessorImpl.cpp`.
+- `gApplicationProcessor` from `OTAHooks.cpp`.
+- `Server::sServer` from `Server.cpp`.
+- `ThreadStackManagerImpl::sInstance` from `ThreadStackManagerImpl.cpp`.
+
+These instances and global variables are placed in `SMU2` memory through name
+matching in the application linker script. They should not be changed or, if
+changed, the names must be updated in `k32w1_app.ld`. See
+[k32w1_app.ld](../../../../platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld)
+for names and `SMU2` memory range size.
+
+To use the `SMU2` Memory an optimized `NBU` binary is also needed. See
+[Flashing the NBU image](#flashing-the-nbu-image).
+
+## Flashing
+
+Two images must be written to the board: one for the host (CM33) and one for the
+`NBU` (CM3).
+
+The image needed on the host side is the one generated in `out/debug/` while the
+one needed on the `NBU` side can be found in the downloaded NXP-SDK package at
+path -
+`middleware\wireless\ieee-802.15.4\bin\k32w1\k32w1_nbu_ble_15_4_dyn_matter_$version.sb3`.
+
+### Flashing the `NBU` image
+
+`NBU` image should be written only when a new NXP-SDK is released.
+
+[K32W148 board quick start guide](https://www.nxp.com/document/guide/getting-started-with-the-k32w148-development-platform:GS-K32W148EVK)
+can be used for updating the `NBU/radio` core:
+
+- Section 2.4 – Get Software – install `SPSDK` (Secure Provisioning Command
+ Line Tool)
+- Section 3.3 – Updating `NBU` for Wireless examples - use the corresponding
+ .sb3 file found in the SDK package at path
+ `middleware\wireless\ieee-802.15.4\bin\k32w1\`
+
+### Flashing the host image
+
+Host image is the one found under `out/debug/`. It should be written after each
+build process.
+
+If debugging is needed then jump directly to the [Debugging](#debugging)
+section. Otherwise, if only flashing is needed then
+[JLink 7.84b](https://www.segger.com/downloads/jlink/) can be used:
+
+- Plug K32W1 to the USB port (no need to keep the SW4 button pressed while
+ doing this)
+
+- Create a new file, `commands_script`, with the following content (change
+ application name accordingly):
+
+```bash
+reset
+halt
+loadfile chip-k32w1-light-example.srec
+reset
+go
+quit
+```
+
+- copy the application and `commands_script` in the same folder that JLink
+ executable is placed. Execute:
+
+```bash
+$ jlink -device K32W1480 -if SWD -speed 4000 -autoconnect 1 -CommanderScript commands_script
+```
+
+## Debugging
+
+One option for debugging would be to use MCUXpresso IDE.
+
+- Drag-and-drop the zip file containing the NXP SDK in the "Installed SDKs"
+ tab:
+
+
+
+- Import any demo application from the installed SDK:
+
+```
+Import SDK example(s).. -> choose a demo app (demo_apps -> hello_world) -> Finish
+```
+
+
+
+- Flash the previously imported demo application on the board:
+
+```
+Right click on the application (from Project Explorer) -> Debug as -> JLink/CMSIS-DAP
+```
+
+After this step, a debug configuration specific for the K32W1 board was created.
+This debug configuration will be used later on for debugging the application
+resulted after ot-nxp compilation.
+
+- Import Matter repo in MCUXpresso IDE as Makefile Project. Use _none_ as
+ _Toolchain for Indexer Settings_:
+
+```
+File -> Import -> C/C++ -> Existing Code as Makefile Project
+```
+
+
+
+- Replace the path of the existing demo application with the path of the K32W1
+ application:
+
+```
+Run -> Debug Configurations... -> C/C++ Application
+```
+
+
+
+## OTA
+
+### Convert `srec` into `sb3` file
+
+The OTA image files must be encrypted using Over The Air Programming Tool
+([OTAP](https://www.nxp.com/design/microcontrollers-developer-resources/connectivity-tool-suite:CONNECTIVITY-TOOL-SUITE?#downloads)).
+Bootloader will load the new OTA image only if it detects that the file was
+encrypted with the `OTAP` correct keys.
+
+`.srec` file is input for Over The air Programming (`OTAP`) application
+(unencrypted) and it's converted to `.sb3` format (encrypted).
+
+In `OTAP` application
+
+- select OTA protocol => `OTAP` Matter
+- Browse File
+- follow default options (KW45/K32W148, Preserve NVM)
+- image information: will update "Application Core (MCU)" - this will generate
+ the image only for the CM33 core
+- keep other settings at default values
+
+### Convert sb3 into ota file
+
+In order to build an OTA image, use NXP wrapper over the standard tool
+`src/app/ota_image_tool.py`:
+
+- `scripts/tools/nxp/factory_data_generator/ota_image_tool.py` The tool can be
+ used to generate an OTA image with the following format:
+ `| OTA image header | TLV1 | TLV2 | ... | TLVn |` where each TLV is in the
+ form `|tag|length|value|`
+
+Note that "standard" TLV format is used. Matter TLV format is only used for
+factory data TLV value.
+
+Please see more in the
+[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md).
+
+Here is an example that generates an OTA image with application update TLV from
+a sb3 file:
+
+```
+./scripts/tools/nxp/ota/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 43033 -vs "1.0" -da sha256 --app-input-file ~/binaries/chip-k32w1-43033.sb3 ~/binaries/chip-k32w1-43033.ota
+
+```
+
+A note regarding OTA image header version (`-vn` option). An application binary
+has its own software version (given by
+`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION`, which can be overwritten). For
+having a correct OTA process, the OTA header version should be the same as the
+binary embedded software version. A user can set a custom software version in
+the gn build args by setting `chip_software_version` to the wanted version.
+
+### Running OTA
+
+The OTA topology used for OTA testing is illustrated in the figure below.
+Topology is similar with the one used for Matter Test Events.
+
+
+
+The concept for OTA is the next one:
+
+- there is an OTA Provider Application that holds the OTA image. In our case,
+ this is a Linux application running on an Ubuntu based-system;
+- the OTA Requestor functionality is embedded inside the Lighting Application.
+ It will be used for requesting OTA blocks from the OTA Provider;
+- the controller (a linux application called chip-tool) will be used for
+ commissioning both the device and the OTA Provider App. The device will be
+ commissioned using the standard Matter flow (BLE + IEEE 802.15.4) while the
+ OTA Provider Application will be commissioned using the _onnetwork_ option
+ of chip-tool;
+- during commissioning, each device is assigned a node id by the chip-tool
+ (can be specified manually by the user). Using the node id of the device and
+ of the lighting application, chip-tool triggers the OTA transfer by invoking
+ the _announce-ota-provider_ command - basically, the OTA Requestor is
+ informed of the node id of the OTA Provider Application.
+
+_Computer #1_ can be any system running an Ubuntu distribution. We recommand
+using CSA official instructions from
+[here](https://groups.csa-iot.org/wg/matter-csg/document/28566), where RPi 4 are
+proposed. Also, CSA official instructions document point to the OS/Docker images
+that should be used on the RPis. For compatibility reasons, we recommand
+compiling chip-tool and OTA Provider applications with the same commit id that
+was used for compiling the Lighting Application. Also, please note that there is
+a single controller (chip-tool) running on Computer #1 which is used for
+commissioning both the device and the OTA Provider Application. If needed,
+[these instructions](https://itsfoss.com/connect-wifi-terminal-ubuntu/) could be
+used for connecting the RPis to WiFi.
+
+Build the Linux OTA provider application:
+
+```
+user@computer1:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false
+```
+
+Build Linux chip-tool:
+
+```
+user@computer1:~/connectedhomeip$ : ./scripts/examples/gn_build_example.sh examples/chip-tool out/chip-tool-app
+```
+
+Start the OTA Provider Application:
+
+```
+user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_*
+user@computer1:~/connectedhomeip$ : ./out/ota-provider-app/chip-ota-provider-app -f chip-k32w1-43033.ota
+```
+
+Provision the OTA provider application and assign node id _1_. Also, grant ACL
+entries to allow OTA requestors:
+
+```
+user@computer1:~/connectedhomeip$ : rm -rf /tmp/chip_*
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing onnetwork 1 20202021
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0
+```
+
+Provision the device and assign node id _2_:
+
+```
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool pairing ble-thread 2 hex: 20202021 3840
+```
+
+Start the OTA process:
+
+```
+user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-ota-provider 1 0 0 0 2 0
+```
+
+### Known issues
+
+- SRP cache on the openthread border router needs to flushed each time a new
+ commissioning process is attempted. For this, factory reset the device, then
+ execute _ot-ctl server disable_ followed by _ot-ctl server enable_. After
+ this step, the commissioning process of the device can start;
+- Due to some MDNS issues, the commissioning of the OTA Provider Application
+ may fail. Please make sure that the SRP cache is disabled (_ot-ctl srp
+ server disable_) on the openthread border router while commissioning the OTA
+ Provider Application;
+- No other Docker image should be running (e.g.: Docker image needed by Test
+ Harness) except the OTBR one. A docker image can be killed using the
+ command:
+
+```
+user@computer1:~/connectedhomeip$ : sudo docker kill $container_id
+```
+
+- In order to avoid MDNS issues, only one interface should be active at one
+ time. E.g.: if WiFi is used then disable the Ethernet interface and also
+ disable multicast on that interface:
+
+```
+user@computer1:~/connectedhomeip$ sudo ip link set dev eth0 down
+user@computer1:~/connectedhomeip$ sudo ifconfig eth0 -multicast
+```
+
+- If OTBR Docker image is used, then the "-B" parameter should point to the
+ interface used for the backbone.
+
+- If Wi-Fi is used on a RPI4, then a 5Ghz network should be selected.
+ Otherwise, issues related to BLE-WiFi combo may appear.
diff --git a/examples/lighting-app/nxp/k32w/k32w1/args.gni b/examples/lighting-app/nxp/k32w/k32w1/args.gni
new file mode 100644
index 00000000000000..4efb6421f5ca02
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/args.gni
@@ -0,0 +1,23 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/examples/platform/nxp/k32w/k32w1/args.gni")
+
+# SDK target. This is overridden to add our SDK app_config.h & defines.
+k32w1_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_stack_lock_tracking = "fatal"
+chip_enable_ble = true
diff --git a/examples/lighting-app/nxp/k32w/k32w1/build_overrides b/examples/lighting-app/nxp/k32w/k32w1/build_overrides
new file mode 120000
index 00000000000000..ad07557834803a
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/build_overrides
@@ -0,0 +1 @@
+../../../../build_overrides/
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..07d8b6a92f5e69
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Security and Authentication disabled for development build.
+// For convenience, enable CHIP Security Test Mode and disable the requirement for
+// authentication in various protocols.
+// WARNING: These options make it possible to circumvent basic CHIP security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting-app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005
+
+// Use a default setup PIN code if one hasn't been provisioned in flash.
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#define CHIP_DEVICE_CONFIG_USE_TEST_PAIRING_CODE "CHIPUS"
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in CHIP NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 100
+
+#ifndef CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "v0.1.0"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ *
+ * A string identifying the software version running on the device.
+ * CHIP currently expects the software version to be in the format
+ * {MAJOR_VERSION}.0d{MINOR_VERSION}
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8"
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "NXP Semiconductors"
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "NXP Demo App"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC
+ *
+ * Enables synchronizing the device's real time clock with a remote CHIP Time service
+ * using the CHIP Time Sync protocol.
+ */
+// #define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 1
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT
+ *
+ * The amount of time in miliseconds after which BLE should change his advertisements
+ * from fast interval to slow interval.
+ *
+ * 30000 (30 secondes).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000)
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT
+ *
+ * The amount of time in miliseconds after which BLE advertisement should be disabled, counting
+ * from the moment of slow advertisement commencement.
+ *
+ * Defaults to 9000000 (15 minutes).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_ADVERTISING_TIMEOUT (15 * 60 * 1000)
+
+/**
+ * CONFIG_CHIP_NFC_COMMISSIONING, CHIP_DEVICE_CONFIG_ENABLE_NFC
+ *
+ * NFC commissioning is not supported on K32W1
+ */
+#define CONFIG_CHIP_NFC_COMMISSIONING 0
+#define CHIP_DEVICE_CONFIG_ENABLE_NFC 0
+
+/**
+ * @def CHIP_CONFIG_MAX_FABRICS
+ *
+ * @brief
+ * Maximum number of fabrics the device can participate in. Each fabric can
+ * provision the device with its unique operational credentials and manage
+ * its own access control lists.
+ */
+#define CHIP_CONFIG_MAX_FABRICS 5 // 5 is the minimum number of supported fabrics
+
+/**
+ * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER
+ *
+ * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2
+
+/**
+ * @def CHIP_IM_MAX_NUM_WRITE_HANDLER
+ *
+ * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE
+ *
+ * For a development build, set the default importance of events to be logged as Debug.
+ * Since debug is the lowest importance level, this means all standard, critical, info and
+ * debug importance level vi events get logged.
+ */
+#if BUILD_RELEASE
+#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Production
+#else
+#define CHIP_CONFIG_EVENT_LOGGING_DEFAULT_IMPORTANCE chip::Profiles::DataManagement::Debug
+#endif // BUILD_RELEASE
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h b/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h
new file mode 100644
index 00000000000000..95279e6337a7f7
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/include/FreeRTOSConfig.h
@@ -0,0 +1,181 @@
+/*
+ * FreeRTOS Kernel V10.2.0
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+#pragma once
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION 1
+#define configUSE_TICKLESS_IDLE 0
+/* Ensure stdint is only used by the compiler, and not the assembler. */
+#if defined(__ICCARM__) || defined(__ARMCC_VERSION) || defined(__GNUC__)
+#include
+extern uint32_t SystemCoreClock;
+#endif
+#define configCPU_CLOCK_HZ (SystemCoreClock)
+#define configTICK_RATE_HZ ((TickType_t) 100)
+#define configMAX_PRIORITIES (8)
+// idle task stack size needs to be increased for OTA EEPROM processing
+#define configMINIMAL_STACK_SIZE ((unsigned short) 450)
+#define configMAX_TASK_NAME_LEN 20
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
+#define configQUEUE_REGISTRY_SIZE 8
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 0
+#define configUSE_NEWLIB_REENTRANT 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
+
+/* Tasks.c additions (e.g. Thread Aware Debug capability) */
+#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
+
+/* Used memory allocation (heap_x.c) */
+#define configFRTOS_MEMORY_SCHEME 4
+
+/* Memory allocation related definitions. */
+#define configSUPPORT_STATIC_ALLOCATION 0
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
+#define configTOTAL_HEAP_SIZE ((size_t) (gTotalHeapSize_c))
+#define configAPPLICATION_ALLOCATED_HEAP 1
+
+/* Hook function related definitions. */
+#ifndef configUSE_IDLE_HOOK
+#define configUSE_IDLE_HOOK 1
+#endif
+#define configUSE_TICK_HOOK 0
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#ifndef configUSE_MALLOC_FAILED_HOOK
+#define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+/* Task aware debugging. */
+#define configRECORD_STACK_HIGH_ADDRESS 1
+
+/* Co-routine related definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES 2
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
+#define configTIMER_QUEUE_LENGTH 10
+#define configTIMER_TASK_STACK_DEPTH (360)
+
+/* Define to trap errors during development. */
+#define configASSERT(x) \
+ if ((x) == 0) \
+ { \
+ taskDISABLE_INTERRUPTS(); \
+ for (;;) \
+ ; \
+ }
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_xResumeFromISR 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_eTaskGetState 0
+#define INCLUDE_xEventGroupSetBitFromISR 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 0
+#define INCLUDE_xTaskGetHandle 0
+#define INCLUDE_xTaskResumeFromISR 1
+#define INCLUDE_xQueueGetMutexHolder 1
+
+/* Interrupt nesting behaviour configuration. Cortex-M specific. */
+#ifdef __NVIC_PRIO_BITS
+/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+#define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+#define configPRIO_BITS 3
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x7
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+
+#ifndef configENABLE_FPU
+#define configENABLE_FPU 0
+#endif
+#ifndef configENABLE_MPU
+#define configENABLE_MPU 0
+#endif
+#ifndef configENABLE_TRUSTZONE
+#define configENABLE_TRUSTZONE 0
+#endif
+#ifndef configRUN_FREERTOS_SECURE_ONLY
+#define configRUN_FREERTOS_SECURE_ONLY 1
+#endif
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp
new file mode 100644
index 00000000000000..66eee725c581c2
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/AppTask.cpp
@@ -0,0 +1,870 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * Copyright (c) 2021 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "AppTask.h"
+#include "AppEvent.h"
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/* OTA related includes */
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+#include "OtaSupport.h"
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#include "K32W1PersistentStorageOpKeystore.h"
+
+#include "LEDWidget.h"
+#include "app.h"
+#include "app_config.h"
+#include "fsl_component_button.h"
+#include "fwk_platform.h"
+
+#define FACTORY_RESET_TRIGGER_TIMEOUT 6000
+#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+
+TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer.
+
+static QueueHandle_t sAppEventQueue;
+
+/*
+ * The status LED and the external flash CS pin are wired together.
+ * The OTA image writing may fail if used together.
+ */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+static LEDWidget sStatusLED;
+#endif
+static LEDWidget sLightLED;
+
+static bool sIsThreadProvisioned = false;
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+static bool sHaveFullConnectivity = false;
+#endif
+static bool sHaveBLEConnections = false;
+
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+extern "C" void otPlatUartProcess(void);
+#endif
+
+using namespace ::chip::Credentials;
+using namespace ::chip::DeviceLayer;
+using namespace chip;
+using namespace chip::app;
+
+AppTask AppTask::sAppTask;
+
+// This key is for testing/certification only and should not be used in production devices.
+// For production devices this key must be provided from factory data.
+uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop,
+ Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator, AppTask::OnTriggerEffect,
+ // Use invalid value for identifiers to enable TriggerEffect command
+ // to stop Identify command for each effect
+ Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue,
+ Clusters::Identify::EffectVariantEnum::kDefault };
+
+/* OTA related variables */
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+static DefaultOTARequestor gRequestorCore;
+static DefaultOTARequestorStorage gRequestorStorage;
+static DeviceLayer::DefaultOTARequestorDriver gRequestorUser;
+static BDXDownloader gDownloader;
+
+constexpr uint16_t requestedOtaBlockSize = 1024;
+#endif
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent));
+ if (sAppEventQueue == NULL)
+ {
+ err = APP_ERROR_EVENT_QUEUE_FAILED;
+ K32W_LOG("Failed to allocate app event queue");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ return err;
+}
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ PlatformMgr().AddEventHandler(MatterEventHandler, 0);
+
+ // Init ZCL Data Model and start server
+ PlatformMgr().ScheduleWork(InitServer, 0);
+
+ // Initialize device attestation config
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+
+ // QR code will be used with CHIP Tool
+ AppTask::PrintOnboardingInfo();
+
+ if (LightingMgr().Init() != 0)
+ {
+ K32W_LOG("LightingMgr().Init() failed");
+ assert(0);
+ }
+
+ LightingMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+
+ /* start with all LEDS turnedd off */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Init(SYSTEM_STATE_LED, false);
+#endif
+ sLightLED.Init(LIGHT_STATE_LED, false);
+ UpdateDeviceState();
+
+ /* intialize the Keyboard and button press callback */
+ BUTTON_InstallCallback((button_handle_t) g_buttonHandle[0], KBD_Callback, (void *) BLE_BUTTON);
+ BUTTON_InstallCallback((button_handle_t) g_buttonHandle[1], KBD_Callback, (void *) LIGHT_BUTTON);
+
+ // Create FreeRTOS sw timer for Function Selection.
+ sFunctionTimer = xTimerCreate("FnTmr", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = app task obj context
+ TimerEventHandler // timer callback handler
+ );
+
+ if (sFunctionTimer == NULL)
+ {
+ err = APP_ERROR_CREATE_TIMER_FAILED;
+ K32W_LOG("app_timer_create() failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ // Print the current software version
+ char currentSoftwareVer[ConfigurationManager::kMaxSoftwareVersionStringLength + 1] = { 0 };
+ err = ConfigurationMgr().GetSoftwareVersionString(currentSoftwareVer, sizeof(currentSoftwareVer));
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Get version error");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ uint32_t currentVersion;
+ err = ConfigurationMgr().GetSoftwareVersion(currentVersion);
+
+ K32W_LOG("Current Software Version: %s, %d", currentSoftwareVer, currentVersion);
+
+ return err;
+}
+
+void LockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().LockThreadStack();
+}
+
+void UnlockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack();
+}
+
+void AppTask::InitServer(intptr_t arg)
+{
+ static chip::CommonCaseDeviceServerInitParams initParams;
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+
+#if CHIP_CRYPTO_PLATFORM
+ static chip::K32W1PersistentStorageOpKeystore sK32W1PersistentStorageOpKeystore;
+ VerifyOrDie((sK32W1PersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR);
+ initParams.operationalKeystore = &sK32W1PersistentStorageOpKeystore;
+#endif
+
+ // Init ZCL Data Model and start server
+ static DefaultTestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
+ initParams.testEventTriggerDelegate = &testEventTriggerDelegate;
+ chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
+ nativeParams.lockCb = LockOpenThreadTask;
+ nativeParams.unlockCb = UnlockOpenThreadTask;
+ nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
+ initParams.endpointNativeParams = static_cast(&nativeParams);
+ VerifyOrDie((chip::Server::GetInstance().Init(initParams)) == CHIP_NO_ERROR);
+}
+
+void AppTask::PrintOnboardingInfo()
+{
+ chip::PayloadContents payload;
+ CHIP_ERROR err = GetPayloadContents(payload, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "GetPayloadContents() failed: %" CHIP_ERROR_FORMAT, err.Format());
+ }
+ payload.commissioningFlow = chip::CommissioningFlow::kUserActionRequired;
+ PrintOnboardingCodes(payload);
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+void AppTask::InitOTA(intptr_t arg)
+{
+ // Initialize and interconnect the Requestor and Image Processor objects -- START
+ SetRequestorInstance(&gRequestorCore);
+
+ gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage());
+ gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader);
+ gRequestorUser.SetMaxDownloadBlockSize(requestedOtaBlockSize);
+ auto & imageProcessor = OTAImageProcessorImpl::GetDefaultInstance();
+ gRequestorUser.Init(&gRequestorCore, &imageProcessor);
+ CHIP_ERROR err = imageProcessor.Init(&gDownloader);
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Image processor init failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ // Connect the gDownloader and Image Processor objects
+ gDownloader.SetImageProcessorDelegate(&imageProcessor);
+ // Initialize and interconnect the Requestor and Image Processor objects -- END
+}
+#endif
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("AppTask.Init() failed");
+ assert(err == CHIP_NO_ERROR);
+ }
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10));
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+
+ // Collect connectivity and configuration state from the CHIP stack. Because the
+ // CHIP event loop is being run in a separate task, the stack must be locked
+ // while these values are queried. However we use a non-blocking lock request
+ // (TryLockChipStack()) to avoid blocking other UI activities when the CHIP
+ // task is busy (e.g. with a long crypto operation).
+ if (PlatformMgr().TryLockChipStack())
+ {
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+ otPlatUartProcess();
+#endif
+
+ sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
+ sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0);
+ PlatformMgr().UnlockChipStack();
+ }
+
+ // Update the status LED if factory reset or identify process have not been initiated.
+ //
+ // If system has "full connectivity", keep the LED On constantly.
+ //
+ // If thread and service provisioned, but not attached to the thread network yet OR no
+ // connectivity to the service OR subscriptions are not fully established
+ // THEN blink the LED Off for a short period of time.
+ //
+ // If the system has ble connection(s) uptill the stage above, THEN blink the LEDs at an even
+ // rate of 100ms.
+ //
+ // Otherwise, blink the LED ON for a very short time.
+ if (sAppTask.mFunction != kFunction_FactoryReset)
+ {
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (sHaveFullConnectivity)
+ {
+ sStatusLED.Set(true);
+ }
+ else if (sIsThreadProvisioned)
+ {
+ sStatusLED.Blink(950, 50);
+ }
+ else if (sHaveBLEConnections)
+ {
+ sStatusLED.Blink(100, 100);
+ }
+ else
+ {
+ sStatusLED.Blink(50, 950);
+ }
+#endif
+ }
+
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Animate();
+#endif
+ sLightLED.Animate();
+ }
+}
+
+void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action)
+{
+ if ((pin_no != RESET_BUTTON) && (pin_no != LIGHT_BUTTON) && (pin_no != OTA_BUTTON) && (pin_no != BLE_BUTTON))
+ {
+ return;
+ }
+
+ AppEvent button_event;
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.PinNo = pin_no;
+ button_event.ButtonEvent.Action = button_action;
+
+ if (pin_no == LIGHT_BUTTON)
+ {
+ button_event.Handler = LightActionEventHandler;
+ }
+ else if (pin_no == OTA_BUTTON)
+ {
+ // button_event.Handler = OTAHandler;
+ }
+ else if (pin_no == BLE_BUTTON)
+ {
+ button_event.Handler = BleHandler;
+
+ if (button_action == RESET_BUTTON_PUSH)
+ {
+ button_event.Handler = ResetActionEventHandler;
+ }
+ }
+ sAppTask.PostEvent(&button_event);
+}
+
+button_status_t AppTask::KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam)
+{
+ uint32_t pinNb = (uint32_t) callbackParam;
+ switch (message->event)
+ {
+ case kBUTTON_EventOneClick:
+ case kBUTTON_EventShortPress:
+ switch (pinNb)
+ {
+ case BLE_BUTTON:
+ K32W_LOG("pb1 short press");
+ if (sAppTask.mResetTimerActive)
+ {
+ ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH);
+ }
+ else
+ {
+ ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH);
+ }
+ break;
+
+ case LIGHT_BUTTON:
+ K32W_LOG("pb2 short press");
+ ButtonEventHandler(LIGHT_BUTTON, LIGHT_BUTTON_PUSH);
+ break;
+ }
+ break;
+
+ case kBUTTON_EventLongPress:
+ switch (pinNb)
+ {
+ case BLE_BUTTON:
+ K32W_LOG("pb1 long press");
+ ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH);
+ break;
+
+ case LIGHT_BUTTON:
+ K32W_LOG("pb2 long press");
+ ButtonEventHandler(OTA_BUTTON, OTA_BUTTON_PUSH);
+ break;
+ }
+ break;
+
+ default:
+ /* No action required */
+ break;
+ }
+ return kStatus_BUTTON_Success;
+}
+
+void AppTask::TimerEventHandler(TimerHandle_t xTimer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = (void *) xTimer;
+ event.Handler = FunctionTimerEventHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Timer)
+ return;
+
+ K32W_LOG("Device will factory reset...");
+
+ // Actually trigger Factory Reset
+ chip::Server::GetInstance().ScheduleFactoryReset();
+}
+
+void AppTask::ResetActionEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->ButtonEvent.PinNo != RESET_BUTTON && aEvent->ButtonEvent.PinNo != BLE_BUTTON)
+ return;
+
+ if (sAppTask.mResetTimerActive)
+ {
+ sAppTask.CancelTimer();
+ sAppTask.mFunction = kFunction_NoneSelected;
+
+ RestoreLightingState();
+
+ K32W_LOG("Factory Reset was cancelled!");
+ }
+ else
+ {
+ uint32_t resetTimeout = FACTORY_RESET_TRIGGER_TIMEOUT;
+
+ if (sAppTask.mFunction != kFunction_NoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate Factory Reset!");
+ return;
+ }
+
+ K32W_LOG("Factory Reset Triggered. Push the RESET button within %lu ms to cancel!", resetTimeout);
+ sAppTask.mFunction = kFunction_FactoryReset;
+
+ /* LEDs will start blinking to signal that a Factory Reset was scheduled */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Set(false);
+#endif
+ sLightLED.Set(false);
+
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ sStatusLED.Blink(500);
+#endif
+ sLightLED.Blink(500);
+
+ sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+ }
+}
+
+void AppTask::LightActionEventHandler(AppEvent * aEvent)
+{
+ LightingManager::Action_t action;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ int32_t actor = 0;
+ bool initiated = false;
+
+ if (sAppTask.mFunction != kFunction_NoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate ON/OFF Light command!");
+ return;
+ }
+
+ if (aEvent->Type == AppEvent::kEventType_TurnOn)
+ {
+ action = static_cast(aEvent->LightEvent.Action);
+ actor = aEvent->LightEvent.Actor;
+ }
+ else if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ actor = AppEvent::kEventType_Button;
+
+ if (LightingMgr().IsTurnedOff())
+ {
+ action = LightingManager::TURNON_ACTION;
+ }
+ else
+ {
+ action = LightingManager::TURNOFF_ACTION;
+ }
+ }
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ action = LightingManager::INVALID_ACTION;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ initiated = LightingMgr().InitiateAction(actor, action);
+
+ if (!initiated)
+ {
+ K32W_LOG("Action is already in progress or active.");
+ }
+ }
+}
+
+void AppTask::OTAHandler(AppEvent * aEvent)
+{
+ if (aEvent->ButtonEvent.PinNo != OTA_BUTTON)
+ return;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (sAppTask.mFunction != kFunction_NoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate OTA!");
+ return;
+ }
+
+ PlatformMgr().ScheduleWork(StartOTAQuery, 0);
+#endif
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+void AppTask::StartOTAQuery(intptr_t arg)
+{
+ GetRequestorInstance()->TriggerImmediateQuery();
+}
+#endif
+
+void AppTask::BleHandler(AppEvent * aEvent)
+{
+ if (aEvent->ButtonEvent.PinNo != BLE_BUTTON)
+ return;
+
+ if (sAppTask.mFunction != kFunction_NoneSelected)
+ {
+ K32W_LOG("Another function is scheduled. Could not toggle BLE state!");
+ return;
+ }
+ PlatformMgr().ScheduleWork(AppTask::BleStartAdvertising, 0);
+}
+
+void AppTask::BleStartAdvertising(intptr_t arg)
+{
+ if (ConnectivityMgr().IsBLEAdvertisingEnabled())
+ {
+ ConnectivityMgr().SetBLEAdvertisingEnabled(false);
+ K32W_LOG("Stopped BLE Advertising!");
+ }
+ else
+ {
+ ConnectivityMgr().SetBLEAdvertisingEnabled(true);
+ if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() == CHIP_NO_ERROR)
+ {
+ K32W_LOG("Started BLE Advertising!");
+ }
+ else
+ {
+ K32W_LOG("OpenBasicCommissioningWindow() failed");
+ }
+ }
+}
+
+void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t)
+{
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ if (event->Type == DeviceEventType::kDnssdInitialized)
+ {
+ K32W_LOG("Dnssd platform initialized.");
+ PlatformMgr().ScheduleWork(InitOTA, 0);
+ }
+#else
+ if (event->Type == DeviceEventType::kDnssdInitialized)
+ {
+ sHaveFullConnectivity = TRUE;
+ }
+#endif
+}
+
+void AppTask::CancelTimer()
+{
+ if (xTimerStop(sFunctionTimer, 0) == pdFAIL)
+ {
+ K32W_LOG("app timer stop() failed");
+ }
+
+ mResetTimerActive = false;
+}
+
+void AppTask::StartTimer(uint32_t aTimeoutInMs)
+{
+ if (xTimerIsTimerActive(sFunctionTimer))
+ {
+ K32W_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+ {
+ K32W_LOG("app timer start() failed");
+ }
+
+ mResetTimerActive = true;
+}
+
+void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
+{
+ // start flashing the LEDs rapidly to indicate action initiation.
+ if (aAction == LightingManager::TURNON_ACTION)
+ {
+ K32W_LOG("Turn on Action has been initiated")
+ }
+ else if (aAction == LightingManager::TURNOFF_ACTION)
+ {
+ K32W_LOG("Turn off Action has been initiated")
+ }
+
+ if (aActor == AppEvent::kEventType_Button)
+ {
+ sAppTask.mSyncClusterToButtonAction = true;
+ }
+
+ sAppTask.mFunction = kFunctionTurnOnTurnOff;
+}
+
+void AppTask::ActionCompleted(LightingManager::Action_t aAction)
+{
+ // Turn on the light LED if in a TURNON state OR
+ // Turn off the light LED if in a TURNOFF state.
+ if (aAction == LightingManager::TURNON_ACTION)
+ {
+ K32W_LOG("Turn on action has been completed")
+ sLightLED.Set(true);
+ }
+ else if (aAction == LightingManager::TURNOFF_ACTION)
+ {
+ K32W_LOG("Turn off action has been completed")
+ sLightLED.Set(false);
+ }
+
+ if (sAppTask.mSyncClusterToButtonAction)
+ {
+ sAppTask.UpdateClusterState();
+ sAppTask.mSyncClusterToButtonAction = false;
+ }
+
+ sAppTask.mFunction = kFunction_NoneSelected;
+}
+
+void AppTask::RestoreLightingState(void)
+{
+ /* restore initial state for the LED indicating Lighting state */
+ if (LightingMgr().IsTurnedOff())
+ {
+ sLightLED.Set(false);
+ }
+ else
+ {
+ sLightLED.Set(true);
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction))
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate Identify process!");
+ return;
+ }
+
+ if (kFunction_TriggerEffect == sAppTask.mFunction)
+ {
+ chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify);
+ OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify);
+ }
+
+ ChipLogProgress(Zcl, "Identify process has started. Status LED should blink with a period of 0.5 seconds.");
+ sAppTask.mFunction = kFunction_Identify;
+ sLightLED.Set(false);
+ sLightLED.Blink(250);
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ if (kFunction_Identify == sAppTask.mFunction)
+ {
+ ChipLogProgress(Zcl, "Identify process has stopped.");
+ sAppTask.mFunction = kFunction_NoneSelected;
+
+ RestoreLightingState();
+ }
+}
+
+void AppTask::OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState)
+{
+ // Let Identify command take over if called during TriggerEffect already running
+ if (kFunction_TriggerEffect == sAppTask.mFunction)
+ {
+ ChipLogProgress(Zcl, "TriggerEffect has stopped.");
+ sAppTask.mFunction = kFunction_NoneSelected;
+
+ // TriggerEffect finished - reset identifiers
+ // Use invalid value for identifiers to enable TriggerEffect command
+ // to stop Identify command for each effect
+ gIdentify.mCurrentEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue;
+ gIdentify.mTargetEffectIdentifier = Clusters::Identify::EffectIdentifierEnum::kUnknownEnumValue;
+ gIdentify.mEffectVariant = Clusters::Identify::EffectVariantEnum::kDefault;
+
+ RestoreLightingState();
+ }
+}
+
+void AppTask::OnTriggerEffect(Identify * identify)
+{
+ // Allow overlapping TriggerEffect calls
+ if ((kFunction_NoneSelected != sAppTask.mFunction) && (kFunction_TriggerEffect != sAppTask.mFunction))
+ {
+ K32W_LOG("Another function is scheduled. Could not initiate Identify process!");
+ return;
+ }
+
+ sAppTask.mFunction = kFunction_TriggerEffect;
+ uint16_t timerDelay = 0;
+
+ ChipLogProgress(Zcl, "TriggerEffect has started.");
+
+ switch (identify->mCurrentEffectIdentifier)
+ {
+ case Clusters::Identify::EffectIdentifierEnum::kBlink:
+ timerDelay = 2;
+ break;
+
+ case Clusters::Identify::EffectIdentifierEnum::kBreathe:
+ timerDelay = 15;
+ break;
+
+ case Clusters::Identify::EffectIdentifierEnum::kOkay:
+ timerDelay = 4;
+ break;
+
+ case Clusters::Identify::EffectIdentifierEnum::kChannelChange:
+ ChipLogProgress(Zcl, "Channel Change effect not supported, using effect %d",
+ to_underlying(Clusters::Identify::EffectIdentifierEnum::kBlink));
+ timerDelay = 2;
+ break;
+
+ case Clusters::Identify::EffectIdentifierEnum::kFinishEffect:
+ chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify);
+ timerDelay = 1;
+ break;
+
+ case Clusters::Identify::EffectIdentifierEnum::kStopEffect:
+ chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerEffectComplete, identify);
+ OnTriggerEffectComplete(&chip::DeviceLayer::SystemLayer(), identify);
+ break;
+
+ default:
+ ChipLogProgress(Zcl, "Invalid effect identifier.");
+ }
+
+ if (timerDelay)
+ {
+ sLightLED.Set(false);
+ sLightLED.Blink(500);
+
+ chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(timerDelay), OnTriggerEffectComplete, identify);
+ }
+}
+
+void AppTask::PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_TurnOn;
+ event.LightEvent.Actor = aActor;
+ event.LightEvent.Action = aAction;
+ event.Handler = LightActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::PostEvent(const AppEvent * aEvent)
+{
+ if (sAppEventQueue != NULL)
+ {
+ if (!xQueueSend(sAppEventQueue, aEvent, 1))
+ {
+ K32W_LOG("Failed to post event to app task event queue");
+ }
+ }
+}
+
+void AppTask::DispatchEvent(AppEvent * aEvent)
+{
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ K32W_LOG("Event received with no handler. Dropping event.");
+ }
+}
+
+void AppTask::UpdateClusterState(void)
+{
+ PlatformMgr().ScheduleWork(UpdateClusterStateInternal, 0);
+}
+
+void AppTask::UpdateClusterStateInternal(intptr_t arg)
+{
+ uint8_t newValue = !LightingMgr().IsTurnedOff();
+
+ // write the new on/off value
+ EmberAfStatus status = app::Clusters::OnOff::Attributes::OnOff::Set(1, newValue);
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ ChipLogError(NotSpecified, "ERR: updating on/off %x", status);
+ }
+}
+
+void AppTask::UpdateDeviceState(void)
+{
+ PlatformMgr().ScheduleWork(UpdateDeviceStateInternal, 0);
+}
+
+void AppTask::UpdateDeviceStateInternal(intptr_t arg)
+{
+ bool onoffAttrValue = 0;
+
+ /* get onoff attribute value */
+ (void) app::Clusters::OnOff::Attributes::OnOff::Get(1, &onoffAttrValue);
+
+ /* set the device state */
+ sLightLED.Set(onoffAttrValue);
+ LightingMgr().SetState(onoffAttrValue);
+}
+
+extern "C" void OTAIdleActivities(void)
+{
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ OTA_TransactionResume();
+#endif
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp
new file mode 100644
index 00000000000000..7a5cefc9b668fc
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/LightingManager.cpp
@@ -0,0 +1,80 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LightingManager.h"
+
+#include "AppTask.h"
+#include "FreeRTOS.h"
+
+#include "app_config.h"
+
+LightingManager LightingManager::sLight;
+
+int LightingManager::Init()
+{
+ mState = kState_On;
+
+ return 0;
+}
+
+void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+ mActionInitiated_CB = aActionInitiated_CB;
+ mActionCompleted_CB = aActionCompleted_CB;
+}
+
+void LightingManager::SetState(bool state)
+{
+ mState = state ? kState_On : kState_Off;
+}
+
+bool LightingManager::IsTurnedOff()
+{
+ return (mState == kState_Off) ? true : false;
+}
+
+bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+ bool action_initiated = false;
+
+ if (mState == kState_On && aAction == TURNOFF_ACTION)
+ {
+ action_initiated = true;
+ mState = kState_Off;
+ }
+ else if (mState == kState_Off && aAction == TURNON_ACTION)
+ {
+ action_initiated = true;
+ mState = kState_On;
+ }
+
+ if (action_initiated)
+ {
+ if (mActionInitiated_CB)
+ {
+ mActionInitiated_CB(aAction, aActor);
+ }
+ if (mActionCompleted_CB)
+ {
+ mActionCompleted_CB(aAction);
+ }
+ }
+
+ return action_initiated;
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..5a4eee6e2c09e4
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/ZclCallbacks.cpp
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "AppTask.h"
+#include "LightingManager.h"
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value)
+{
+ if (path.mClusterId == OnOff::Id)
+ {
+ if (path.mAttributeId != OnOff::Attributes::OnOff::Id)
+ {
+ ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId));
+ return;
+ }
+
+ LightingMgr().InitiateAction(0, *value ? LightingManager::TURNON_ACTION : LightingManager::TURNOFF_ACTION);
+ }
+ else if (path.mClusterId == LevelControl::Id)
+ {
+ ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(path.mAttributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (path.mClusterId == ColorControl::Id)
+ {
+ ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(path.mAttributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (path.mClusterId == OnOffSwitchConfiguration::Id)
+ {
+ ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(path.mAttributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else
+ {
+ ChipLogProgress(Zcl, "Unknown attribute ID: " ChipLogFormatMEI, ChipLogValueMEI(path.mAttributeId));
+ }
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h
new file mode 100644
index 00000000000000..902c70b3cb656f
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/include/AppEvent.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * Copyright (c) 2021 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_None = 0,
+ kEventType_Button,
+ kEventType_Timer,
+ kEventType_TurnOn,
+ kEventType_Install,
+ kEventType_OTAResume,
+ };
+
+ AppEventTypes Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t PinNo;
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LightEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h
new file mode 100644
index 00000000000000..db81edf168c41e
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/include/AppTask.h
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright (c) 2021 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "LightingManager.h"
+
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "fsl_component_button.h"
+#include "timers.h"
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+class AppTask
+{
+public:
+ CHIP_ERROR StartAppTask();
+ static void AppTaskMain(void * pvParameter);
+
+ void PostTurnOnActionRequest(int32_t aActor, LightingManager::Action_t aAction);
+ void PostEvent(const AppEvent * event);
+
+ void UpdateClusterState(void);
+ void UpdateDeviceState(void);
+
+ // Identify cluster callbacks.
+ static void OnIdentifyStart(Identify * identify);
+ static void OnIdentifyStop(Identify * identify);
+ static void OnTriggerEffect(Identify * identify);
+ static void OnTriggerEffectComplete(chip::System::Layer * systemLayer, void * appState);
+
+private:
+ friend AppTask & GetAppTask(void);
+
+ CHIP_ERROR Init();
+
+ static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
+ static void ActionCompleted(LightingManager::Action_t aAction);
+
+ void CancelTimer(void);
+
+ void DispatchEvent(AppEvent * event);
+
+ static void FunctionTimerEventHandler(AppEvent * aEvent);
+ static button_status_t KBD_Callback(void * buttonHandle, button_callback_message_t * message, void * callbackParam);
+ static void OTAHandler(AppEvent * aEvent);
+ static void BleHandler(AppEvent * aEvent);
+ static void BleStartAdvertising(intptr_t arg);
+ static void LightActionEventHandler(AppEvent * aEvent);
+ static void ResetActionEventHandler(AppEvent * aEvent);
+ static void InstallEventHandler(AppEvent * aEvent);
+
+ static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action);
+ static void TimerEventHandler(TimerHandle_t xTimer);
+
+ static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+ void StartTimer(uint32_t aTimeoutInMs);
+
+ static void RestoreLightingState(void);
+
+#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
+ static void InitOTA(intptr_t arg);
+ static void StartOTAQuery(intptr_t arg);
+#endif
+
+ static void UpdateClusterStateInternal(intptr_t arg);
+ static void UpdateDeviceStateInternal(intptr_t arg);
+ static void InitServer(intptr_t arg);
+ static void PrintOnboardingInfo();
+
+ enum Function_t
+ {
+ kFunction_NoneSelected = 0,
+ kFunction_FactoryReset,
+ kFunctionTurnOnTurnOff,
+ kFunction_Identify,
+ kFunction_TriggerEffect,
+ kFunction_Invalid
+ } Function;
+
+ Function_t mFunction = kFunction_NoneSelected;
+ bool mResetTimerActive = false;
+ bool mSyncClusterToButtonAction = false;
+
+ static AppTask sAppTask;
+};
+
+inline AppTask & GetAppTask(void)
+{
+ return AppTask::sAppTask;
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h
new file mode 100644
index 00000000000000..327bf3bdf02763
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/include/LightingManager.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * Copyright (c) 2021 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+
+class LightingManager
+{
+public:
+ enum Action_t
+ {
+ TURNON_ACTION = 0,
+ TURNOFF_ACTION,
+
+ INVALID_ACTION
+ } Action;
+
+ enum State_t
+ {
+ kState_On = 0,
+ kState_Off,
+ } State;
+
+ int Init();
+ bool IsTurnedOff();
+ bool InitiateAction(int32_t aActor, Action_t aAction);
+
+ typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+ typedef void (*Callback_fn_completed)(Action_t);
+ void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+ void SetState(bool state);
+
+private:
+ friend LightingManager & LightingMgr(void);
+ State_t mState;
+
+ Callback_fn_initiated mActionInitiated_CB;
+ Callback_fn_completed mActionCompleted_CB;
+
+ static LightingManager sLight;
+};
+
+inline LightingManager & LightingMgr(void)
+{
+ return LightingManager::sLight;
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h b/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h
new file mode 100644
index 00000000000000..ff938f494b089d
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/include/app_config.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (c) 2021 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ---- Light Example App Config ----
+
+#define RESET_BUTTON 1
+#define LIGHT_BUTTON 2
+#define OTA_BUTTON 3
+#define BLE_BUTTON 4
+
+#define RESET_BUTTON_PUSH 1
+#define LIGHT_BUTTON_PUSH 2
+#define OTA_BUTTON_PUSH 3
+#define BLE_BUTTON_PUSH 4
+
+#define APP_BUTTON_PUSH 1
+
+#define LIGHT_STATE_LED 1
+#define SYSTEM_STATE_LED 0
+
+// Time it takes for the light to switch on/off
+#define ACTUATOR_MOVEMENT_PERIOS_MS 50
+
+// ---- Light Example SWU Config ----
+#define SWU_INTERVAl_WINDOW_MIN_MS (23 * 60 * 60 * 1000) // 23 hours
+#define SWU_INTERVAl_WINDOW_MAX_MS (24 * 60 * 60 * 1000) // 24 hours
+
+#if K32W_LOG_ENABLED
+#define K32W_LOG(...) otPlatLog(OT_LOG_LEVEL_NONE, OT_LOG_REGION_API, ##__VA_ARGS__);
+#else
+#define K32W_LOG(...)
+#endif
diff --git a/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp b/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp
new file mode 100644
index 00000000000000..7ebd3f3ed3b1b7
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/main/main.cpp
@@ -0,0 +1,140 @@
+/*
+ *
+ * Copyright (c) 2021 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ================================================================================
+// Main Code
+// ================================================================================
+
+#include "openthread/platform/logging.h"
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "FreeRtosHooks.h"
+#include "app_config.h"
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Logging;
+
+#include
+
+typedef void (*InitFunc)(void);
+extern InitFunc __init_array_start;
+extern InitFunc __init_array_end;
+
+extern "C" void main_task(void const * argument)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ /* Call C++ constructors */
+ InitFunc * pFunc = &__init_array_start;
+ for (; pFunc < &__init_array_end; ++pFunc)
+ {
+ (*pFunc)();
+ }
+
+ mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
+
+ err = PlatformMgrImpl().InitBoardFwk();
+ if (err != CHIP_NO_ERROR)
+ {
+ return;
+ }
+
+ /* Used for HW initializations */
+ otSysInit(0, NULL);
+
+ K32W_LOG("Welcome to NXP Lighting Demo App");
+
+ /* Mbedtls Threading support is needed because both
+ * Thread and Matter tasks are using it */
+ freertos_mbedtls_mutex_init();
+
+ // Init Chip memory management before the stack
+ chip::Platform::MemoryInit();
+
+ err = PlatformMgr().InitChipStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during PlatformMgr().InitMatterStack()");
+ goto exit;
+ }
+
+ err = ThreadStackMgr().InitThreadStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during ThreadStackMgr().InitThreadStack()");
+ goto exit;
+ }
+
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ goto exit;
+ }
+
+ // Start OpenThread task
+ err = ThreadStackMgrImpl().StartThreadTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during ThreadStackMgrImpl().StartThreadTask()");
+ goto exit;
+ }
+
+ err = GetAppTask().StartAppTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during GetAppTask().StartAppTask()");
+ goto exit;
+ }
+
+ err = PlatformMgr().StartEventLoopTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ K32W_LOG("Error during PlatformMgr().StartEventLoopTask();");
+ goto exit;
+ }
+
+ GetAppTask().AppTaskMain(NULL);
+
+exit:
+ return;
+}
+
+/**
+ * Glue function called directly by the OpenThread stack
+ * when system event processing work is pending.
+ */
+extern "C" void otSysEventSignalPending(void)
+{
+ {
+ BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+ portYIELD_FROM_ISR(yieldRequired);
+ }
+}
diff --git a/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip b/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip
new file mode 120000
index 00000000000000..305f2077ffe860
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w/k32w1/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../../..
\ No newline at end of file
diff --git a/examples/platform/nxp/k32w/k32w1/BUILD.gn b/examples/platform/nxp/k32w/k32w1/BUILD.gn
new file mode 100644
index 00000000000000..0a980406bce075
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/k32w1_sdk.gni")
+
+import("${k32w1_sdk_build_root}/k32w1_sdk.gni")
+
+config("chip_examples_project_config") {
+ include_dirs = [
+ "app/project_include",
+ "${chip_root}",
+ ]
+}
+
+source_set("openthread_core_config_k32w1_chip_examples") {
+ sources = [ "app/project_include/OpenThreadConfig.h" ]
+
+ public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w1:openthread_core_config_k32w1" ]
+
+ public_configs = [ ":chip_examples_project_config" ]
+}
diff --git a/examples/platform/nxp/k32w/k32w1/app/BUILD.gn b/examples/platform/nxp/k32w/k32w1/app/BUILD.gn
new file mode 100644
index 00000000000000..6671d140688df9
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+
+config("chip_examples_project_config") {
+ include_dirs = [ "app/project_include" ]
+}
+
+source_set("openthread_core_config_k32w1_chip_examples") {
+ sources = [ "app/project_include/OpenThreadConfig.h" ]
+
+ public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w1:openthread_core_config_k32w1" ]
+
+ public_configs = [ ":chip_examples_project_config" ]
+}
diff --git a/examples/platform/nxp/k32w/k32w1/app/args.gni b/examples/platform/nxp/k32w/k32w1/app/args.gni
new file mode 100644
index 00000000000000..c09510c14df229
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/args.gni
@@ -0,0 +1,33 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+
+import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni")
+
+arm_float_abi = "hard"
+arm_cpu = "cortex-m33"
+arm_fpu = "fpv5-sp-d16"
+arm_arch = "armv8-m.main+dsp+fp"
+
+openthread_project_core_config_file = "OpenThreadConfig.h"
+
+chip_ble_project_config_include = ""
+chip_device_project_config_include = ""
+chip_project_config_include = ""
+chip_inet_project_config_include = ""
+chip_system_project_config_include = ""
+
+chip_system_config_provide_statistics = false
+chip_with_nlfaultinjection = true
diff --git a/examples/platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld b/examples/platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld
new file mode 100644
index 00000000000000..de9c882af9fed4
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/ldscripts/k32w1_app.ld
@@ -0,0 +1,52 @@
+/*
+** Copyright (c) 2023 Project CHIP Authors
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+m_smu2_data_start = 0x489C0000;
+m_smu2_data_end = 0x489C537B;
+m_smu2_data_size = m_smu2_data_end - m_smu2_data_start + 1;
+
+/* Specify the extra application specific memory areas */
+MEMORY
+{
+ m_smu2_data (RW) : ORIGIN = m_smu2_data_start, LENGTH = m_smu2_data_size
+}
+
+
+/* Define the extra application specific output sections */
+SECTIONS
+{
+ .smu2 (NOLOAD) :
+ {
+ /* This is used by the startup in order to initialize the free .smu2 section */
+ . = ALIGN(4);
+ __START_SMU2 = .;
+ __smu2_start__ = .;
+ *(.smu2)
+ /* These input section descriptions should not be changed as they match */
+ /* specific Matter instances/global variables. */
+ *(.bss.*chip*Server*sServer*)
+ *(*gImageProcessor)
+ *(*gApplicationProcessor)
+ *(.bss.*ThreadStackManagerImpl*sInstance*)
+ . = ALIGN(4);
+ __smu2_end__ = .;
+ __END_SMU2 = .;
+ ASSERT(__smu2_end__ > 18K, "SMU2 section unexpected end address, check variable names");
+ } > m_smu2_data
+}
+
+
+INCLUDE connectivity.ld
diff --git a/examples/platform/nxp/k32w/k32w1/app/project_include/OpenThreadConfig.h b/examples/platform/nxp/k32w/k32w1/app/project_include/OpenThreadConfig.h
new file mode 100644
index 00000000000000..932812aa711659
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/project_include/OpenThreadConfig.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Overrides to default OpenThread configuration.
+ *
+ */
+
+#pragma once
+
+// Disable the Nxp-supplied OpenThread logging facilities
+// and use the facilities provided by the Device Layer
+// (see src/platform/K32W/Logging.cpp).
+#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP
+
+// When operating in a less than ideal RF environment, having a more forgiving configuration
+// of OpenThread makes thread a great deal more reliable.
+#define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY 120 // default is 28800
+#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 15 // default is 3
+#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT 1 // default is 0
+#define OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS 16 // default is 4
+
+// Enable periodic parent search to speed up finding a better parent.
+#define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1 // default is 0
+#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -45 // default is -65
+#define OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1 // default is 0
+
+// Use smaller maximum interval to speed up reattaching.
+#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL (60 * 10 * 1000) // default 1200000 ms
+
+// disable unused features
+#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0
+#define OPENTHREAD_CONFIG_JOINER_ENABLE 0
+#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0
+#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0
+#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0
+#define OPENTHREAD_CONFIG_TCP_ENABLE 0
+
+#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 0
+#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 0
+
+#define OPENTHREAD_CONFIG_DUA_ENABLE 1
+#define OPENTHREAD_CONFIG_MLR_ENABLE 1
+
+#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 0
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 0
+
+#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 30
+
+#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 0
+#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 0
+#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 0
+
+// #define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG
+
+// Use the NXP-supplied default platform configuration for remainder
+// of OpenThread config options.
+//
+// NB: This file gets included during the build of OpenThread. Hence
+// it cannot use "openthread" in the path to the included file.
+//
+#include "openthread-core-k32w1-config.h"
diff --git a/examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn b/examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn
new file mode 100644
index 00000000000000..dafa6de4d3d31d
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/support/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/k32w1_sdk.gni")
+
+config("support_config") {
+ include_dirs = [ "../../../../.." ]
+
+ # Link options that provides replace dynamic memory operations in standard
+ # library with the FreeRTOS malloc in platform code.
+ ldflags = [
+ # memory allocation -- these must be re-entrant and do locking
+ "-Wl,--wrap=malloc",
+ "-Wl,--wrap=free",
+ "-Wl,--wrap=realloc",
+ "-Wl,--wrap=calloc",
+ "-Wl,--wrap=MemoryAlloc",
+
+ # Wrap these in case internal newlib call them (e.g. strdup will)
+ # directly call _malloc_r)
+ "-Wl,--wrap=_malloc_r",
+ "-Wl,--wrap=_realloc_r",
+ "-Wl,--wrap=_free_r",
+ "-Wl,--wrap=_calloc_r",
+ "-Wl,--gc-sections,--defsym=gUseNVMLink_d=1",
+ ]
+}
+
+source_set("freertos_mbedtls_utils") {
+ sources = [
+ "FreeRtosHooks.c",
+ "FreeRtosHooks.h",
+ "Memconfig.cpp",
+ ]
+
+ deps = [ "${chip_root}/src/lib/support" ]
+
+ cflags = [ "-Wconversion" ]
+
+ public_configs = [ ":support_config" ]
+}
diff --git a/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c
new file mode 100644
index 00000000000000..83549b1dc1f04a
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.c
@@ -0,0 +1,152 @@
+/*
+ *
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "FreeRtosHooks.h"
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+#include
+
+#include
+#include
+
+#include "NVM_Interface.h"
+#include "PWR_Interface.h"
+#include "board.h"
+#include "fsl_os_abstraction.h"
+
+/* Bluetooth Low Energy */
+#include "ble_config.h"
+#include "l2ca_cb_interface.h"
+
+#if defined gLoggingActive_d && (gLoggingActive_d > 0)
+#include "dbg_logging.h"
+#ifndef DBG_APP
+#define DBG_APP 0
+#endif
+#define APP_DBG_LOG(fmt, ...) \
+ if (DBG_APP) \
+ do \
+ { \
+ DbgLogAdd(__FUNCTION__, fmt, VA_NUM_ARGS(__VA_ARGS__), ##__VA_ARGS__); \
+ } while (0);
+#else
+#define APP_DBG_LOG(...)
+#endif
+
+#if (configUSE_TICKLESS_IDLE != 0)
+extern uint64_t PWR_TryEnterLowPower(uint64_t timeoutUs);
+#endif
+
+static inline void mutex_init(mbedtls_threading_mutex_t * p_mutex)
+{
+ assert(p_mutex != NULL);
+ *p_mutex = xSemaphoreCreateMutex();
+ assert(*p_mutex != NULL);
+}
+
+static inline void mutex_free(mbedtls_threading_mutex_t * p_mutex)
+{
+ assert(p_mutex != NULL);
+ assert(*p_mutex != NULL);
+ vSemaphoreDelete(*p_mutex);
+}
+
+static inline int mutex_lock(mbedtls_threading_mutex_t * p_mutex)
+{
+ assert(p_mutex != NULL);
+ assert(*p_mutex != NULL);
+ return xSemaphoreTake(*p_mutex, portMAX_DELAY) != pdTRUE;
+}
+
+static inline int mutex_unlock(mbedtls_threading_mutex_t * p_mutex)
+{
+ assert(p_mutex != NULL);
+ assert(*p_mutex != NULL);
+ return xSemaphoreGive(*p_mutex) != pdTRUE;
+}
+
+void freertos_mbedtls_mutex_init(void)
+{
+ mbedtls_threading_set_alt(mutex_init, mutex_free, mutex_lock, mutex_unlock);
+}
+
+void freertos_mbedtls_mutex_free(void)
+{
+ mbedtls_threading_free_alt();
+}
+
+#if (configUSE_TICKLESS_IDLE != 0)
+
+/*! *********************************************************************************
+ *\private
+ *\fn void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+ *\brief This function will try to put the MCU into a deep sleep mode for at
+ * most the maximum OS idle time specified. Else the MCU will enter a
+ * sleep mode until the first IRQ.
+ *
+ *\param [in] xExpectedIdleTime The idle time in OS ticks.
+ *
+ *\retval none.
+ *
+ *\remarks This feature is available only for FreeRTOS.
+ ********************************************************************************** */
+void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime)
+{
+ bool abortIdle = false;
+ uint64_t actualIdleTimeUs, expectedIdleTimeUs;
+
+ /* The OSA_InterruptDisable() API will prevent us to wakeup so we use
+ * OSA_DisableIRQGlobal() */
+ OSA_DisableIRQGlobal();
+
+ /* Disable and prepare systicks for low power */
+ abortIdle = PWR_SysticksPreProcess((uint32_t) xExpectedIdleTime, &expectedIdleTimeUs);
+
+ if (abortIdle == false)
+ {
+ /* Enter low power with a maximal timeout */
+ actualIdleTimeUs = PWR_TryEnterLowPower(expectedIdleTimeUs);
+
+ /* Re enable systicks and compensate systick timebase */
+ PWR_SysticksPostProcess(expectedIdleTimeUs, actualIdleTimeUs);
+ }
+
+ /* Exit from critical section */
+ OSA_EnableIRQGlobal();
+}
+#endif
+
+extern void OTAIdleActivities(void);
+
+void vApplicationIdleHook(void)
+{
+ // Data queued by PDM will be written to external flash
+ // when PDM_vIdleTask is called. Interrupts are disabled
+ // to ensure there is no context switch during the actual
+ // writing, thus avoiding race conditions.
+ OSA_InterruptDisable();
+#if CHIP_PLAT_NVM_SUPPORT
+ NvIdle();
+#endif
+ OSA_InterruptEnable();
+
+ OTAIdleActivities();
+}
diff --git a/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.h b/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.h
new file mode 100644
index 00000000000000..a27f72d498f81d
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/support/FreeRtosHooks.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+typedef void * mbedtls_threading_mutex_t;
+
+extern void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),
+ void (*mutex_free)(mbedtls_threading_mutex_t *),
+ int (*mutex_lock)(mbedtls_threading_mutex_t *),
+ int (*mutex_unlock)(mbedtls_threading_mutex_t *));
+
+extern void mbedtls_threading_free_alt(void);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Function for initializing alternative MbedTLS mutexes to enable the usage of the FreeRTOS implementation. */
+void freertos_mbedtls_mutex_init(void);
+
+/**@brief Function for releasing MbedTLS alternative mutexes. */
+void freertos_mbedtls_mutex_free(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/nxp/k32w/k32w1/app/support/Memconfig.cpp b/examples/platform/nxp/k32w/k32w1/app/support/Memconfig.cpp
new file mode 100644
index 00000000000000..e5acf5ea3ceecb
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/app/support/Memconfig.cpp
@@ -0,0 +1,184 @@
+/*
+ *
+ * Copyright (c) 2020-2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file contains platform specific implementations for stdlib malloc/calloc/realloc/free
+ * functions, so that CHIPPlatformMemory* works as intended with the platform's heap.
+ */
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include
+#include
+#include
+
+#ifndef NDEBUG
+#include
+#include
+#endif
+
+#include
+
+#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+#include
+#include
+#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+
+/* Assumes 8bit bytes! */
+#define heapBITS_PER_BYTE ((size_t) 8)
+
+/* Define the linked list structure. This is used to link free blocks in order
+of their memory address. */
+typedef struct A_BLOCK_LINK
+{
+ struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
+ size_t xBlockSize; /*<< The size of the free block. */
+} BlockLink_t;
+
+/* The size of the structure placed at the beginning of each allocated memory
+block must by correctly byte aligned. */
+static const size_t xHeapStructSize =
+ (sizeof(BlockLink_t) + ((size_t) (portBYTE_ALIGNMENT - 1))) & ~((size_t) portBYTE_ALIGNMENT_MASK);
+
+/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
+member of an BlockLink_t structure is set then the block belongs to the
+application. When the bit is free the block is still part of the free heap
+space. */
+static size_t xBlockAllocatedBit = ((size_t) 1) << ((sizeof(size_t) * heapBITS_PER_BYTE) - 1);
+
+extern "C" {
+
+/* xPortMallocUsableSize relies on heap4 implementation.
+It returns the size of an allocated block and it is
+called by __wrap_realloc.
+Thus it is validated in __wrap_realloc function that the allocated size
+of the old_ptr is smaller than the allocated size of new_ptr */
+size_t xPortMallocUsableSize(void * pv)
+{
+ uint8_t * puc = (uint8_t *) pv;
+ BlockLink_t * pxLink;
+ void * voidp;
+ size_t sz = 0;
+
+ if (pv != NULL)
+ {
+ vTaskSuspendAll();
+ {
+ /* The memory being checked will have an BlockLink_t structure immediately
+ before it. */
+ puc -= xHeapStructSize;
+
+ /* This casting is to keep the compiler from issuing warnings. */
+ voidp = (void *) puc;
+ pxLink = (BlockLink_t *) voidp;
+
+ /* Check if the block is actually allocated. */
+ configASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0);
+ configASSERT(pxLink->pxNextFreeBlock == NULL);
+
+ sz = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize;
+ }
+ (void) xTaskResumeAll();
+ }
+
+ return sz;
+}
+
+void * __wrap_malloc(size_t size)
+{
+ return pvPortMalloc(size);
+}
+
+void __wrap_free(void * ptr)
+{
+ vPortFree(ptr);
+}
+
+void * __wrap_calloc(size_t num, size_t size)
+{
+ size_t total_size = num * size;
+
+ // Handle overflow from (num * size)
+ if ((size != 0) && ((total_size / size) != num))
+ {
+ return nullptr;
+ }
+
+ void * ptr = pvPortMalloc(total_size);
+ if (ptr)
+ {
+ memset(ptr, 0, total_size);
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "__wrap_calloc: Could not allocate memory!");
+ }
+
+ return ptr;
+}
+
+void * __wrap_realloc(void * ptr, size_t new_size)
+{
+
+ void * new_ptr = NULL;
+
+ if (new_size)
+ {
+ size_t old_ptr_size = xPortMallocUsableSize(ptr);
+ if (new_size <= old_ptr_size)
+ {
+ /* Return old pointer if the newly allocated size is smaller
+ or equal to the allocated size for old_ptr */
+ return ptr;
+ }
+
+ /* if old_ptr is NULL, then old_ptr_size is zero and new_ptr will be returned */
+ new_ptr = pvPortMalloc(new_size);
+
+ if (!new_ptr)
+ {
+ ChipLogError(DeviceLayer, "__wrap_realloc: Could not allocate memory!");
+ return NULL;
+ }
+
+ memset(reinterpret_cast(new_ptr) + old_ptr_size, 0, (new_size - old_ptr_size));
+ memcpy(new_ptr, ptr, old_ptr_size);
+ }
+
+ vPortFree(ptr);
+
+ return new_ptr;
+}
+
+void * __wrap__malloc_r(void * REENT, size_t size)
+{
+ return __wrap_malloc(size);
+}
+
+void __wrap__free_r(void * REENT, void * ptr)
+{
+ __wrap_free(ptr);
+}
+
+void * __wrap__realloc_r(void * REENT, void * ptr, size_t new_size)
+{
+ return __wrap_realloc(ptr, new_size);
+}
+
+} // extern "C"
diff --git a/examples/platform/nxp/k32w/k32w1/args.gni b/examples/platform/nxp/k32w/k32w1/args.gni
new file mode 100644
index 00000000000000..f7d9dccd82e1fd
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/args.gni
@@ -0,0 +1,38 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+
+import("${chip_root}/src/platform/nxp/k32w/k32w1/args.gni")
+
+arm_float_abi = "hard"
+arm_cpu = "cortex-m33"
+arm_fpu = "fpv5-sp-d16"
+arm_arch = "armv8-m.main+dsp+fp"
+
+chip_openthread_ftd = false
+openthread_core_config_deps = []
+openthread_core_config_deps = [ "${chip_root}/examples/platform/nxp/k32w/k32w1:openthread_core_config_k32w1_chip_examples" ]
+
+chip_ble_project_config_include = ""
+chip_device_project_config_include = ""
+chip_project_config_include = ""
+chip_inet_project_config_include = ""
+chip_system_project_config_include = ""
+
+chip_system_config_provide_statistics = false
+chip_with_nlfaultinjection = true
+
+chip_system_config_use_open_thread_inet_endpoints = true
+chip_with_lwip = false
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg
new file mode 100644
index 00000000000000..407c781220c4a6
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/debug_k32w1.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/import_demo.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/import_demo.jpg
new file mode 100644
index 00000000000000..6016c448a48e49
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/import_demo.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg
new file mode 100644
index 00000000000000..be3ad84380a8aa
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/installed_sdks.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg
new file mode 100644
index 00000000000000..550f2743367865
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/k32w1-evk.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg
new file mode 100644
index 00000000000000..9dd4190b6d99e0
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/mcux-sdk-download.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/new_project.jpg b/examples/platform/nxp/k32w/k32w1/doc/images/new_project.jpg
new file mode 100644
index 00000000000000..ce34586229bd67
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/new_project.jpg differ
diff --git a/examples/platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG b/examples/platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG
new file mode 100644
index 00000000000000..75fc40a70e3b27
Binary files /dev/null and b/examples/platform/nxp/k32w/k32w1/doc/images/ota_topology.JPG differ
diff --git a/examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp b/examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp
new file mode 100644
index 00000000000000..b7a01ae6c7545f
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/util/LEDWidget.cpp
@@ -0,0 +1,93 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LEDWidget.h"
+
+#include
+
+#include "app.h"
+
+#if (defined(gAppLedCnt_c) && (gAppLedCnt_c > 0))
+
+void LEDWidget::Init(uint8_t led, bool inverted)
+{
+ mLastChangeTimeMS = 0;
+ mBlinkOnTimeMS = 0;
+ mBlinkOffTimeMS = 0;
+ mGPIONum = led;
+ mState = false;
+ mOnLogic = !inverted;
+
+ Set(false);
+}
+
+void LEDWidget::Invert(void)
+{
+ Set(!mState);
+}
+
+void LEDWidget::Set(bool state)
+{
+ mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
+ DoSet(state);
+}
+
+void LEDWidget::Blink(uint32_t changeRateMS)
+{
+ Blink(changeRateMS, changeRateMS);
+}
+
+void LEDWidget::Blink(uint32_t onTimeMS, uint32_t offTimeMS)
+{
+ mBlinkOnTimeMS = onTimeMS;
+ mBlinkOffTimeMS = offTimeMS;
+ Animate();
+}
+
+void LEDWidget::Animate()
+{
+ if (mBlinkOnTimeMS != 0 && mBlinkOffTimeMS != 0)
+ {
+ uint64_t nowMS = chip::System::SystemClock().GetMonotonicMilliseconds64().count();
+ uint64_t stateDurMS = mState ? mBlinkOnTimeMS : mBlinkOffTimeMS;
+ uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS;
+
+ if (nextChangeTimeMS < nowMS)
+ {
+ DoSet(!mState);
+ mLastChangeTimeMS = nowMS;
+ }
+ }
+}
+
+void LEDWidget::DoSet(bool state)
+{
+ mState = state;
+
+ if (state)
+ {
+ (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mGPIONum], mOnLogic);
+ }
+ else
+ {
+ (void) LED_TurnOnOff((led_handle_t) g_ledHandle[mGPIONum], !mOnLogic);
+ }
+}
+
+#endif /* (defined(gAppLedCnt_c) && (gAppLedCnt_c > 0)) */
diff --git a/examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h b/examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h
new file mode 100644
index 00000000000000..4d55f246d49e05
--- /dev/null
+++ b/examples/platform/nxp/k32w/k32w1/util/include/LEDWidget.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #include "LED.h"
+#include "EmbeddedTypes.h"
+#pragma once
+
+class LEDWidget
+{
+public:
+ void Init(uint8_t gpioNum, bool inverted);
+ void Set(bool state);
+ void Invert(void);
+ void Blink(uint32_t changeRateMS);
+ void Blink(uint32_t onTimeMS, uint32_t offTimeMS);
+ void Animate();
+
+private:
+ uint64_t mLastChangeTimeMS;
+ uint32_t mBlinkOnTimeMS;
+ uint32_t mBlinkOffTimeMS;
+ uint8_t mGPIONum;
+ bool mState;
+ bool mOnLogic;
+
+ void DoSet(bool state);
+};
diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py
index 6d039d53b5676c..03089edd1d5571 100755
--- a/scripts/build/build/targets.py
+++ b/scripts/build/build/targets.py
@@ -24,7 +24,7 @@
from builders.host import HostApp, HostBoard, HostBuilder, HostCryptoLibrary, HostFuzzingType
from builders.imx import IMXApp, IMXBuilder
from builders.infineon import InfineonApp, InfineonBoard, InfineonBuilder
-from builders.k32w import K32WApp, K32WBuilder
+from builders.k32w import K32WApp, K32WBoard, K32WBuilder
from builders.mbed import MbedApp, MbedBoard, MbedBuilder, MbedProfile
from builders.mw320 import MW320App, MW320Builder
from builders.nrf import NrfApp, NrfBoard, NrfConnectBuilder
@@ -454,12 +454,18 @@ def BuildASRTarget():
def BuildK32WTarget():
target = BuildTarget('k32w', K32WBuilder)
+ # boards
+ target.AppendFixedTargets([
+ TargetPart('k32w0', board=K32WBoard.K32W0),
+ TargetPart('k32w1', board=K32WBoard.K32W1)
+ ])
+
# apps
target.AppendFixedTargets([
TargetPart('light', app=K32WApp.LIGHT, release=True),
TargetPart('shell', app=K32WApp.SHELL, release=True),
TargetPart('lock', app=K32WApp.LOCK, release=True),
- TargetPart('contact', app=K32WApp.CONTACT, release=True),
+ TargetPart('contact', app=K32WApp.CONTACT, release=True)
])
target.AppendModifier(name="se05x", se05x=True)
@@ -470,6 +476,7 @@ def BuildK32WTarget():
target.AppendModifier(name="crypto-platform", crypto_platform=True)
target.AppendModifier(
name="tokenizer", tokenizer=True).ExceptIfRe("-nologs")
+ target.AppendModifier(name="openthread-ftd", openthread_ftd=True)
return target
diff --git a/scripts/build/builders/k32w.py b/scripts/build/builders/k32w.py
index be17730c481148..1cf7862d3d8739 100644
--- a/scripts/build/builders/k32w.py
+++ b/scripts/build/builders/k32w.py
@@ -18,6 +18,27 @@
from .gn import GnBuilder
+class K32WBoard(Enum):
+ K32W0 = auto()
+ K32W1 = auto()
+
+ def Name(self):
+ if self == K32WBoard.K32W0:
+ return 'k32w0x'
+ elif self == K32WBoard.K32W1:
+ return 'k32w1'
+ else:
+ raise Exception('Unknown board type: %r' % self)
+
+ def FolderName(self):
+ if self == K32WBoard.K32W0:
+ return 'k32w/k32w0'
+ elif self == K32WBoard.K32W1:
+ return 'k32w/k32w1'
+ else:
+ raise Exception('Unknown board type: %r' % self)
+
+
class K32WApp(Enum):
LIGHT = auto()
LOCK = auto()
@@ -36,20 +57,20 @@ def ExampleName(self):
else:
raise Exception('Unknown app type: %r' % self)
- def AppNamePrefix(self):
+ def NameSuffix(self):
if self == K32WApp.LIGHT:
- return 'chip-k32w0x-light-example'
+ return 'light-example'
elif self == K32WApp.LOCK:
- return 'chip-k32w0x-lock-example'
+ return 'lock-example'
elif self == K32WApp.SHELL:
- return 'chip-k32w0x-shell-example'
+ return 'shell-example'
elif self == K32WApp.CONTACT:
- return 'chip-k32w0x-contact-example'
+ return 'contact-example'
else:
raise Exception('Unknown app type: %r' % self)
- def BuildRoot(self, root):
- return os.path.join(root, 'examples', self.ExampleName(), 'nxp', 'k32w', 'k32w0')
+ def BuildRoot(self, root, board):
+ return os.path.join(root, 'examples', self.ExampleName(), 'nxp', board.FolderName())
class K32WBuilder(GnBuilder):
@@ -58,6 +79,7 @@ def __init__(self,
root,
runner,
app: K32WApp = K32WApp.LIGHT,
+ board: K32WBoard = K32WBoard.K32W0,
release: bool = False,
low_power: bool = False,
tokenizer: bool = False,
@@ -66,12 +88,14 @@ def __init__(self,
disable_logs: bool = False,
se05x: bool = False,
tinycrypt: bool = False,
- crypto_platform: bool = False):
+ crypto_platform: bool = False,
+ openthread_ftd: bool = False):
super(K32WBuilder, self).__init__(
- root=app.BuildRoot(root),
+ root=app.BuildRoot(root, board),
runner=runner)
self.code_root = root
self.app = app
+ self.board = board
self.low_power = low_power
self.tokenizer = tokenizer
self.release = release
@@ -81,11 +105,10 @@ def __init__(self,
self.se05x = se05x
self.tinycrypt = tinycrypt
self.crypto_platform = crypto_platform
+ self.openthread_ftd = openthread_ftd
def GnBuildArgs(self):
- args = [
- 'k32w0_sdk_root="%s"' % os.environ['NXP_K32W0_SDK_ROOT'],
- ]
+ args = []
if self.low_power:
args.append('chip_with_low_power=1')
@@ -116,18 +139,17 @@ def GnBuildArgs(self):
if self.crypto_platform:
args.append('chip_crypto=\"platform\"')
+ if self.openthread_ftd:
+ args.append('chip_openthread_ftd=true')
+
return args
def generate(self):
- self._Execute([os.path.join(
- self.code_root, 'third_party/nxp/k32w0_sdk/sdk_fixes/patch_k32w_sdk.sh')])
-
super(K32WBuilder, self).generate()
def build_outputs(self):
- items = {}
- for extension in ["", ".map", ".hex"]:
- name = '%s%s' % (self.app.AppNamePrefix(), extension)
- items[name] = os.path.join(self.output_dir, name)
-
- return items
+ name = 'chip-%s-%s' % (self.board.Name(), self.app.NameSuffix())
+ return {
+ '%s.elf' % name: os.path.join(self.output_dir, name),
+ '%s.map' % name: os.path.join(self.output_dir, '%s.map' % name)
+ }
diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt
index e7500ab0ca3b76..c78c87b83fda35 100644
--- a/scripts/build/testdata/all_targets_linux_x64.txt
+++ b/scripts/build/testdata/all_targets_linux_x64.txt
@@ -14,7 +14,7 @@ linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,therm
linux-x64-efr32-test-runner[-clang]
imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release]
infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage]
-k32w-{light,shell,lock,contact}[-se05x][-no-ble][-no-ota][-low-power][-nologs][-crypto-platform][-tokenizer]
+k32w-{k32w0,k32w1}-{light,shell,lock,contact}[-se05x][-no-ble][-no-ota][-low-power][-nologs][-crypto-platform][-tokenizer][-openthread-ftd]
mbed-cy8cproto_062_4343w-{lock,light,all-clusters,all-clusters-minimal,pigweed,ota-requestor,shell}[-release][-develop][-debug]
mw320-all-clusters-app
nrf-{nrf5340dk,nrf52840dk,nrf52840dongle}-{all-clusters,all-clusters-minimal,lock,light,light-switch,shell,pump,pump-controller,window-covering}[-rpc]
diff --git a/scripts/checkout_submodules.py b/scripts/checkout_submodules.py
index 22750fd40a8bff..e1c8eb888fcc99 100755
--- a/scripts/checkout_submodules.py
+++ b/scripts/checkout_submodules.py
@@ -36,7 +36,7 @@
'efr32',
'esp32',
'infineon',
- 'k32w0',
+ 'k32w',
'linux',
'mbed',
'nrfconnect',
diff --git a/src/lwip/BUILD.gn b/src/lwip/BUILD.gn
index 3547ac1157568d..241a059abb7428 100644
--- a/src/lwip/BUILD.gn
+++ b/src/lwip/BUILD.gn
@@ -31,11 +31,12 @@ if (lwip_platform == "") {
assert(lwip_platform == "external" || lwip_platform == "standalone" ||
lwip_platform == "cc13xx_26xx" || lwip_platform == "cc32xx" ||
lwip_platform == "silabs" || lwip_platform == "k32w0" ||
- lwip_platform == "qpg" || lwip_platform == "mbed" ||
- lwip_platform == "psoc6" || lwip_platform == "cyw30739" ||
- lwip_platform == "bl602" || lwip_platform == "mw320" ||
- lwip_platform == "bl702" || lwip_platform == "bl702l" ||
- lwip_platform == "mt793x" || lwip_platform == "asr",
+ lwip_platform == "k32w1" || lwip_platform == "qpg" ||
+ lwip_platform == "mbed" || lwip_platform == "psoc6" ||
+ lwip_platform == "cyw30739" || lwip_platform == "bl602" ||
+ lwip_platform == "mw320" || lwip_platform == "bl702" ||
+ lwip_platform == "bl702l" || lwip_platform == "mt793x" ||
+ lwip_platform == "asr",
"Unsupported lwIP platform: ${lwip_platform}")
if (lwip_platform != "external") {
@@ -56,6 +57,8 @@ if (lwip_platform == "cc13xx_26xx") {
import("${qpg_sdk_build_root}/qpg_sdk.gni")
} else if (lwip_platform == "k32w0") {
import("//build_overrides/k32w0_sdk.gni")
+} else if (lwip_platform == "k32w1") {
+ import("//build_overrides/k32w1_sdk.gni")
} else if (lwip_platform == "psoc6") {
import("//build_overrides/psoc6.gni")
} else if (lwip_platform == "cyw30739") {
@@ -207,6 +210,8 @@ if (current_os == "zephyr" || current_os == "mbed") {
public_deps += [ "${chip_root}/src/lib/support" ]
} else if (lwip_platform == "k32w0") {
public_deps += [ "${k32w0_sdk_build_root}:k32w0_sdk" ]
+ } else if (lwip_platform == "k32w1") {
+ public_deps += [ "${k32w1_sdk_build_root}:k32w1_sdk" ]
} else if (lwip_platform == "cyw30739") {
public_deps += [ "${cyw30739_sdk_build_root}:cyw30739_sdk" ]
} else if (lwip_platform == "bl702") {
diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn
index 292ab1cbd7ae77..c588b94fa1621b 100644
--- a/src/platform/BUILD.gn
+++ b/src/platform/BUILD.gn
@@ -205,6 +205,9 @@ if (chip_device_platform != "none" && chip_device_platform != "external") {
} else if (chip_device_platform == "k32w0") {
device_layer_target_define = "K32W"
defines += [ "CHIP_DEVICE_LAYER_TARGET=nxp/k32w/k32w0" ]
+ } else if (chip_device_platform == "k32w1") {
+ device_layer_target_define = "K32W"
+ defines += [ "CHIP_DEVICE_LAYER_TARGET=nxp/k32w/k32w1" ]
} else if (chip_device_platform == "telink") {
device_layer_target_define = "TELINK"
defines += [ "CHIP_DEVICE_LAYER_TARGET=telink" ]
@@ -494,6 +497,8 @@ if (chip_device_platform != "none") {
_platform_target = "ESP32"
} else if (chip_device_platform == "k32w0") {
_platform_target = "nxp/k32w/k32w0"
+ } else if (chip_device_platform == "k32w1") {
+ _platform_target = "nxp/k32w/k32w1"
} else if (chip_device_platform == "linux") {
_platform_target = "Linux"
} else if (chip_device_platform == "nrfconnect") {
diff --git a/src/platform/device.gni b/src/platform/device.gni
index 8bfaee12b86a01..b139f44fba879b 100644
--- a/src/platform/device.gni
+++ b/src/platform/device.gni
@@ -16,7 +16,7 @@ import("//build_overrides/chip.gni")
import("${chip_root}/src/ble/ble.gni")
declare_args() {
- # Device platform layer: cc13x2_26x2, cc13x4_26x4, cc32xx, darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w0, qpg, tizen, cyw30739, bl602, mw320, zephyr, beken, openiotsdk, none.
+ # Device platform layer: cc13x2_26x2, cc13x4_26x4, cc32xx, darwin, efr32, esp32, external, freertos, linux, nrfconnect, k32w0, k32w1, qpg, tizen, cyw30739, bl602, mw320, zephyr, beken, openiotsdk, none.
chip_device_platform = "auto"
chip_platform_target = ""
@@ -51,8 +51,9 @@ declare_args() {
chip_device_platform == "linux" || chip_device_platform == "qpg" ||
chip_device_platform == "cc13x2_26x2" ||
chip_device_platform == "cc13x4_26x4" ||
- chip_device_platform == "k32w0" || chip_device_platform == "tizen" ||
- chip_device_platform == "webos" || chip_device_platform == "stm32"
+ chip_device_platform == "k32w0" || chip_device_platform == "k32w1" ||
+ chip_device_platform == "tizen" || chip_device_platform == "stm32" ||
+ chip_device_platform == "webos"
}
declare_args() {
@@ -140,6 +141,8 @@ if (chip_device_platform == "cc13x2_26x2") {
_chip_device_layer = "qpg"
} else if (chip_device_platform == "k32w0") {
_chip_device_layer = "nxp/k32w/k32w0"
+} else if (chip_device_platform == "k32w1") {
+ _chip_device_layer = "nxp/k32w/k32w1"
} else if (chip_device_platform == "telink") {
_chip_device_layer = "telink"
} else if (chip_device_platform == "mbed") {
@@ -234,15 +237,15 @@ assert(
chip_device_platform == "external" || chip_device_platform == "linux" ||
chip_device_platform == "tizen" ||
chip_device_platform == "nrfconnect" ||
- chip_device_platform == "k32w0" || chip_device_platform == "qpg" ||
- chip_device_platform == "telink" || chip_device_platform == "mbed" ||
- chip_device_platform == "psoc6" || chip_device_platform == "android" ||
- chip_device_platform == "ameba" || chip_device_platform == "cyw30739" ||
- chip_device_platform == "webos" || chip_device_platform == "mw320" ||
- chip_device_platform == "zephyr" || chip_device_platform == "beken" ||
- chip_device_platform == "bl602" || chip_device_platform == "bl702" ||
- chip_device_platform == "bl702l" || chip_device_platform == "mt793x" ||
- chip_device_platform == "SiWx917" ||
+ chip_device_platform == "k32w0" || chip_device_platform == "k32w1" ||
+ chip_device_platform == "qpg" || chip_device_platform == "telink" ||
+ chip_device_platform == "mbed" || chip_device_platform == "psoc6" ||
+ chip_device_platform == "android" || chip_device_platform == "ameba" ||
+ chip_device_platform == "cyw30739" || chip_device_platform == "webos" ||
+ chip_device_platform == "mw320" || chip_device_platform == "zephyr" ||
+ chip_device_platform == "beken" || chip_device_platform == "bl602" ||
+ chip_device_platform == "bl702" || chip_device_platform == "bl702l" ||
+ chip_device_platform == "mt793x" || chip_device_platform == "SiWx917" ||
chip_device_platform == "openiotsdk" || chip_device_platform == "asr" ||
chip_device_platform == "stm32",
"Please select a valid value for chip_device_platform")
diff --git a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
index 2e3c5a35974c96..65b2f68cb20e90 100644
--- a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
+++ b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
@@ -184,6 +184,18 @@ CHIP_ERROR BLEManagerCommon::_Init()
eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_INIT_COMPLETE, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_INIT_COMPLETE, err = CHIP_ERROR_INCORRECT_STATE);
+#if BLE_HIGH_TX_POWER
+ /* Set Adv Power */
+ Gap_SetTxPowerLevel(gAdvertisingPowerLeveldBm_c, gTxPowerAdvChannel_c);
+ eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+ VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, err = CHIP_ERROR_INCORRECT_STATE);
+
+ /* Set Connect Power */
+ Gap_SetTxPowerLevel(gConnectPowerLeveldBm_c, gTxPowerConnChannel_c);
+ eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+ VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, err = CHIP_ERROR_INCORRECT_STATE);
+#endif
+
#if defined(CPU_JN518X) && defined(chip_with_low_power) && (chip_with_low_power == 1)
PWR_ChangeDeepSleepMode(cPWR_PowerDown_RamRet);
#endif
diff --git a/src/platform/nxp/k32w/common/K32W_OTA_README.md b/src/platform/nxp/k32w/common/K32W_OTA_README.md
index 4f2ba7b6e52960..63079e0ce3c81e 100644
--- a/src/platform/nxp/k32w/common/K32W_OTA_README.md
+++ b/src/platform/nxp/k32w/common/K32W_OTA_README.md
@@ -128,6 +128,13 @@ at next boot. The `FactoryDataProvider` offers a default restore mechanism and
support for registering additional restore mechanisms or overwriting the default
one.
+Prior to factory data update, the old factory data is backed up in external
+flash. If anything interrupts the update (e.g. power loss), there is a slight
+chance the internal flash factory data section is erased and has to be restored
+at next boot. The `FactoryDataProvider` offers a default restore mechanism and
+support for registering additional restore mechanisms or overwriting the default
+one.
+
Restore mechanisms are just functions that have this signature:
`CHIP_ERROR (*)(void)`. Any such function can be registered through
`FactoryDataProvider::RegisterRestoreMechanism`.
@@ -138,12 +145,6 @@ The default restore mechanism is implemented as a weak function:
overwritten at application level. When doing the actual restore, the mechanisms
are called in the order they were registered.
-The default restore mechanism is implemented as a weak function:
-`FactoryDataDefaultRestoreMechanism`. It is registered in
-`K32W0FactoryDataProvider::Init`, before factory data validation, and it can be
-overwritten at application level. When doing the actual restore, the mechanisms
-are called in the order they were registered.
-
Please note that the restore mechanisms registration order matters. Once a
restore mechanism is successful (`CHIP_NO_ERROR` is returned), the restore
process has finished and subsequent restore mechanisms will not be called.
diff --git a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
index f8d8b4b5a0f8e6..16493144c632be 100644
--- a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
+++ b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
@@ -28,6 +28,13 @@
using namespace chip::DeviceLayer;
using namespace ::chip::DeviceLayer::Internal;
+#if USE_SMU2_AS_SYSTEM_MEMORY
+// The attribute specifier should not be changed.
+static chip::OTAImageProcessorImpl gImageProcessor __attribute__((section(".smu2")));
+#else
+static chip::OTAImageProcessorImpl gImageProcessor;
+#endif
+
namespace chip {
CHIP_ERROR OTAImageProcessorImpl::Init(OTADownloader * downloader)
@@ -96,16 +103,10 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
{
auto * imageProcessor = reinterpret_cast(context);
- if (imageProcessor == nullptr)
- {
- ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
- return;
- }
- else if (imageProcessor->mDownloader == nullptr)
- {
- ChipLogError(SoftwareUpdate, "mDownloader is null");
- return;
- }
+
+ VerifyOrReturn(imageProcessor != nullptr, ChipLogError(SoftwareUpdate, "ImageProcessor context is null"));
+
+ VerifyOrReturn(imageProcessor->mDownloader != nullptr, ChipLogError(SoftwareUpdate, "mDownloader is null"));
GetRequestorInstance()->GetProviderLocation(imageProcessor->mBackupProviderLocation);
@@ -168,11 +169,11 @@ CHIP_ERROR OTAImageProcessorImpl::SelectProcessor(ByteSpan & block)
auto pair = mProcessorMap.find(header.tag);
if (pair == mProcessorMap.end())
{
- ChipLogError(SoftwareUpdate, "There is no registered processor for tag: %" PRIu32, header.tag);
+ ChipLogError(SoftwareUpdate, "There is no registered processor for tag: %lu", header.tag);
return CHIP_OTA_PROCESSOR_NOT_REGISTERED;
}
- ChipLogDetail(SoftwareUpdate, "Selected processor with tag: %ld", pair->first);
+ ChipLogDetail(SoftwareUpdate, "Selected processor with tag: %lu", pair->first);
mCurrentProcessor = pair->second;
mCurrentProcessor->SetLength(header.length);
mCurrentProcessor->SetWasSelected(true);
@@ -185,7 +186,7 @@ CHIP_ERROR OTAImageProcessorImpl::RegisterProcessor(uint32_t tag, OTATlvProcesso
auto pair = mProcessorMap.find(tag);
if (pair != mProcessorMap.end())
{
- ChipLogError(SoftwareUpdate, "A processor for tag %" PRIu32 " is already registered.", tag);
+ ChipLogError(SoftwareUpdate, "A processor for tag %lu is already registered.", tag);
return CHIP_OTA_PROCESSOR_ALREADY_REGISTERED;
}
@@ -210,17 +211,10 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
{
auto * imageProcessor = reinterpret_cast(context);
- if (imageProcessor == nullptr)
- {
- ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
- return;
- }
- if (imageProcessor->mDownloader == nullptr)
- {
- ChipLogError(SoftwareUpdate, "mDownloader is null");
- return;
- }
+ VerifyOrReturn(imageProcessor != nullptr, ChipLogError(SoftwareUpdate, "ImageProcessor context is null"));
+
+ VerifyOrReturn(imageProcessor->mDownloader != nullptr, ChipLogError(SoftwareUpdate, "mDownloader is null"));
CHIP_ERROR status;
auto block = ByteSpan(imageProcessor->mBlock.data(), imageProcessor->mBlock.size());
@@ -243,7 +237,7 @@ void OTAImageProcessorImpl::HandleStatus(CHIP_ERROR status)
if (status == CHIP_NO_ERROR || status == CHIP_ERROR_BUFFER_TOO_SMALL)
{
mParams.downloadedBytes += mBlock.size();
- FetchNextData(reinterpret_cast(this));
+ FetchNextData(0);
}
else if (status == CHIP_OTA_FETCH_ALREADY_SCHEDULED)
{
@@ -294,8 +288,8 @@ CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion));
if (currentVersion != targetVersion)
{
- ChipLogError(SoftwareUpdate, "Current sw version %" PRIu32 " is different than the expected sw version = %" PRIu32,
- currentVersion, targetVersion);
+ ChipLogError(SoftwareUpdate, "Current sw version %lu is different than the expected sw version = %lu", currentVersion,
+ targetVersion);
return CHIP_ERROR_INCORRECT_STATE;
}
@@ -414,8 +408,7 @@ void OTAImageProcessorImpl::FetchNextData(uint32_t context)
OTAImageProcessorImpl & OTAImageProcessorImpl::GetDefaultInstance()
{
- static OTAImageProcessorImpl imageProcessor;
- return imageProcessor;
+ return gImageProcessor;
}
} // namespace chip
diff --git a/src/platform/nxp/k32w/common/OTATlvProcessor.h b/src/platform/nxp/k32w/common/OTATlvProcessor.h
index 534da067148da8..1968f983eda14b 100644
--- a/src/platform/nxp/k32w/common/OTATlvProcessor.h
+++ b/src/platform/nxp/k32w/common/OTATlvProcessor.h
@@ -39,7 +39,8 @@ namespace chip {
#define CHIP_OTA_PROCESSOR_IMG_COMMIT CHIP_ERROR_TLV_PROCESSOR(0x0A)
#define CHIP_OTA_PROCESSOR_CB_NOT_REGISTERED CHIP_ERROR_TLV_PROCESSOR(0x0B)
#define CHIP_OTA_PROCESSOR_EEPROM_OFFSET CHIP_ERROR_TLV_PROCESSOR(0x0C)
-#define CHIP_OTA_PROCESSOR_START_IMAGE CHIP_ERROR_TLV_PROCESSOR(0x0D)
+#define CHIP_OTA_PROCESSOR_EXTERNAL_STORAGE CHIP_ERROR_TLV_PROCESSOR(0x0D)
+#define CHIP_OTA_PROCESSOR_START_IMAGE CHIP_ERROR_TLV_PROCESSOR(0x0E)
// Descriptor constants
inline constexpr size_t kVersionStringSize = 64;
diff --git a/src/platform/nxp/k32w/k32w1/BLEManagerImpl.cpp b/src/platform/nxp/k32w/k32w1/BLEManagerImpl.cpp
new file mode 100644
index 00000000000000..daac54fb5a16e7
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/BLEManagerImpl.cpp
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright (c) 2021-2023 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* this file behaves like a config.h, comes first */
+#include
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+/*! App to Host message queue for the Host Task */
+messaging_t gApp2Host_TaskQueue;
+/*! HCI to Host message queue for the Host Task */
+messaging_t gHci2Host_TaskQueue;
+/*! Event for the Host Task Queue */
+OSA_EVENT_HANDLE_DEFINE(gHost_TaskEvent);
+
+#include
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+BLEManagerImpl BLEManagerImpl::sInstance;
+
+BLEManagerCommon * BLEManagerImpl::GetImplInstance()
+{
+ return &BLEManagerImpl::sInstance;
+}
+
+CHIP_ERROR BLEManagerImpl::InitHostController(ble_generic_cb_fp cb_fp)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ PLATFORM_InitBle();
+
+ (void) RNG_Init();
+ RNG_SetPseudoRandomNoSeed(NULL);
+
+ /* Has to be called after RNG_Init(), once seed is generated. */
+ (void) Controller_SetRandomSeed();
+
+ /* Create BLE Host Task */
+ VerifyOrExit(BLEManagerImpl::blekw_host_init() == CHIP_NO_ERROR, err = CHIP_ERROR_INCORRECT_STATE);
+
+ VerifyOrExit(Hcit_Init(Ble_HciRecv) == gHciSuccess_c, err = CHIP_ERROR_INCORRECT_STATE);
+
+ /* Set BD Address in Controller. Must be done after HCI init and before Host init. */
+ Ble_SetBDAddr();
+
+ /* BLE Host Stack Init */
+ VerifyOrExit(Ble_HostInitialize(cb_fp, Hcit_SendPacket) == gBleSuccess_c, err = CHIP_ERROR_INCORRECT_STATE);
+
+ /* configure tx power to use in NBU specific to BLE */
+ Controller_SetTxPowerLevelDbm(mAdvertisingDefaultTxPower_c, gAdvTxChannel_c);
+ Controller_SetTxPowerLevelDbm(mConnectionDefaultTxPower_c, gConnTxChannel_c);
+ Controller_ConfigureInvalidPduHandling(gLlInvalidPduHandlingType_c);
+
+exit:
+ return err;
+}
+
+void BLEManagerImpl::Host_Task(osaTaskParam_t argument)
+{
+ Host_TaskHandler((void *) NULL);
+}
+
+CHIP_ERROR BLEManagerImpl::blekw_host_init(void)
+{
+ /* Initialization of task related */
+ if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t) gHost_TaskEvent, TRUE))
+ {
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ /* Initialization of task message queue */
+ MSG_InitQueue(&gApp2Host_TaskQueue);
+ MSG_InitQueue(&gHci2Host_TaskQueue);
+
+ /* Task creation */
+ if (pdPASS != xTaskCreate(Host_Task, "hostTask", HOST_TASK_STACK_SIZE, (void *) 0, HOST_TASK_PRIORITY, NULL))
+ {
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */
diff --git a/src/platform/nxp/k32w/k32w1/BLEManagerImpl.h b/src/platform/nxp/k32w/k32w1/BLEManagerImpl.h
new file mode 100644
index 00000000000000..7aa4e9f1604b42
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/BLEManagerImpl.h
@@ -0,0 +1,99 @@
+/*
+ *
+ * Copyright (c) 2021-2023 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "RNG_Interface.h"
+#include "fwk_messaging.h"
+#include "fwk_os_abs.h"
+#include "fwk_platform_ble.h"
+#include "hci_transport.h"
+
+#include "ble_init.h"
+#include "controller_api.h"
+#include "controller_interface.h"
+
+#include
+
+/* host task configuration */
+#define HOST_TASK_PRIORITY (4U)
+#define HOST_TASK_STACK_SIZE (gHost_TaskStackSize_c / sizeof(StackType_t))
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+using namespace chip::Ble;
+
+class BLEManagerImpl final : public BLEManagerCommon
+{
+public:
+ // Allow the BLEManager interface class to delegate method calls to
+ // the implementation methods provided by this class.
+ friend BLEManager;
+
+ CHIP_ERROR InitHostController(ble_generic_cb_fp cb_fp) override;
+ BLEManagerCommon * GetImplInstance() override;
+
+private:
+ static BLEManagerImpl sInstance;
+
+ static CHIP_ERROR blekw_host_init(void);
+ static void Host_Task(osaTaskParam_t argument);
+
+ BleLayer * _GetBleLayer(void);
+
+ // ===== Members for internal use by the following friends.
+ friend BLEManager & BLEMgr(void);
+ friend BLEManagerImpl & BLEMgrImpl(void);
+};
+
+/**
+ * Returns a reference to the public interface of the BLEManager singleton object.
+ *
+ * Internal components should use this to access features of the BLEManager object
+ * that are common to all platforms.
+ */
+inline BLEManager & BLEMgr(void)
+{
+ return BLEManagerImpl::sInstance;
+}
+
+/**
+ * Returns the platform-specific implementation of the BLEManager singleton object.
+ *
+ * Internal components can use this to gain access to features of the BLEManager
+ * that are specific to the K32W platforms.
+ */
+inline BLEManagerImpl & BLEMgrImpl(void)
+{
+ return BLEManagerImpl::sInstance;
+}
+
+inline BleLayer * BLEManagerImpl::_GetBleLayer()
+{
+ return this;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */
diff --git a/src/platform/nxp/k32w/k32w1/BUILD.gn b/src/platform/nxp/k32w/k32w1/BUILD.gn
new file mode 100644
index 00000000000000..effb6cb2fc9d1e
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/BUILD.gn
@@ -0,0 +1,112 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/k32w1_sdk.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${k32w1_sdk_build_root}/k32w1_sdk.gni")
+
+assert(chip_device_platform == "k32w1")
+
+if (chip_enable_openthread) {
+ import("//build_overrides/openthread.gni")
+}
+
+if (chip_crypto == "platform") {
+ import("//build_overrides/mbedtls.gni")
+}
+
+static_library("k32w1") {
+ sources = [
+ "../../../SingletonConfigurationManager.cpp",
+ "../common/BLEManagerCommon.cpp",
+ "../common/BLEManagerCommon.h",
+ "BLEManagerImpl.cpp",
+ "BLEManagerImpl.h",
+ "CHIPDevicePlatformConfig.h",
+ "CHIPDevicePlatformEvent.h",
+ "ConfigurationManagerImpl.cpp",
+ "ConfigurationManagerImpl.h",
+ "ConnectivityManagerImpl.cpp",
+ "ConnectivityManagerImpl.h",
+ "DefaultTestEventTriggerDelegate.cpp",
+ "DefaultTestEventTriggerDelegate.h",
+ "DiagnosticDataProviderImpl.cpp",
+ "DiagnosticDataProviderImpl.h",
+ "K32W1Config.cpp",
+ "K32W1Config.h",
+ "KeyValueStoreManagerImpl.cpp",
+ "KeyValueStoreManagerImpl.h",
+ "Logging.cpp",
+ "PlatformManagerImpl.cpp",
+ "PlatformManagerImpl.h",
+ "SystemTimeSupport.cpp",
+ "ble_function_mux.c",
+ "ram_storage.c",
+ "ram_storage.h",
+ ]
+
+ public_deps = [ "${chip_root}/src/platform:platform_base" ]
+
+ if (chip_with_low_power != 0) {
+ sources += [ "LowPowerHooks.cpp" ]
+ }
+
+ if (chip_enable_ota_requestor) {
+ sources += [
+ "../common/OTAImageProcessorImpl.cpp",
+ "../common/OTAImageProcessorImpl.h",
+ "../common/OTATlvProcessor.cpp",
+ "../common/OTATlvProcessor.h",
+ "OTAFirmwareProcessor.cpp",
+ "OTAFirmwareProcessor.h",
+ "OTAHooks.cpp",
+ ]
+ }
+
+ if (chip_crypto == "platform") {
+ sources += [
+ "CHIPCryptoPalK32W1.cpp",
+ "K32W1PersistentStorageOpKeystore.cpp",
+ "K32W1PersistentStorageOpKeystore.h",
+ ]
+
+ public_deps += [ "${mbedtls_root}:mbedtls" ]
+ }
+
+ deps = []
+
+ if (chip_enable_openthread) {
+ sources += [
+ "../../../OpenThread/OpenThreadUtils.cpp",
+ "ThreadStackManagerImpl.cpp",
+ "ThreadStackManagerImpl.h",
+ ]
+
+ if (chip_mdns == "platform") {
+ sources += [
+ "../../../OpenThread/DnssdImpl.cpp",
+ "../../../OpenThread/OpenThreadDnssdImpl.cpp",
+ "../../../OpenThread/OpenThreadDnssdImpl.h",
+ ]
+ deps += [ "${chip_root}/src/lib/dnssd:platform_header" ]
+ }
+ }
+
+ public_deps += [ "${chip_root}/src/crypto" ]
+
+ public_configs =
+ [ "${chip_root}/src/lib/address_resolve:default_address_resolve_config" ]
+}
diff --git a/src/platform/nxp/k32w/k32w1/BlePlatformConfig.h b/src/platform/nxp/k32w/k32w1/BlePlatformConfig.h
new file mode 100644
index 00000000000000..a003927c74626e
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/BlePlatformConfig.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific configuration overrides for the CHIP BLE
+ * Layer on K32W platforms using the NXP SDK.
+ *
+ */
+
+#pragma once
+
+// ==================== Platform Adaptations ====================
+
+#define BLE_CONNECTION_OBJECT uint8_t
+#define BLE_CONNECTION_UNINITIALIZED ((uint8_t) 0xFF)
+
+// ========== Platform-specific Configuration Overrides =========
+
+/* none so far */
diff --git a/src/platform/nxp/k32w/k32w1/CHIPCryptoPalK32W1.cpp b/src/platform/nxp/k32w/k32w1/CHIPCryptoPalK32W1.cpp
new file mode 100644
index 00000000000000..6aad4ae85ea0fc
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/CHIPCryptoPalK32W1.cpp
@@ -0,0 +1,1004 @@
+/*
+ *
+ * Copyright (c) 2020-2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * mbedTLS based implementation of CHIP crypto primitives
+ */
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "SecLib_ecp256.h"
+#include "sss_crypto.h"
+
+namespace chip {
+namespace Crypto {
+
+#define MAX_ERROR_STR_LEN 128
+#define NUM_BYTES_IN_SHA256_HASH 32
+
+// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro.
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE(x) x
+#endif
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000)
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x
+#endif
+
+typedef struct
+{
+ bool mInitialized;
+ bool mDRBGSeeded;
+ mbedtls_ctr_drbg_context mDRBGCtxt;
+ mbedtls_entropy_context mEntropy;
+} EntropyContext;
+
+static EntropyContext gsEntropyContext;
+
+static void _log_mbedTLS_error(int error_code)
+{
+ if (error_code != 0)
+ {
+#if defined(MBEDTLS_ERROR_C)
+ char error_str[MAX_ERROR_STR_LEN];
+ mbedtls_strerror(error_code, error_str, sizeof(error_str));
+ ChipLogError(Crypto, "mbedTLS error: %s", error_str);
+#else
+ // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise
+ ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast(error_code));
+#endif
+ }
+}
+
+static bool _isValidTagLength(size_t tag_length)
+{
+ if (tag_length == 8 || tag_length == 12 || tag_length == 16)
+ {
+ return true;
+ }
+ return false;
+}
+
+static bool _isValidKeyLength(size_t length)
+{
+ // 16 bytes key for AES-CCM-128, 32 for AES-CCM-256
+ if (length == 16 || length == 32)
+ {
+ return true;
+ }
+ return false;
+}
+
+CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
+ const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
+ uint8_t * tag, size_t tag_length)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 1;
+
+ mbedtls_ccm_context context;
+ mbedtls_ccm_init(&context);
+
+ VerifyOrExit(plaintext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(ciphertext != nullptr || plaintext_length == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+ if (aad_length > 0)
+ {
+ VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ // Size of key is expressed in bits, hence the multiplication by 8.
+ result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // Encrypt
+ result = mbedtls_ccm_encrypt_and_tag(&context, plaintext_length, Uint8::to_const_uchar(nonce), nonce_length,
+ Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext),
+ Uint8::to_uchar(ciphertext), Uint8::to_uchar(tag), tag_length);
+ _log_mbedTLS_error(result);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ mbedtls_ccm_free(&context);
+ return error;
+}
+
+CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len,
+ const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
+ size_t nonce_length, uint8_t * plaintext)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 1;
+
+ mbedtls_ccm_context context;
+ mbedtls_ccm_init(&context);
+
+ VerifyOrExit(plaintext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(ciphertext != nullptr || ciphertext_len == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ if (aad_len > 0)
+ {
+ VerifyOrExit(aad != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ // Size of key is expressed in bits, hence the multiplication by 8.
+ result = mbedtls_ccm_setkey(&context, MBEDTLS_CIPHER_ID_AES, key.As(), sizeof(Aes128KeyByteArray) * 8);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ // Decrypt
+ result = mbedtls_ccm_auth_decrypt(&context, ciphertext_len, Uint8::to_const_uchar(nonce), nonce_length,
+ Uint8::to_const_uchar(aad), aad_len, Uint8::to_const_uchar(ciphertext),
+ Uint8::to_uchar(plaintext), Uint8::to_const_uchar(tag), tag_length);
+ _log_mbedTLS_error(result);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ mbedtls_ccm_free(&context);
+ return error;
+}
+
+CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+ // zero data length hash is supported.
+ VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+ const int result = mbedtls_sha256(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0);
+#else
+ const int result = mbedtls_sha256_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer), 0);
+#endif
+
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+ // zero data length hash is supported.
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+ const int result = mbedtls_sha1(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer));
+#else
+ const int result = mbedtls_sha1_ret(Uint8::to_const_uchar(data), data_length, Uint8::to_uchar(out_buffer));
+#endif
+
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(mbedtls_sha256_context),
+ "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying mbedtls_sha256_context");
+
+static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
+{
+ return SafePointerCast(context);
+}
+
+Hash_SHA256_stream::Hash_SHA256_stream(void)
+{
+ mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext);
+ mbedtls_sha256_init(context);
+}
+
+Hash_SHA256_stream::~Hash_SHA256_stream(void)
+{
+ mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext);
+ mbedtls_sha256_free(context);
+ Clear();
+}
+
+CHIP_ERROR Hash_SHA256_stream::Begin(void)
+{
+ mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext);
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+ const int result = mbedtls_sha256_starts(context, 0);
+#else
+ const int result = mbedtls_sha256_starts_ret(context, 0);
+#endif
+
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
+{
+ mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext);
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+ const int result = mbedtls_sha256_update(context, Uint8::to_const_uchar(data.data()), data.size());
+#else
+ const int result = mbedtls_sha256_update_ret(context, Uint8::to_const_uchar(data.data()), data.size());
+#endif
+
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
+{
+ mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext);
+
+ // Back-up context as we are about to finalize the hash to extract digest.
+ mbedtls_sha256_context previous_ctx;
+ mbedtls_sha256_init(&previous_ctx);
+ mbedtls_sha256_clone(&previous_ctx, context);
+
+ // Pad + compute digest, then finalize context. It is restored next line to continue.
+ CHIP_ERROR result = Finish(out_buffer);
+
+ // Restore context prior to finalization.
+ mbedtls_sha256_clone(context, &previous_ctx);
+ mbedtls_sha256_free(&previous_ctx);
+
+ return result;
+}
+
+CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
+{
+ VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+ mbedtls_sha256_context * const context = to_inner_hash_sha256_context(&mContext);
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+ const int result = mbedtls_sha256_finish(context, Uint8::to_uchar(out_buffer.data()));
+#else
+ const int result = mbedtls_sha256_finish_ret(context, Uint8::to_uchar(out_buffer.data()));
+#endif
+
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+ out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length);
+
+ return CHIP_NO_ERROR;
+}
+
+void Hash_SHA256_stream::Clear(void)
+{
+ mbedtls_platform_zeroize(this, sizeof(*this));
+}
+
+CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length,
+ const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length)
+{
+ VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(secret_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ // Salt is optional
+ if (salt_length > 0)
+ {
+ VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ VerifyOrReturnError(info_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(info != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL);
+
+ const int result = mbedtls_hkdf(md, Uint8::to_const_uchar(salt), salt_length, Uint8::to_const_uchar(secret), secret_length,
+ Uint8::to_const_uchar(info), info_length, Uint8::to_uchar(out_buffer), out_length);
+ _log_mbedTLS_error(result);
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
+ uint8_t * out_buffer, size_t out_length)
+{
+ VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ const mbedtls_md_info_t * const md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ VerifyOrReturnError(md != nullptr, CHIP_ERROR_INTERNAL);
+
+ const int result =
+ mbedtls_md_hmac(md, Uint8::to_const_uchar(key), key_length, Uint8::to_const_uchar(message), message_length, out_buffer);
+
+ _log_mbedTLS_error(result);
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
+ unsigned int iteration_count, uint32_t key_length, uint8_t * output)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+ const mbedtls_md_info_t * md_info;
+ mbedtls_md_context_t md_ctxt;
+ constexpr int use_hmac = 1;
+
+ bool free_md_ctxt = false;
+
+ VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ VerifyOrExit(md_info != nullptr, error = CHIP_ERROR_INTERNAL);
+
+ mbedtls_md_init(&md_ctxt);
+ free_md_ctxt = true;
+
+ result = mbedtls_md_setup(&md_ctxt, md_info, use_hmac);
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+ result = mbedtls_pkcs5_pbkdf2_hmac(&md_ctxt, Uint8::to_const_uchar(password), plen, Uint8::to_const_uchar(salt), slen,
+ iteration_count, key_length, Uint8::to_uchar(output));
+
+ VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+
+ if (free_md_ctxt)
+ {
+ mbedtls_md_free(&md_ctxt);
+ }
+
+ return error;
+}
+
+static EntropyContext * get_entropy_context()
+{
+ if (!gsEntropyContext.mInitialized)
+ {
+ mbedtls_entropy_init(&gsEntropyContext.mEntropy);
+ mbedtls_ctr_drbg_init(&gsEntropyContext.mDRBGCtxt);
+
+ gsEntropyContext.mInitialized = true;
+ }
+
+ return &gsEntropyContext;
+}
+
+static mbedtls_ctr_drbg_context * get_drbg_context()
+{
+ EntropyContext * const context = get_entropy_context();
+
+ mbedtls_ctr_drbg_context * const drbgCtxt = &context->mDRBGCtxt;
+
+ if (!context->mDRBGSeeded)
+ {
+ const int status = mbedtls_ctr_drbg_seed(drbgCtxt, mbedtls_entropy_func, &context->mEntropy, nullptr, 0);
+ if (status != 0)
+ {
+ _log_mbedTLS_error(status);
+ return nullptr;
+ }
+
+ context->mDRBGSeeded = true;
+ }
+
+ return drbgCtxt;
+}
+
+CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold)
+{
+ VerifyOrReturnError(fn_source != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ EntropyContext * const entropy_ctxt = get_entropy_context();
+ VerifyOrReturnError(entropy_ctxt != nullptr, CHIP_ERROR_INTERNAL);
+
+ const int result =
+ mbedtls_entropy_add_source(&entropy_ctxt->mEntropy, fn_source, p_source, threshold, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
+{
+ VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+ mbedtls_ctr_drbg_context * const drbg_ctxt = get_drbg_context();
+ VerifyOrReturnError(drbg_ctxt != nullptr, CHIP_ERROR_INTERNAL);
+
+ const int result = mbedtls_ctr_drbg_random(drbg_ctxt, Uint8::to_uchar(out_buffer), out_length);
+ VerifyOrReturnError(result == 0, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length)
+{
+ return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1;
+}
+
+mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType)
+{
+ switch (keyType)
+ {
+ case SupportedECPKeyTypes::ECP256R1:
+ return MBEDTLS_ECP_DP_SECP256R1;
+ default:
+ return MBEDTLS_ECP_DP_NONE;
+ }
+}
+
+static inline sss_sscp_object_t * to_keypair(P256KeypairContext * context)
+{
+ return SafePointerCast(context);
+}
+
+static inline const sss_sscp_object_t * to_const_keypair(const P256KeypairContext * context)
+{
+ return SafePointerCast(context);
+}
+
+CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ sss_sscp_asymmetric_t asyc;
+ size_t signatureSize = kP256_ECDSA_Signature_Length_Raw;
+
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint8_t digest[kSHA256_Hash_Length];
+ memset(&digest[0], 0, sizeof(digest));
+ ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
+
+ sss_sscp_object_t * keypair = to_keypair(&mKeypair);
+
+ VerifyOrExit((sss_sscp_asymmetric_context_init(&asyc, &g_sssSession, keypair, kAlgorithm_SSS_ECDSA_SHA256, kMode_SSS_Sign) ==
+ kStatus_SSS_Success),
+ CHIP_ERROR_INTERNAL);
+ VerifyOrExit((sss_sscp_asymmetric_sign_digest(&asyc, digest, kP256_FE_Length, out_signature.Bytes(), &signatureSize) ==
+ kStatus_SSS_Success),
+ CHIP_ERROR_INTERNAL);
+ VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ (void) sss_sscp_asymmetric_context_free(&asyc);
+ return error;
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
+ const P256ECDSASignature & signature) const
+{
+#if defined(MBEDTLS_ECDSA_C)
+ VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint8_t digest[kSHA256_Hash_Length];
+ memset(&digest[0], 0, sizeof(digest));
+ ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
+
+ return ECDSA_validate_hash_signature(&digest[0], sizeof(digest), signature);
+#else
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
+ const P256ECDSASignature & signature) const
+{
+
+ VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ sss_sscp_object_t ecdsaPublic;
+ sss_sscp_asymmetric_t asyc;
+ bool bFreeAsyncCtx = false;
+
+ size_t keySize = SSS_ECP_KEY_SZ(kP256_PrivateKey_Length);
+
+ VerifyOrReturnError(sss_sscp_key_object_init(&ecdsaPublic, &g_keyStore) == kStatus_SSS_Success, CHIP_ERROR_INTERNAL);
+
+ VerifyOrReturnError(sss_sscp_key_object_allocate_handle(&ecdsaPublic, 0u, kSSS_KeyPart_Public, kSSS_CipherType_EC_NIST_P,
+ keySize, SSS_KEYPROP_OPERATION_ASYM) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ // The first byte of the public key is the uncompressed marker
+ VerifyOrExit(SSS_KEY_STORE_SET_KEY(&ecdsaPublic, Uint8::to_const_uchar(*this) + 1, Length() - 1, keySize * 8,
+ (uint32_t) kSSS_KeyPart_Public) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(sss_sscp_asymmetric_context_init(&asyc, &g_sssSession, &ecdsaPublic, kAlgorithm_SSS_ECDSA_SHA256,
+ kMode_SSS_Verify) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ bFreeAsyncCtx = true;
+ VerifyOrExit(sss_sscp_asymmetric_verify_digest(&asyc, (uint8_t *) hash, hash_length, (uint8_t *) signature.ConstBytes(),
+ signature.Length()) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+exit:
+
+ if (bFreeAsyncCtx)
+ {
+ /* Need to be very careful, if we try to free something that is not initialized with success we will get an hw fault */
+ (void) sss_sscp_asymmetric_context_free(&asyc);
+ }
+ (void) SSS_KEY_OBJ_FREE(&ecdsaPublic);
+
+ return error;
+}
+
+CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
+{
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
+
+ sss_sscp_object_t * keypair = to_keypair(&mKeypair);
+ size_t coordinateLen = kP256_PrivateKey_Length;
+ size_t coordinateBitsLen = coordinateLen * 8;
+ size_t keySize = SSS_ECP_KEY_SZ(kP256_PrivateKey_Length);
+
+ sss_sscp_derive_key_t dCtx;
+ sss_sscp_object_t pEcdhPubKey;
+ sss_sscp_object_t sharedSecret;
+
+ bool bFreeSharedSecret = false;
+ bool bFreeDeriveContex = false;
+
+ VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+
+ /* Remote public key */
+ VerifyOrReturnError(sss_sscp_key_object_init(&pEcdhPubKey, &g_keyStore) == kStatus_SSS_Success, CHIP_ERROR_INTERNAL);
+ VerifyOrReturnError(sss_sscp_key_object_allocate_handle(&pEcdhPubKey, 0u, kSSS_KeyPart_Public, kSSS_CipherType_EC_NIST_P,
+ keySize, SSS_KEYPROP_OPERATION_KDF) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ // The first byte of the public key is the uncompressed marker
+ VerifyOrExit(SSS_KEY_STORE_SET_KEY(&pEcdhPubKey, Uint8::to_const_uchar(remote_public_key) + 1, keySize, coordinateBitsLen,
+ kSSS_KeyPart_Public) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+
+ /* Shared secret */
+ VerifyOrExit(sss_sscp_key_object_init(&sharedSecret, &g_keyStore) == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(sss_sscp_key_object_allocate_handle(&sharedSecret, 0u, kSSS_KeyPart_Default, kSSS_CipherType_AES, coordinateLen,
+ SSS_KEYPROP_OPERATION_NONE) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+ bFreeSharedSecret = true;
+
+ /* Secret Key generated inside SSS */
+ VerifyOrExit(sss_sscp_derive_key_context_init(&dCtx, &g_sssSession, keypair, kAlgorithm_SSS_ECDH,
+ kMode_SSS_ComputeSharedSecret) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+ bFreeDeriveContex = true;
+
+ VerifyOrExit(sss_sscp_asymmetric_dh_derive_key(&dCtx, &pEcdhPubKey, &sharedSecret) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(SSS_KEY_STORE_GET_PUBKEY(&sharedSecret, out_secret.Bytes(), &coordinateLen, &coordinateBitsLen) ==
+ kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+ SuccessOrExit(error = out_secret.SetLength(secret_length));
+
+exit:
+ (void) SSS_KEY_OBJ_FREE(&pEcdhPubKey);
+
+ /* Need to be very careful, if we try to free something that is not initialized with success we will get a hw fault */
+ if (bFreeSharedSecret)
+ (void) SSS_KEY_OBJ_FREE(&sharedSecret);
+ if (bFreeDeriveContex)
+ (void) sss_sscp_derive_key_context_free(&dCtx);
+
+ return error;
+}
+
+void ClearSecretData(uint8_t * buf, size_t len)
+{
+ mbedtls_platform_zeroize(buf, len);
+}
+
+// THE BELOW IS FROM `third_party/openthread/repo/third_party/mbedtls/repo/library/constant_time.c` since
+// mbedtls_ct_memcmp is not available on Linux somehow :(
+int mbedtls_ct_memcmp_copy(const void * a, const void * b, size_t n)
+{
+ size_t i;
+ volatile const unsigned char * A = (volatile const unsigned char *) a;
+ volatile const unsigned char * B = (volatile const unsigned char *) b;
+ volatile unsigned char diff = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ /* Read volatile data in order before computing diff.
+ * This avoids IAR compiler warning:
+ * 'the order of volatile accesses is undefined ..' */
+ unsigned char x = A[i], y = B[i];
+ diff |= x ^ y;
+ }
+
+ return ((int) diff);
+}
+
+bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
+{
+ return mbedtls_ct_memcmp_copy(a, b, n) == 0;
+}
+
+CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
+{
+
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ size_t keyBitsLen = kP256_PrivateKey_Length * 8;
+ size_t keySize = SSS_ECP_KEY_SZ(kP256_PrivateKey_Length);
+
+ Clear();
+
+ sss_sscp_object_t * keypair = to_keypair(&mKeypair);
+
+ VerifyOrReturnError(sss_sscp_key_object_init(keypair, &g_keyStore) == kStatus_SSS_Success, CHIP_ERROR_INTERNAL);
+
+ VerifyOrReturnError(sss_sscp_key_object_allocate_handle(
+ keypair, 0x0u, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 3 * kP256_PrivateKey_Length,
+ SSS_KEYPROP_OPERATION_KDF | SSS_KEYPROP_OPERATION_ASYM) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(SSS_ECP_GENERATE_KEY(keypair, keyBitsLen) == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL);
+
+ // The first byte of the public key is the uncompressed marker
+ Uint8::to_uchar(mPublicKey)[0] = 0x04;
+
+ // Extract public key, write from the second byte
+ VerifyOrExit(SSS_KEY_STORE_GET_PUBKEY(keypair, Uint8::to_uchar(mPublicKey) + 1, &keySize, &keyBitsLen) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ mInitialized = true;
+
+exit:
+ if (mInitialized != true)
+ (void) SSS_KEY_OBJ_FREE(keypair);
+
+ return error;
+}
+
+CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+ Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ Clear();
+
+ const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length();
+ sss_sscp_object_t * keypair = to_keypair(&mKeypair);
+
+ VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+ bbuf.Put(input.ConstBytes(), mPublicKey.Length());
+ VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
+
+ /* must load plain text private key inside SSS */
+ VerifyOrExit((sss_sscp_key_object_init(keypair, &g_keyStore) == kStatus_SSS_Success), error = CHIP_ERROR_INTERNAL);
+
+ /* Allocate key handle */
+ VerifyOrExit(sss_sscp_key_object_allocate_handle(keypair, 0x0u, kSSS_KeyPart_Private, kSSS_CipherType_EC_NIST_P,
+ kP256_PrivateKey_Length, SSS_KEYPROP_OPERATION_ASYM) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+
+ if (SSS_KEY_STORE_SET_KEY(keypair, privkey, kP256_PrivateKey_Length, kP256_PrivateKey_Length * 8, kSSS_KeyPart_Private) !=
+ kStatus_SSS_Success)
+ {
+ (void) SSS_KEY_OBJ_FREE(keypair);
+ error = CHIP_ERROR_INTERNAL;
+ }
+ else
+ {
+ mInitialized = true;
+ }
+
+exit:
+ return error;
+}
+void P256Keypair::Clear()
+{
+ if (mInitialized)
+ {
+ sss_sscp_object_t * keypair = to_keypair(&mKeypair);
+ (void) SSS_KEY_OBJ_FREE(keypair);
+ mInitialized = false;
+ }
+}
+
+P256Keypair::~P256Keypair()
+{
+ Clear();
+}
+
+CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+
+ MutableByteSpan csr(out_csr, csr_length);
+ CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+ csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+ return err;
+}
+
+typedef struct Spake2p_Context
+{
+ ecp256Point_t M;
+ ecp256Point_t N;
+ ecp256Point_t X;
+ ecp256Point_t Y;
+ ecp256Point_t L;
+ ecp256Point_t Z;
+ ecp256Point_t V;
+
+ big_int256_t w0;
+ big_int256_t w1;
+ big_int256_t xy;
+ big_int256_t tempbn;
+
+} Spake2p_Context;
+
+static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context)
+{
+ return SafePointerCast(context);
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+ memset(context, 0, sizeof(Spake2p_Context));
+
+ M = &context->M;
+ N = &context->N;
+ X = &context->X;
+ Y = &context->Y;
+ L = &context->L;
+ V = &context->V;
+ Z = &context->Z;
+
+ w0 = &context->w0;
+ w1 = &context->w1;
+ xy = &context->xy;
+ tempbn = &context->tempbn;
+
+ return error;
+
+exit:
+ _log_mbedTLS_error(result);
+ Clear();
+ return error;
+}
+
+void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
+{
+ VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT);
+
+ state = CHIP_SPAKE2P_STATE::PREINIT;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len,
+ MutableByteSpan & out_span)
+{
+ HMAC_sha hmac;
+ VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+ ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length));
+ out_span = out_span.SubSpan(0, kSHA256_Hash_Length);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len,
+ const uint8_t * in, size_t in_len)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ int result = 0;
+
+ uint8_t computed_mac[kSHA256_Hash_Length];
+ MutableByteSpan computed_mac_span{ computed_mac };
+ VerifyOrExit(mac_len == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ SuccessOrExit(error = Mac(key, key_len, in, in_len, computed_mac_span));
+ VerifyOrExit(computed_mac_span.size() == mac_len, error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(IsBufferContentEqualConstantTime(mac, computed_mac, kSHA256_Hash_Length), error = CHIP_ERROR_INTERNAL);
+
+exit:
+ _log_mbedTLS_error(result);
+ return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe)
+{
+ secEcp256Status_t result;
+ uint32_t FE[SEC_ECP256_COORDINATE_WLEN];
+
+ result = ECP256_ModularReductionN(FE, in, in_len);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ result = ECP256_FieldLoad((uint32_t *) fe, (const uint8_t *) FE, in_len);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len)
+{
+ secEcp256Status_t result;
+
+ result = ECP256_FieldWrite(out, (uint8_t *) fe);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe)
+{
+ secEcp256Status_t result;
+ big_int256_t PrivateKey;
+
+ result = ECP256_GeneratePrivateKey(&PrivateKey);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ result = ECP256_FieldWrite((uint8_t *) fe, (uint8_t *) &PrivateKey);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2)
+{
+ secEcp256Status_t result;
+
+ result = ECP256_ScalarMultiplicationModN((uint32_t *) fer, (const uint32_t *) fe1, (const uint32_t *) fe2);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R)
+{
+ ECP256_PointLoad((ecp256Point_t *) R, in, false);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len)
+{
+ ECP256_PointWrite(out, (ecp256Point_t *) R, false);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1)
+{
+ secEcp256Status_t result;
+
+ result = ECP256_PointMult((ecp256Point_t *) R, (const uint8_t *) P1, (const uint8_t *) fe1);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2,
+ const void * fe2)
+{
+ secEcp256Status_t result;
+
+ result = ECP256_DoublePointMulAdd(R, P1, fe1, P2, fe2);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R)
+{
+ secEcp256Status_t result;
+
+ result = ECP256_PointInvert((uint32_t *) R, (const uint32_t *) R);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R)
+{
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len)
+{
+ secEcp256Status_t result;
+ ecp256Point_t gen_point;
+ uint32_t W1[SEC_ECP256_COORDINATE_WLEN];
+
+ result = ECP256_ModularReductionN(W1, w1in, w1in_len);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ result = ECP256_GeneratePublicKey((uint8_t *) &gen_point, (uint8_t *) &W1, NULL);
+ VerifyOrReturnError(result == gSecEcp256Success_c, CHIP_ERROR_INTERNAL);
+
+ ECP256_PointWrite(Lout, (ecp256Point_t *) &gen_point, false);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R)
+{
+ VerifyOrReturnError(ECP256_PointValid((ecp256Point_t *) R), CHIP_ERROR_INTERNAL);
+
+ return CHIP_NO_ERROR;
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformConfig.h b/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformConfig.h
new file mode 100644
index 00000000000000..60a1498cff9444
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformConfig.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific configuration overrides for the chip Device Layer
+ * on K32W platforms using the NXP SDK.
+ */
+
+#pragma once
+
+// ==================== Platform Adaptations ====================
+
+#define K32W_NO_ERRORS 0
+#define K32W_ENTRY_NOT_FOUND 1
+
+#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0
+#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0
+
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#define CHIP_DEVICE_CHIP0BLE_DEBUG 0
+#endif
+
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0
+// #define CHIP_DEVICE_CONFIG_PERSISTED_STORAGE_GLOBAL_EIDC_KEY 2
+
+// ========== Platform-specific Configuration =========
+
+// These are configuration options that are unique to the K32W platform.
+// These can be overridden by the application as needed.
+
+/**
+ * @def CHIP_DEVICE_LAYER_BLE_OBSERVER_PRIORITY
+ *
+ * The priority of the SoftDevice observer event handler registered by the
+ * chip BleLayer.
+ */
+#ifndef CHIP_DEVICE_LAYER_BLE_OBSERVER_PRIORITY
+#define CHIP_DEVICE_LAYER_BLE_OBSERVER_PRIORITY 3
+#endif // CHIP_DEVICE_LAYER_BLE_OBSERVER_PRIORITY
+
+/**
+ * @def CHIP_DEVICE_LAYER_BLE_CONN_CFG_TAG
+ *
+ * The SoftDevice BLE connection configuration tag used by the chip
+ * BleLayer.
+ */
+#ifndef CHIP_DEVICE_LAYER_BLE_CONN_CFG_TAG
+#define CHIP_DEVICE_LAYER_BLE_CONN_CFG_TAG 1
+#endif // CHIP_DEVICE_LAYER_BLE_CONN_CFG_TAG
+
+/**
+ * @def CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY
+ *
+ * The delay before rebooting after an OTA process was finished.
+ */
+#ifndef CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY
+#define CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY 3000
+#endif // CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY
+
+// ========== Platform-specific Configuration Overrides =========
+#ifndef CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE
+#define CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE (6 * 1024)
+#endif // CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE
+
+#ifndef CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE
+#define CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE 3072
+#endif // CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE
+
+// Max size of event queue
+#define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 25
+
+#ifndef CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME
+#define CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME "BLE App Task"
+#endif // CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME
+
+#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_TELEMETRY 0
+#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY 0
+#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_TELEMETRY_FULL 0
+
+#define CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED 1
+
+#define CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART 0
+
+#define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0
+
+#define CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY 3
+
+#define CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY 2
+
+#if CHIP_ENABLE_OPENTHREAD
+#define CHIP_DEVICE_CONFIG_ENABLE_THREAD 1
+#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT 1
+#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT 1
+#endif
+
+#define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1
diff --git a/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformEvent.h b/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformEvent.h
new file mode 100644
index 00000000000000..e4acfb369c4bef
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/CHIPDevicePlatformEvent.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Defines platform-specific event types and data for the chip
+ * Device Layer on K32W061 platforms using the NXP SDK.
+ */
+
+#pragma once
+
+#include
+
+namespace chip {
+namespace DeviceLayer {
+
+namespace DeviceEventType {
+
+/**
+ * Enumerates K32W1 platform-specific event types that are visible to the application.
+ */
+enum PublicPlatformSpecificEventTypes
+{
+ /* None currently defined */
+};
+
+/**
+ * Enumerates K32W061 platform-specific event types that are internal to the chip Device Layer.
+ */
+enum InternalPlatformSpecificEventTypes
+{
+ /* None currently defined */
+};
+
+} // namespace DeviceEventType
+
+/**
+ * Represents platform-specific event information for NXP K32W061 platforms.
+ */
+
+struct ChipDevicePlatformEvent final
+{
+};
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h
new file mode 100644
index 00000000000000..b8ae07689e14bb
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific configuration overrides for CHIP on
+ * NXP K32W platforms.
+ */
+
+#pragma once
+
+#include
+
+// ==================== General Platform Adaptations ====================
+
+#define CHIP_CONFIG_ABORT() abort()
+
+#define CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE uint16_t
+#define CHIP_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID 1
+#define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 2
+
+#define CHIP_CONFIG_LIFETIIME_PERSISTED_COUNTER_KEY 0x01
+
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE (512)
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE (512)
+
+// ==================== Security Adaptations ====================
+
+// FIXME: K32W currently set to CHIP (Does this use Entropy.cpp ?)
+
+// ==================== General Configuration Overrides ====================
+
+#ifndef CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS
+#define CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS 8
+#endif // CHIP_CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS
+
+#ifndef CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS
+#define CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS 8
+#endif // CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS
+
+#ifndef CHIP_LOG_FILTERING
+#define CHIP_LOG_FILTERING 0
+#endif // CHIP_LOG_FILTERING
+
+#ifndef CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS
+#define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1
+#endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS
+
+// ==================== WDM Configuration Overrides ====================
+
+#ifndef WDM_MAX_NUM_SUBSCRIPTION_CLIENTS
+#define WDM_MAX_NUM_SUBSCRIPTION_CLIENTS 2
+#endif // WDM_MAX_NUM_SUBSCRIPTION_CLIENTS
+
+#ifndef WDM_MAX_NUM_SUBSCRIPTION_HANDLERS
+#define WDM_MAX_NUM_SUBSCRIPTION_HANDLERS 2
+#endif // WDM_MAX_NUM_SUBSCRIPTION_HANDLERS
+
+#ifndef WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT
+#define WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT 2
+#endif // WDM_PUBLISHER_MAX_NOTIFIES_IN_FLIGHT
diff --git a/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.cpp b/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.cpp
new file mode 100644
index 00000000000000..43aa7fa591b8f0
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.cpp
@@ -0,0 +1,291 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides the implementation of the Device Layer ConfigurationManager object
+ * for K32W platforms using the NXP SDK.
+ */
+
+/* this file behaves like a config.h, comes first */
+#include
+
+#include
+#include
+#include
+#include
+
+// #include
+#include "fsl_cmc.h"
+#include "fsl_device_registers.h"
+
+namespace chip {
+namespace DeviceLayer {
+
+using namespace ::chip::DeviceLayer::Internal;
+
+// TODO: Define a Singleton instance of CHIP Group Key Store here
+
+ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance()
+{
+ static ConfigurationManagerImpl sInstance;
+ return sInstance;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::Init()
+{
+ CHIP_ERROR err;
+ uint32_t rebootCount = 0;
+
+ if (K32WConfig::ConfigValueExists(K32WConfig::kCounterKey_RebootCount))
+ {
+ err = GetRebootCount(rebootCount);
+ SuccessOrExit(err);
+
+ err = StoreRebootCount(rebootCount + 1);
+ SuccessOrExit(err);
+ }
+ else
+ {
+ // The first boot after factory reset of the Node.
+ err = StoreRebootCount(0);
+ SuccessOrExit(err);
+ }
+
+ if (!K32WConfig::ConfigValueExists(K32WConfig::kCounterKey_TotalOperationalHours))
+ {
+ err = StoreTotalOperationalHours(0);
+ SuccessOrExit(err);
+ }
+
+ if (!K32WConfig::ConfigValueExists(K32WConfig::kCounterKey_BootReason))
+ {
+ err = StoreBootReason(to_underlying(BootReasonType::kUnspecified));
+ SuccessOrExit(err);
+ }
+
+ // Initialize the generic implementation base class.
+ err = Internal::GenericConfigurationManagerImpl::Init();
+ SuccessOrExit(err);
+
+ // TODO: Initialize the global GroupKeyStore object here
+
+ err = CHIP_NO_ERROR;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreSoftwareUpdateCompleted()
+{
+ /* Empty implementation*/
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount)
+{
+ return ReadConfigValue(K32WConfig::kCounterKey_RebootCount, rebootCount);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount)
+{
+ return WriteConfigValue(K32WConfig::kCounterKey_RebootCount, rebootCount);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
+{
+ return ReadConfigValue(K32WConfig::kCounterKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours)
+{
+ return WriteConfigValue(K32WConfig::kCounterKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason)
+{
+ bootReason = to_underlying(BootReasonType::kUnspecified);
+
+ uint32_t reason = CMC_GetSystemResetStatus(CMC0);
+
+ if ((reason & CMC_SRS_POR_MASK) || (reason & CMC_SRS_PIN_MASK))
+ {
+ bootReason = to_underlying(BootReasonType::kPowerOnReboot);
+ }
+ else if (reason & CMC_SRS_SW_MASK)
+ {
+ bootReason = to_underlying(BootReasonType::kSoftwareReset);
+ }
+ else if ((reason & CMC_SRS_WDOG0_MASK) || (reason & CMC_SRS_WDOG1_MASK))
+ {
+ bootReason = to_underlying(BootReasonType::kSoftwareWatchdogReset);
+ }
+ else
+ {
+ bootReason = to_underlying(BootReasonType::kUnspecified);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreBootReason(uint32_t bootReason)
+{
+ return WriteConfigValue(K32WConfig::kCounterKey_BootReason, bootReason);
+}
+
+bool ConfigurationManagerImpl::CanFactoryReset()
+{
+ // TODO: query the application to determine if factory reset is allowed.
+ return true;
+}
+
+void ConfigurationManagerImpl::InitiateFactoryReset()
+{
+ PlatformMgr().ScheduleWork(DoFactoryReset);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+ uint32_t & value)
+{
+ CHIP_ERROR err;
+
+ err = K32WConfig::ReadConfigValueCounter(persistedStorageKey, value);
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+ uint32_t value)
+{
+ // This method reads Chip Persisted Counter type nvm3 objects.
+ // (where persistedStorageKey represents an index to the counter).
+ CHIP_ERROR err;
+
+ err = K32WConfig::WriteConfigValueCounter(persistedStorageKey, value);
+ if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+ }
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val)
+{
+ return K32WConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val)
+{
+ return K32WConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val)
+{
+ return K32WConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
+{
+ return K32WConfig::ReadConfigValueStr(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
+{
+ return K32WConfig::ReadConfigValueBin(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val)
+{
+ return K32WConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val)
+{
+ return K32WConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val)
+{
+ return K32WConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str)
+{
+ return K32WConfig::WriteConfigValueStr(key, str);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen)
+{
+ return K32WConfig::WriteConfigValueStr(key, str, strLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
+{
+ return K32WConfig::WriteConfigValueBin(key, data, dataLen);
+}
+
+void ConfigurationManagerImpl::RunConfigUnitTest(void)
+{
+ K32WConfig::RunConfigUnitTest();
+}
+
+void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg)
+{
+ CHIP_ERROR err;
+
+ ChipLogProgress(DeviceLayer, "Performing factory reset");
+
+ err = K32WConfig::FactoryResetConfig();
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", ErrorStr(err));
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+ ThreadStackMgr().ErasePersistentInfo();
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+ // Restart the system.
+ ChipLogProgress(DeviceLayer, "System restarting");
+
+ NVIC_SystemReset();
+
+ while (1)
+ {
+ }
+}
+
+ConfigurationManager & ConfigurationMgrImpl()
+{
+ return ConfigurationManagerImpl::GetDefaultInstance();
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.h b/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.h
new file mode 100644
index 00000000000000..26201d85f58a52
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/ConfigurationManagerImpl.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the ConfigurationManager object
+ * for K32W platforms using the NXP SDK.
+ */
+
+#pragma once
+
+#include "K32W1Config.h"
+#include
+
+namespace chip {
+namespace DeviceLayer {
+
+/**
+ * Concrete implementation of the ConfigurationManager singleton object for the K32W platform.
+ */
+class ConfigurationManagerImpl final : public Internal::GenericConfigurationManagerImpl
+{
+public:
+ // This returns an instance of this class.
+ static ConfigurationManagerImpl & GetDefaultInstance();
+ CHIP_ERROR StoreSoftwareUpdateCompleted();
+
+private:
+ // ===== Members that implement the ConfigurationManager public interface.
+
+ CHIP_ERROR Init(void) override;
+ CHIP_ERROR GetPrimaryWiFiMACAddress(uint8_t * buf) override;
+ bool CanFactoryReset(void) override;
+ void InitiateFactoryReset(void) override;
+ CHIP_ERROR ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t & value) override;
+ CHIP_ERROR WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key key, uint32_t value) override;
+ CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override;
+ CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override;
+ CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
+ CHIP_ERROR StoreTotalOperationalHours(uint32_t totalOperationalHours) override;
+ CHIP_ERROR GetBootReason(uint32_t & bootReasons) override;
+ CHIP_ERROR StoreBootReason(uint32_t bootReasons) override;
+
+ // NOTE: Other public interface methods are implemented by GenericConfigurationManagerImpl<>.
+
+ // ===== Members that implement the GenericConfigurationManagerImpl protected interface.
+ CHIP_ERROR ReadConfigValue(Key key, bool & val) override;
+ CHIP_ERROR ReadConfigValue(Key key, uint32_t & val) override;
+ CHIP_ERROR ReadConfigValue(Key key, uint64_t & val) override;
+ CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) override;
+ CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) override;
+ CHIP_ERROR WriteConfigValue(Key key, bool val) override;
+ CHIP_ERROR WriteConfigValue(Key key, uint32_t val) override;
+ CHIP_ERROR WriteConfigValue(Key key, uint64_t val) override;
+ CHIP_ERROR WriteConfigValueStr(Key key, const char * str) override;
+ CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen) override;
+ CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) override;
+ void RunConfigUnitTest(void) override;
+
+ // ===== Private members reserved for use by this class only.
+
+ static void DoFactoryReset(intptr_t arg);
+};
+
+inline CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf)
+{
+ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+}
+
+/**
+ * Returns the platform-specific implementation of the ConfigurationManager object.
+ *
+ * Applications can use this to gain access to features of the ConfigurationManager
+ * that are specific to the selected platform.
+ */
+ConfigurationManager & ConfigurationMgrImpl();
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.cpp b/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.cpp
new file mode 100644
index 00000000000000..3182a874fbf41c
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.cpp
@@ -0,0 +1,83 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* this file behaves like a config.h, comes first */
+#include
+
+#include
+#include
+#include
+#include
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#include
+#include
+#include
+#include
+#endif
+
+#include
+
+#if INET_CONFIG_ENABLE_TCP_ENDPOINT
+#include
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#include
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::System;
+using namespace ::chip::TLV;
+using namespace ::chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+
+ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
+
+CHIP_ERROR ConnectivityManagerImpl::_Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ // Initialize the generic base classes that require it.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+ GenericConnectivityManagerImpl_Thread::_Init();
+#endif
+
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+ // Forward the event to the generic base classes as needed.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+ GenericConnectivityManagerImpl_Thread::_OnPlatformEvent(event);
+#endif
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.h b/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.h
new file mode 100644
index 00000000000000..4b8708d3dc604b
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/ConnectivityManagerImpl.h
@@ -0,0 +1,105 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#if INET_CONFIG_ENABLE_TCP_ENDPOINT
+#include
+#endif
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#include
+#else
+#include
+#endif
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include
+#else
+#include
+#endif
+#include
+
+namespace chip {
+namespace DeviceLayer {
+
+/**
+ * Concrete implementation of the ConnectivityManager singleton object for NXP K32W platforms.
+ */
+class ConnectivityManagerImpl final : public ConnectivityManager,
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ public Internal::GenericConnectivityManagerImpl_BLE,
+#else
+ public Internal::GenericConnectivityManagerImpl_NoBLE,
+#endif
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+ public Internal::GenericConnectivityManagerImpl_Thread,
+#else
+ public Internal::GenericConnectivityManagerImpl_NoThread,
+#endif
+ public Internal::GenericConnectivityManagerImpl_NoWiFi,
+ public Internal::GenericConnectivityManagerImpl_UDP,
+#if INET_CONFIG_ENABLE_TCP_ENDPOINT
+ public Internal::GenericConnectivityManagerImpl_TCP,
+#endif
+ public Internal::GenericConnectivityManagerImpl
+{
+ // Allow the ConnectivityManager interface class to delegate method calls to
+ // the implementation methods provided by this class.
+ friend class ConnectivityManager;
+
+private:
+ // ===== Members that implement the ConnectivityManager abstract interface.
+
+ CHIP_ERROR _Init(void);
+ void _OnPlatformEvent(const ChipDeviceEvent * event);
+
+ // ===== Members for internal use by the following friends.
+
+ friend ConnectivityManager & ConnectivityMgr(void);
+ friend ConnectivityManagerImpl & ConnectivityMgrImpl(void);
+
+ static ConnectivityManagerImpl sInstance;
+};
+
+/**
+ * Returns the public interface of the ConnectivityManager singleton object.
+ *
+ * Chip applications should use this to access features of the ConnectivityManager object
+ * that are common to all platforms.
+ */
+inline ConnectivityManager & ConnectivityMgr(void)
+{
+ return ConnectivityManagerImpl::sInstance;
+}
+
+/**
+ * Returns the platform-specific implementation of the ConnectivityManager singleton object.
+ *
+ * Chip applications can use this to gain access to features of the ConnectivityManager
+ * that are specific to the ESP32 platform.
+ */
+inline ConnectivityManagerImpl & ConnectivityMgrImpl(void)
+{
+ return ConnectivityManagerImpl::sInstance;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp b/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp
new file mode 100644
index 00000000000000..1a01acfdb69385
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.cpp
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DefaultTestEventTriggerDelegate.h"
+
+#include
+#include
+
+namespace chip {
+
+bool DefaultTestEventTriggerDelegate::DoesEnableKeyMatch(const ByteSpan & enableKey) const
+{
+ return !mEnableKey.empty() && mEnableKey.data_equal(enableKey);
+}
+
+CHIP_ERROR DefaultTestEventTriggerDelegate::HandleEventTrigger(uint64_t eventTrigger)
+{
+ if (eventTrigger == kQueryTrigger)
+ {
+ ChipLogProgress(DeviceLayer, "DefaultTestEventTriggerDelegate: event triggered");
+ return CHIP_NO_ERROR;
+ }
+
+ return CHIP_ERROR_INVALID_ARGUMENT;
+}
+
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h b/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h
new file mode 100644
index 00000000000000..cf71fb37d96470
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+
+namespace chip {
+
+class DefaultTestEventTriggerDelegate : public TestEventTriggerDelegate
+{
+public:
+ static constexpr uint64_t kQueryTrigger = 1234;
+
+ explicit DefaultTestEventTriggerDelegate(const ByteSpan & enableKey) : mEnableKey(enableKey) {}
+
+ bool DoesEnableKeyMatch(const ByteSpan & enableKey) const override;
+ CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override;
+
+private:
+ ByteSpan mEnableKey;
+};
+
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.cpp b/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.cpp
new file mode 100644
index 00000000000000..5bc354351e4fb7
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.cpp
@@ -0,0 +1,232 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the DiagnosticDataProvider object
+ * for k32w1 platform.
+ */
+
+#include
+
+#include
+#include
+#include
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#include
+#endif
+
+extern "C" void xPortResetHeapMinimumEverFreeHeapSize(void);
+
+#include
+
+#include
+
+using namespace ::chip::app::Clusters::GeneralDiagnostics;
+
+namespace chip {
+namespace DeviceLayer {
+
+DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance()
+{
+ static DiagnosticDataProviderImpl sInstance;
+ return sInstance;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapFree(uint64_t & currentHeapFree)
+{
+ size_t freeHeapSize;
+
+ freeHeapSize = xPortGetFreeHeapSize();
+ currentHeapFree = static_cast(freeHeapSize);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapUsed(uint64_t & currentHeapUsed)
+{
+ size_t freeHeapSize;
+ size_t usedHeapSize;
+
+ freeHeapSize = xPortGetFreeHeapSize();
+ usedHeapSize = MinimalHeapSize_c - freeHeapSize;
+
+ currentHeapUsed = static_cast(usedHeapSize);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark)
+{
+ size_t highWatermarkHeapSize;
+
+ highWatermarkHeapSize = MinimalHeapSize_c - xPortGetMinimumEverFreeHeapSize();
+ currentHeapHighWatermark = static_cast(highWatermarkHeapSize);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetThreadMetrics(ThreadMetrics ** threadMetricsOut)
+{
+ /* Obtain all available task information */
+ TaskStatus_t * taskStatusArray;
+ ThreadMetrics * head = nullptr;
+ unsigned long arraySize, x, dummy;
+
+ arraySize = uxTaskGetNumberOfTasks();
+
+ taskStatusArray = (TaskStatus_t *) pvPortMalloc(arraySize * sizeof(TaskStatus_t));
+
+ if (taskStatusArray != NULL)
+ {
+ /* Generate raw status information about each task. */
+ arraySize = uxTaskGetSystemState(taskStatusArray, arraySize, &dummy);
+ /* For each populated position in the taskStatusArray array,
+ format the raw data as human readable ASCII data. */
+
+ for (x = 0; x < arraySize; x++)
+ {
+ ThreadMetrics * thread = (ThreadMetrics *) pvPortMalloc(sizeof(ThreadMetrics));
+
+ strncpy(thread->NameBuf, taskStatusArray[x].pcTaskName, kMaxThreadNameLength - 1);
+ thread->NameBuf[kMaxThreadNameLength] = '\0';
+ thread->name.Emplace(CharSpan::fromCharString(thread->NameBuf));
+ thread->id = taskStatusArray[x].xTaskNumber;
+
+ thread->stackFreeMinimum.Emplace(taskStatusArray[x].usStackHighWaterMark);
+
+ /* Unsupported metrics */
+ thread->stackFreeCurrent.ClearValue();
+ thread->stackSize.ClearValue();
+
+ thread->Next = head;
+ head = thread;
+ }
+
+ *threadMetricsOut = head;
+ /* The array is no longer needed, free the memory it consumes. */
+ vPortFree(taskStatusArray);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void DiagnosticDataProviderImpl::ReleaseThreadMetrics(ThreadMetrics * threadMetrics)
+{
+ while (threadMetrics)
+ {
+ ThreadMetrics * del = threadMetrics;
+ threadMetrics = threadMetrics->Next;
+ vPortFree(del);
+ }
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount)
+{
+ uint32_t count = 0;
+
+ CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count);
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ rebootCount = static_cast(count);
+ }
+
+ return err;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime)
+{
+ System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp();
+ System::Clock::Timestamp startTime = PlatformMgrImpl().GetStartTime();
+
+ if (currentTime >= startTime)
+ {
+ upTime = std::chrono::duration_cast(currentTime - startTime).count();
+ return CHIP_NO_ERROR;
+ }
+
+ return CHIP_ERROR_INVALID_TIME;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
+{
+ uint64_t upTime = 0;
+
+ if (GetUpTime(upTime) == CHIP_NO_ERROR)
+ {
+ uint32_t totalHours = 0;
+ if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ totalOperationalHours = totalHours + static_cast(upTime / 3600);
+ return CHIP_NO_ERROR;
+ }
+ }
+
+ return CHIP_ERROR_INVALID_TIME;
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason)
+{
+ uint32_t reason = 0;
+
+ CHIP_ERROR err = ConfigurationMgr().GetBootReason(reason);
+
+ if (err == CHIP_NO_ERROR)
+ {
+ VerifyOrReturnError(reason <= UINT8_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
+ bootReason = static_cast(reason);
+ }
+
+ return err;
+}
+
+DiagnosticDataProvider & GetDiagnosticDataProviderImpl()
+{
+ return DiagnosticDataProviderImpl::GetDefaultInstance();
+}
+
+CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp)
+{
+ NetworkInterface * ifp = new NetworkInterface();
+
+ const char * threadNetworkName = otThreadGetNetworkName(ThreadStackMgrImpl().OTInstance());
+ ifp->name = Span(threadNetworkName, strlen(threadNetworkName));
+ ifp->isOperational = true;
+ ifp->offPremiseServicesReachableIPv4.SetNull();
+ ifp->offPremiseServicesReachableIPv6.SetNull();
+ ifp->type = InterfaceTypeEnum::EMBER_ZCL_INTERFACE_TYPE_ENUM_THREAD;
+ uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength];
+ ConfigurationMgr().GetPrimary802154MACAddress(macBuffer);
+ ifp->hardwareAddress = ByteSpan(macBuffer, ConfigurationManager::kPrimaryMACAddressLength);
+ ifp->Next = nullptr;
+
+ *netifpp = ifp;
+ return CHIP_NO_ERROR;
+}
+
+void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp)
+{
+ while (netifp)
+ {
+ NetworkInterface * del = netifp;
+ netifp = netifp->Next;
+ delete del;
+ }
+}
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.h b/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.h
new file mode 100644
index 00000000000000..78cca26b3683ee
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/DiagnosticDataProviderImpl.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Provides an implementation of the DiagnosticDataProvider object.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace chip {
+namespace DeviceLayer {
+
+/**
+ * Concrete implementation of the PlatformManager singleton object for Linux platforms.
+ */
+class DiagnosticDataProviderImpl : public DiagnosticDataProvider
+{
+public:
+ static DiagnosticDataProviderImpl & GetDefaultInstance();
+
+ // ===== Methods that implement the PlatformManager abstract interface.
+
+ bool SupportsWatermarks() override { return true; }
+ CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override;
+ CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override;
+ CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override;
+ CHIP_ERROR GetThreadMetrics(ThreadMetrics ** threadMetricsOut) override;
+ void ReleaseThreadMetrics(ThreadMetrics * threadMetrics) override;
+
+ CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override;
+ CHIP_ERROR GetUpTime(uint64_t & upTime) override;
+ CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
+ CHIP_ERROR GetBootReason(BootReasonType & bootReason) override;
+ CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override;
+ void ReleaseNetworkInterfaces(NetworkInterface * netifp) override;
+};
+
+/**
+ * Returns the platform-specific implementation of the DiagnosticDataProvider singleton object.
+ *
+ * Applications can use this to gain access to features of the DiagnosticDataProvider
+ * that are specific to the selected platform.
+ */
+DiagnosticDataProvider & GetDiagnosticDataProviderImpl();
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/InetPlatformConfig.h b/src/platform/nxp/k32w/k32w1/InetPlatformConfig.h
new file mode 100644
index 00000000000000..e59c31f75eac37
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/InetPlatformConfig.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific configuration overrides for the CHIP Inet
+ * Layer on K32W platforms using the NXP SDK.
+ *
+ */
+
+#pragma once
+
+// ==================== Platform Adaptations ====================
+
+#ifndef INET_CONFIG_ENABLE_IPV4
+#error Inet IPv4 configuration should be configured at build generation time
+#endif
+
+// ========== Platform-specific Configuration Overrides =========
+
+#ifndef INET_CONFIG_NUM_TCP_ENDPOINTS
+#define INET_CONFIG_NUM_TCP_ENDPOINTS 4
+#endif // INET_CONFIG_NUM_TCP_ENDPOINTS
+
+#ifndef INET_CONFIG_NUM_UDP_ENDPOINTS
+#define INET_CONFIG_NUM_UDP_ENDPOINTS 4
+#endif // INET_CONFIG_NUM_UDP_ENDPOINTS
diff --git a/src/platform/nxp/k32w/k32w1/K32W1Config.cpp b/src/platform/nxp/k32w/k32w1/K32W1Config.cpp
new file mode 100644
index 00000000000000..ee41809dcca7b9
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/K32W1Config.cpp
@@ -0,0 +1,435 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2020 Google LLC.
+ * Copyright (c) 2018 Nest Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Utilities for accessing persisted device configuration on
+ * platforms based on the NXP K32W SDK.
+ */
+/* this file behaves like a config.h, comes first */
+#include
+
+#include
+
+#include
+#include
+#include
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include
+#endif
+
+#if (defined(K32W_LOG_ENABLED) && (K32W_LOG_ENABLED > 0))
+// #include "fsl_component_log.h"
+// #include "fsl_component_log_backend_debugconsole.h"
+#endif
+#include "FreeRTOS.h"
+#include "FunctionLib.h"
+#include "NVM_Interface.h"
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+#ifndef CHIP_PLAT_NVM_SUPPORT
+#define CHIP_PLAT_NVM_SUPPORT 0
+#endif
+
+#ifndef CHIP_PLAT_NVM_STATIC_ALLOC
+#define CHIP_PLAT_NVM_STATIC_ALLOC 1
+#endif
+
+#define CHIP_CONFIG_RAM_BUFFER_SIZE 10240
+
+#ifndef NVM_ID_CHIP_CONFIG_DATA
+#define NVM_ID_CHIP_CONFIG_DATA 0xf104
+#endif
+
+#if 0
+typedef struct
+{
+ uint16_t chipConfigRamBufferLen;
+ uint8_t chipConfigRamBuffer[3072];
+} ChipConfigRamStruct_t;
+static ChipConfigRamStruct_t *chipConfigRamStruct;
+#endif
+
+#if CHIP_PLAT_NVM_STATIC_ALLOC
+static uint8_t chipConfigRamBuffer[CHIP_CONFIG_RAM_BUFFER_SIZE] = { 0 };
+#endif
+
+static ramBufferDescriptor * ramDescr;
+
+#define RAM_DESC_HEADER_SIZE (sizeof(ramDescr->ramBufferLen + ramDescr->ramBufferMaxLen))
+
+#if CHIP_PLAT_NVM_SUPPORT
+NVM_RegisterDataSet((void *) chipConfigRamBuffer, 1, sizeof(chipConfigRamBuffer), NVM_ID_CHIP_CONFIG_DATA, gNVM_MirroredInRam_c);
+#endif
+
+static rsError AddToRamStorage(ramBufferDescriptor * pBuffer, uint16_t aKey, const uint8_t * aValue, uint16_t aValueLength)
+{
+ rsError err;
+
+#if !CHIP_PLAT_NVM_STATIC_ALLOC
+ uint32_t allocSize = pBuffer->ramBufferMaxLen;
+
+ if (allocSize <= pBuffer->ramBufferLen + aValueLength)
+ {
+ while (allocSize < pBuffer->ramBufferLen + aValueLength)
+ {
+ /* Need to realocate the memory buffer, increase size by 512B until nvm data fits */
+ allocSize += 512;
+ }
+
+ pBuffer->ramBufferLen = allocSize;
+ allocSize += RAM_DESC_HEADER_SIZE;
+
+ pBuffer = (ramBufferDescriptor *) realloc((void *) pBuffer, allocSize);
+ VerifyOrExit((NULL != pBuffer), err = RS_ERROR_NO_BUFS);
+ }
+#endif
+
+ err = ramStorageSet(pBuffer, aKey, aValue, aValueLength);
+
+#if !CHIP_PLAT_NVM_STATIC_ALLOC
+exit:
+#endif
+
+ return err;
+}
+
+CHIP_ERROR K32WConfig::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ bool bLoadDataFromNvm = true;
+ uint32_t allocSize = CHIP_CONFIG_RAM_BUFFER_SIZE;
+
+ /* Initialise the Persistent Data Manager */
+#if CHIP_PLAT_NVM_SUPPORT
+ /* Init the NVM module */
+ NvModuleInit();
+#endif
+
+#if CHIP_PLAT_NVM_STATIC_ALLOC
+ ramDescr = (ramBufferDescriptor *) chipConfigRamBuffer;
+#else
+ ramDescr = (ramBufferDescriptor *) malloc(allocSize);
+ VerifyOrExit((NULL != ramDescr), err = CHIP_ERROR_NO_MEMORY);
+#endif
+
+ ramDescr->ramBufferLen = 0;
+
+ if (bLoadDataFromNvm)
+ {
+ /* Try to load the dataset in RAM */
+#if CHIP_PLAT_NVM_SUPPORT
+ NvRestoreDataSet((void *) ramDescr, 0);
+#endif
+ }
+
+ ramDescr->ramBufferMaxLen = allocSize - RAM_DESC_HEADER_SIZE;
+
+#if !CHIP_PLAT_NVM_STATIC_ALLOC
+exit:
+#endif
+
+ return err;
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValue(Key key, bool & val)
+{
+ CHIP_ERROR err;
+ bool tempVal;
+ rsError status;
+ uint16_t sizeToRead = sizeof(tempVal);
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = ramStorageGet(ramDescr, key, 0, (uint8_t *) &tempVal, &sizeToRead);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+ val = tempVal;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint32_t & val)
+{
+ CHIP_ERROR err;
+ uint32_t tempVal;
+ rsError status;
+ uint16_t sizeToRead = sizeof(tempVal);
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = ramStorageGet(ramDescr, key, 0, (uint8_t *) &tempVal, &sizeToRead);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+ val = tempVal;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValue(Key key, uint64_t & val)
+{
+ CHIP_ERROR err;
+ uint32_t tempVal;
+ rsError status;
+ uint16_t sizeToRead = sizeof(tempVal);
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = ramStorageGet(ramDescr, key, 0, (uint8_t *) &tempVal, &sizeToRead);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+ val = tempVal;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
+{
+ CHIP_ERROR err;
+ rsError status;
+ uint16_t sizeToRead = bufSize;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+
+ // We can call ramStorageGet with null pointer to only retrieve the size
+ status = ramStorageGet(ramDescr, key, 0, (uint8_t *) buf, &sizeToRead);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+ outLen = sizeToRead;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
+{
+ return ReadConfigValueStr(key, (char *) buf, bufSize, outLen);
+}
+
+CHIP_ERROR K32WConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val)
+{
+ Key key = kMinConfigKey_ChipCounter + counterIdx;
+ return ReadConfigValue(key, val);
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValue(Key key, bool val)
+{
+ CHIP_ERROR err;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = AddToRamStorage(ramDescr, key, (uint8_t *) &val, sizeof(bool));
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSaveOnIdle(ramDescr, false);
+#endif
+ // ChipLogProgress(DeviceLayer, "WriteConfigValue done");
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValueSync(Key key, bool val)
+{
+ CHIP_ERROR err;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = AddToRamStorage(ramDescr, key, (uint8_t *) &val, sizeof(bool));
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSyncSave(ramDescr, false);
+#endif
+ // ChipLogProgress(DeviceLayer, "WriteConfigValue done");
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint32_t val)
+{
+ CHIP_ERROR err;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = AddToRamStorage(ramDescr, key, (uint8_t *) &val, sizeof(uint32_t));
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSaveOnIdle(ramDescr, false);
+#endif
+ // ChipLogProgress(DeviceLayer, "WriteConfigValue done");
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValue(Key key, uint64_t val)
+{
+ CHIP_ERROR err;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = AddToRamStorage(ramDescr, key, (uint8_t *) &val, sizeof(uint64_t));
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSaveOnIdle(ramDescr, false);
+#endif
+ // ChipLogProgress(DeviceLayer, "WriteConfigValue done");
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str)
+{
+ return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0);
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
+{
+ CHIP_ERROR err;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+
+ if (str != NULL)
+ {
+ status = AddToRamStorage(ramDescr, key, (uint8_t *) str, strLen);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSaveOnIdle(ramDescr, false);
+#endif
+ }
+ else
+ {
+ err = ClearConfigValue(key);
+ SuccessOrExit(err);
+ }
+
+exit:
+ return err;
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
+{
+ return WriteConfigValueStr(key, (char *) data, dataLen);
+}
+
+CHIP_ERROR K32WConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val)
+{
+ Key key = kMinConfigKey_ChipCounter + counterIdx;
+ return WriteConfigValue(key, val);
+}
+
+CHIP_ERROR K32WConfig::ClearConfigValue(Key key)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ rsError status;
+
+ VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
+ status = ramStorageDelete(ramDescr, key, 0);
+ SuccessOrExit(err = MapRamStorageStatus(status));
+
+#if CHIP_PLAT_NVM_SUPPORT
+ NvSaveOnIdle(ramDescr, false);
+#endif
+
+exit:
+ return err;
+}
+
+bool K32WConfig::ConfigValueExists(Key key)
+{
+ rsError status;
+ uint16_t sizeToRead;
+ bool found = false;
+
+ if (ValidConfigKey(key))
+ {
+ status = ramStorageGet(ramDescr, key, 0, NULL, &sizeToRead);
+ found = (status == RS_ERROR_NONE && sizeToRead != 0);
+ }
+ return found;
+}
+
+CHIP_ERROR K32WConfig::FactoryResetConfig(void)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ FactoryResetConfigInternal(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig);
+ FactoryResetConfigInternal(kMinConfigKey_KVSKey, kMaxConfigKey_KVSKey);
+ FactoryResetConfigInternal(kMinConfigKey_KVSValue, kMaxConfigKey_KVSValue);
+
+#if CHIP_PLAT_NVM_SUPPORT
+ /* Save in flash now */
+ NvSyncSave(ramDescr, false);
+#endif
+
+ return err;
+}
+
+void K32WConfig::FactoryResetConfigInternal(Key firstKey, Key lastKey)
+{
+ for (Key key = firstKey; key <= lastKey; key++)
+ {
+ ramStorageDelete(ramDescr, key, 0);
+ }
+}
+
+CHIP_ERROR K32WConfig::MapRamStorageStatus(rsError rsStatus)
+{
+ CHIP_ERROR err;
+
+ switch (rsStatus)
+ {
+ case RS_ERROR_NONE:
+ err = CHIP_NO_ERROR;
+ break;
+ case RS_ERROR_NOT_FOUND:
+ err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+ break;
+ default:
+ err = CHIP_ERROR_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ return err;
+}
+
+bool K32WConfig::ValidConfigKey(Key key)
+{
+ // Returns true if the key is in the valid CHIP Config PDM key range.
+ if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVSValue))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void K32WConfig::RunConfigUnitTest() {}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/K32W1Config.h b/src/platform/nxp/k32w/k32w1/K32W1Config.h
new file mode 100644
index 00000000000000..a14b4d5cd10fdd
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/K32W1Config.h
@@ -0,0 +1,144 @@
+/*
+ *
+ * Copyright (c) 2020-2022 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Utilities for accessing persisted device configuration on
+ * platforms based on the K32W1 SDK.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+#include "FreeRTOS.h"
+#include "NVM_Interface.h"
+
+#include "ram_storage.h"
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+constexpr inline uint16_t K32WConfigKey(uint8_t chipId, uint8_t nvmId)
+{
+ return static_cast(chipId) << 8 | nvmId;
+}
+
+/**
+ * This implementation uses the NVM component as the underlying storage layer.
+ *
+ * NOTE: This class is designed to be mixed-in to the concrete subclass of the
+ * GenericConfigurationManagerImpl<> template. When used this way, the class
+ * naturally provides implementations for the delegated members referenced by
+ * the template class (e.g. the ReadConfigValue() method).
+ */
+class K32WConfig
+{
+public:
+ // Category ids used by the CHIP Device Layer
+ static constexpr uint8_t kFileId_ChipFactory = 0x01; /**< Category containing persistent config values set at
+ * manufacturing time. Retained during factory reset. */
+ static constexpr uint8_t kFileId_ChipConfig = 0x02; /**< Catyegory containing dynamic config values set at runtime.
+ * Cleared during factory reset. */
+ static constexpr uint8_t kFileId_ChipCounter = 0x03; /**< Category containing dynamic counter values set at runtime.
+ * Retained during factory reset. */
+ static constexpr uint8_t kFileId_KVSKey = 0x04; /**< Category containing KVS set at runtime.
+ * Cleared during factory reset. */
+ static constexpr uint8_t kFileId_KVSValue = 0x05; /**< Category containing KVS values set at runtime.
+ * Cleared during factory reset. */
+
+ using Key = uint16_t;
+
+ // Key definitions for well-known configuration values.
+ // Factory config keys
+ static constexpr Key kConfigKey_SerialNum = K32WConfigKey(kFileId_ChipFactory, 0x00);
+ static constexpr Key kConfigKey_MfrDeviceId = K32WConfigKey(kFileId_ChipFactory, 0x01);
+ static constexpr Key kConfigKey_MfrDeviceCert = K32WConfigKey(kFileId_ChipFactory, 0x02);
+ static constexpr Key kConfigKey_MfrDevicePrivateKey = K32WConfigKey(kFileId_ChipFactory, 0x03);
+ static constexpr Key kConfigKey_ManufacturingDate = K32WConfigKey(kFileId_ChipFactory, 0x04);
+ static constexpr Key kConfigKey_SetupPinCode = K32WConfigKey(kFileId_ChipFactory, 0x05);
+ static constexpr Key kConfigKey_MfrDeviceICACerts = K32WConfigKey(kFileId_ChipFactory, 0x06);
+ static constexpr Key kConfigKey_HardwareVersion = K32WConfigKey(kFileId_ChipFactory, 0x07);
+ static constexpr Key kConfigKey_SetupDiscriminator = K32WConfigKey(kFileId_ChipFactory, 0x08);
+ static constexpr Key kConfigKey_Spake2pIterationCount = K32WConfigKey(kFileId_ChipFactory, 0x09);
+ static constexpr Key kConfigKey_Spake2pSalt = K32WConfigKey(kFileId_ChipFactory, 0x0A);
+ static constexpr Key kConfigKey_Spake2pVerifier = K32WConfigKey(kFileId_ChipFactory, 0x0B);
+
+ // CHIP Config Keys
+ static constexpr Key kConfigKey_ServiceConfig = K32WConfigKey(kFileId_ChipConfig, 0x01);
+ static constexpr Key kConfigKey_PairedAccountId = K32WConfigKey(kFileId_ChipConfig, 0x02);
+ static constexpr Key kConfigKey_ServiceId = K32WConfigKey(kFileId_ChipConfig, 0x03);
+ static constexpr Key kConfigKey_LastUsedEpochKeyId = K32WConfigKey(kFileId_ChipConfig, 0x05);
+ static constexpr Key kConfigKey_FailSafeArmed = K32WConfigKey(kFileId_ChipConfig, 0x06);
+ static constexpr Key kConfigKey_RegulatoryLocation = K32WConfigKey(kFileId_ChipConfig, 0x07);
+ static constexpr Key kConfigKey_CountryCode = K32WConfigKey(kFileId_ChipConfig, 0x08);
+ static constexpr Key kConfigKey_UniqueId = K32WConfigKey(kFileId_ChipConfig, 0x0A);
+ static constexpr Key kConfigKey_SoftwareVersion = K32WConfigKey(kFileId_ChipConfig, 0x0B);
+
+ // CHIP Counter Keys
+ static constexpr Key kCounterKey_RebootCount = K32WConfigKey(kFileId_ChipCounter, 0x00);
+ static constexpr Key kCounterKey_UpTime = K32WConfigKey(kFileId_ChipCounter, 0x01);
+ static constexpr Key kCounterKey_TotalOperationalHours = K32WConfigKey(kFileId_ChipCounter, 0x02);
+ static constexpr Key kCounterKey_BootReason = K32WConfigKey(kFileId_ChipCounter, 0x03);
+
+ // Set key id limits for each group.
+ static constexpr Key kMinConfigKey_ChipFactory = K32WConfigKey(kFileId_ChipFactory, 0x00);
+ static constexpr Key kMaxConfigKey_ChipFactory = K32WConfigKey(kFileId_ChipFactory, 0xFF);
+ static constexpr Key kMinConfigKey_ChipConfig = K32WConfigKey(kFileId_ChipConfig, 0x00);
+ static constexpr Key kMaxConfigKey_ChipConfig = K32WConfigKey(kFileId_ChipConfig, 0xFF);
+ static constexpr Key kMinConfigKey_ChipCounter = K32WConfigKey(kFileId_ChipCounter, 0x00);
+ static constexpr Key kMaxConfigKey_ChipCounter = K32WConfigKey(kFileId_ChipCounter, 0xFF); // Allows 32 Counters to be created.
+ static constexpr Key kMinConfigKey_KVSKey = K32WConfigKey(kFileId_KVSKey, 0x00);
+ static constexpr Key kMaxConfigKey_KVSKey = K32WConfigKey(kFileId_KVSKey, 0xFF);
+ static constexpr Key kMinConfigKey_KVSValue = K32WConfigKey(kFileId_KVSValue, 0x00);
+ static constexpr Key kMaxConfigKey_KVSValue = K32WConfigKey(kFileId_KVSValue, 0xFF);
+
+ static CHIP_ERROR Init(void);
+
+ // Configuration methods used by the GenericConfigurationManagerImpl<> template.
+ static CHIP_ERROR ReadConfigValue(Key key, bool & val);
+ static CHIP_ERROR ReadConfigValue(Key key, uint32_t & val);
+ static CHIP_ERROR ReadConfigValue(Key key, uint64_t & val);
+ static CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen);
+ static CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen);
+ static CHIP_ERROR ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val);
+ static CHIP_ERROR WriteConfigValue(Key key, bool val);
+ static CHIP_ERROR WriteConfigValueSync(Key key, bool val);
+ static CHIP_ERROR WriteConfigValue(Key key, uint32_t val);
+ static CHIP_ERROR WriteConfigValue(Key key, uint64_t val);
+ static CHIP_ERROR WriteConfigValueStr(Key key, const char * str);
+ static CHIP_ERROR WriteConfigValueStr(Key key, const char * str, size_t strLen);
+ static CHIP_ERROR WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen);
+ static CHIP_ERROR WriteConfigValueCounter(uint8_t counterIdx, uint32_t val);
+ static CHIP_ERROR ClearConfigValue(Key key);
+ static bool ConfigValueExists(Key key);
+ static CHIP_ERROR FactoryResetConfig(void);
+ static bool ValidConfigKey(Key key);
+
+ static void RunConfigUnitTest(void);
+
+private:
+ static CHIP_ERROR MapRamStorageStatus(rsError rsStatus);
+ static void FactoryResetConfigInternal(Key firstKey, Key lastKey);
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.cpp b/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.cpp
new file mode 100644
index 00000000000000..18c1ff41a79963
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "K32W1PersistentStorageOpKeystore.h"
+
+#include "sss_crypto.h"
+
+namespace chip {
+
+using namespace chip::Crypto;
+
+CHIP_ERROR P256KeypairSSS::Initialize(Crypto::ECPKeyTarget key_target)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ size_t keyBitsLen = kP256_PrivateKey_Length * 8;
+ size_t keySize = SSS_ECP_KEY_SZ(kP256_PrivateKey_Length);
+
+ Clear();
+
+ VerifyOrReturnError(sss_sscp_key_object_init(&mKeyObj, &g_keyStore) == kStatus_SSS_Success, CHIP_ERROR_INTERNAL);
+
+ VerifyOrReturnError(sss_sscp_key_object_allocate_handle(
+ &mKeyObj, 0x0u, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P, 3 * kP256_PrivateKey_Length,
+ SSS_KEYPROP_OPERATION_KDF | SSS_KEYPROP_OPERATION_ASYM) == kStatus_SSS_Success,
+ error = CHIP_ERROR_INTERNAL);
+
+ VerifyOrExit(SSS_ECP_GENERATE_KEY(&mKeyObj, keyBitsLen) == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL);
+
+ // The first byte of the public key is the uncompressed marker
+ Uint8::to_uchar(mPublicKey)[0] = 0x04;
+
+ // Extract public key, write from the second byte
+ VerifyOrExit(SSS_KEY_STORE_GET_PUBKEY(&mKeyObj, Uint8::to_uchar(mPublicKey) + 1, &keySize, &keyBitsLen) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+
+ mInitialized = true;
+
+exit:
+ if (mInitialized != true)
+ (void) SSS_KEY_OBJ_FREE(&mKeyObj);
+
+ return error;
+}
+
+CHIP_ERROR P256KeypairSSS::ExportBlob(P256SerializedKeypairSSS & output) const
+{
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+
+ size_t keyBlobLen = output.Capacity();
+ VerifyOrReturnError(sss_sscp_key_store_export_key(&g_keyStore, &mKeyObj, output.Bytes(), &keyBlobLen,
+ kSSS_blobType_ELKE_blob) == kStatus_SSS_Success,
+ CHIP_ERROR_INTERNAL);
+ output.SetLength(keyBlobLen);
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR P256KeypairSSS::ImportBlob(P256SerializedKeypairSSS & input)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ if (false == mInitialized)
+ {
+ VerifyOrExit((sss_sscp_key_object_init(&mKeyObj, &g_keyStore) == kStatus_SSS_Success), error = CHIP_ERROR_INTERNAL);
+
+ /* Allocate key handle */
+ VerifyOrExit(
+ (sss_sscp_key_object_allocate_handle(&mKeyObj, 0x0u, kSSS_KeyPart_Pair, kSSS_CipherType_EC_NIST_P,
+ 3 * kP256_PrivateKey_Length, SSS_KEYPROP_OPERATION_ASYM) == kStatus_SSS_Success),
+ error = CHIP_ERROR_INTERNAL);
+ }
+
+ VerifyOrExit((sss_sscp_key_store_import_key(&g_keyStore, &mKeyObj, input.Bytes(), input.Length(), kP256_PrivateKey_Length * 8,
+ kSSS_blobType_ELKE_blob) == kStatus_SSS_Success),
+ error = CHIP_ERROR_INTERNAL);
+
+ mInitialized = true;
+
+exit:
+ return error;
+}
+
+CHIP_ERROR P256KeypairSSS::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ sss_sscp_asymmetric_t asyc;
+ size_t signatureSize = kP256_ECDSA_Signature_Length_Raw;
+
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+ VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
+
+ uint8_t digest[kSHA256_Hash_Length];
+ memset(&digest[0], 0, sizeof(digest));
+ ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
+
+ VerifyOrExit((sss_sscp_asymmetric_context_init(&asyc, &g_sssSession, &mKeyObj, kAlgorithm_SSS_ECDSA_SHA256, kMode_SSS_Sign) ==
+ kStatus_SSS_Success),
+ error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit((sss_sscp_asymmetric_sign_digest(&asyc, digest, kP256_FE_Length, out_signature.Bytes(), &signatureSize) ==
+ kStatus_SSS_Success),
+ error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
+
+exit:
+ (void) sss_sscp_asymmetric_context_free(&asyc);
+ return error;
+}
+
+CHIP_ERROR P256KeypairSSS::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+ VerifyOrReturnError(mInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+
+ MutableByteSpan csr(out_csr, csr_length);
+ CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+ csr_length = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+ return err;
+}
+
+void P256KeypairSSS::Clear()
+{
+ if (mInitialized)
+ {
+ (void) SSS_KEY_OBJ_FREE(&mKeyObj);
+ mInitialized = false;
+ }
+}
+
+P256KeypairSSS::~P256KeypairSSS()
+{
+ Clear();
+}
+
+bool K32W1PersistentStorageOpKeystore::HasOpKeypairForFabric(FabricIndex fabricIndex) const
+{
+ VerifyOrReturnError(mStorage != nullptr, false);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
+
+ // If there was a pending keypair, then there's really a usable key
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
+ {
+ return true;
+ }
+
+ P256SerializedKeypairSSS buf;
+
+ uint16_t keySize = static_cast(buf.Capacity());
+ CHIP_ERROR err =
+ mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName(), buf.Bytes(), keySize);
+
+ return (err == CHIP_NO_ERROR && (keySize == SSS_KEY_PAIR_BLOB_SIZE));
+}
+
+CHIP_ERROR K32W1PersistentStorageOpKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex,
+ MutableByteSpan & outCertificateSigningRequest)
+{
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+ // If a key is pending, we cannot generate for a different fabric index until we commit or revert.
+ if ((mPendingFabricIndex != kUndefinedFabricIndex) && (fabricIndex != mPendingFabricIndex))
+ {
+ return CHIP_ERROR_INVALID_FABRIC_INDEX;
+ }
+ VerifyOrReturnError(outCertificateSigningRequest.size() >= Crypto::kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);
+
+ // Replace previous pending keypair, if any was previously allocated
+ ResetPendingKey();
+
+ mPendingKeypair = Platform::New();
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_NO_MEMORY);
+
+ mPendingKeypair->Initialize(Crypto::ECPKeyTarget::ECDSA);
+ size_t csrLength = outCertificateSigningRequest.size();
+ CHIP_ERROR err = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
+ if (err != CHIP_NO_ERROR)
+ {
+ ResetPendingKey();
+ return err;
+ }
+
+ outCertificateSigningRequest.reduce_size(csrLength);
+ mPendingFabricIndex = fabricIndex;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR K32W1PersistentStorageOpKeystore::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
+ const Crypto::P256PublicKey & nocPublicKey)
+{
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Validate public key being activated matches last generated pending keypair
+ VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);
+
+ mIsPendingKeypairActive = true;
+
+ return CHIP_NO_ERROR;
+}
+CHIP_ERROR K32W1PersistentStorageOpKeystore::CommitOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);
+
+ P256SerializedKeypairSSS tmpKeyBlob;
+ uint16_t keyBlobLen = tmpKeyBlob.Capacity();
+
+ mPendingKeypair->ExportBlob(tmpKeyBlob);
+ ReturnErrorOnFailure(
+ mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName(), tmpKeyBlob.Bytes(), keyBlobLen));
+
+ // If we got here, we succeeded and can reset the pending key: next `SignWithOpKeypair` will use the stored key.
+ ResetPendingKey();
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR K32W1PersistentStorageOpKeystore::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
+{
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ // Remove pending state if matching
+ if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
+ {
+ RevertPendingKeypair();
+ }
+
+ CHIP_ERROR err = mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName());
+ if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
+ {
+ err = CHIP_ERROR_INVALID_FABRIC_INDEX;
+ }
+
+ return err;
+}
+
+void K32W1PersistentStorageOpKeystore::RevertPendingKeypair()
+{
+ VerifyOrReturn(mStorage != nullptr);
+
+ // Just reset the pending key, we never stored anything
+ ResetPendingKey();
+}
+
+CHIP_ERROR K32W1PersistentStorageOpKeystore::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+ Crypto::P256ECDSASignature & outSignature) const
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+ if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
+ {
+ VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
+ // We have an override key: sign with it!
+ return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+ }
+
+ P256SerializedKeypairSSS keyBlob;
+ uint16_t keyBlobLen = keyBlob.Capacity();
+ keyBlob.SetLength(keyBlobLen);
+
+ if (fabricIndex != mCachedFabricIndex)
+ {
+ error =
+ mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::FabricOpKey(fabricIndex).KeyName(), keyBlob.Bytes(), keyBlobLen);
+ keyBlob.SetLength(keyBlobLen);
+
+ if (error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
+ {
+ error = CHIP_ERROR_INVALID_FABRIC_INDEX;
+ }
+ ReturnErrorOnFailure(error);
+
+ if (nullptr == mCachedKeypair)
+ {
+ mCachedKeypair = Platform::New();
+ VerifyOrReturnError(mCachedKeypair != nullptr, CHIP_ERROR_NO_MEMORY);
+ }
+
+ VerifyOrReturnError(mCachedKeypair->ImportBlob(keyBlob) == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);
+ }
+
+ return mCachedKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+}
+
+Crypto::P256Keypair * K32W1PersistentStorageOpKeystore::AllocateEphemeralKeypairForCASE()
+{
+ // DO NOT CUT AND PASTE without considering the ReleaseEphemeralKeypair().
+ // If allocating a derived class, then `ReleaseEphemeralKeypair` MUST
+ // de-allocate the derived class after up-casting the base class pointer.
+ return Platform::New();
+}
+
+void K32W1PersistentStorageOpKeystore::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
+{
+ // DO NOT CUT AND PASTE without considering the AllocateEphemeralKeypairForCASE().
+ // This must delete the same concrete class as allocated in `AllocateEphemeralKeypairForCASE`
+ Platform::Delete(keypair);
+}
+
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.h b/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.h
new file mode 100644
index 00000000000000..6402c235527ff0
--- /dev/null
+++ b/src/platform/nxp/k32w/k32w1/K32W1PersistentStorageOpKeystore.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2022 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Platform-specific implementation of the persistent operational keystore for K32W1
+ */
+
+#pragma once
+
+#include
+#include