From 1a27e2bd8e5f5796af3199234a09fb120e54a9c1 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Fri, 11 Nov 2022 14:24:45 -0600 Subject: [PATCH] samples: mimxrt595: Add Deep power down sample Add a sample to put the part into Deep power down mode by setting the state to PM_STATE_SOFT_OFF. Wakup the part using an RTC alarm. Signed-off-by: Mahesh Mahadevan --- .../system_off/CMakeLists.txt | 9 ++ .../mimxrt595_evk_cm33/system_off/Kconfig | 7 + .../mimxrt595_evk_cm33/system_off/README.rst | 142 ++++++++++++++++++ .../mimxrt595_evk_cm33/system_off/app.overlay | 10 ++ .../mimxrt595_evk_cm33/system_off/prj.conf | 14 ++ .../mimxrt595_evk_cm33/system_off/sample.yaml | 13 ++ .../mimxrt595_evk_cm33/system_off/src/main.c | 68 +++++++++ 7 files changed, 263 insertions(+) create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/CMakeLists.txt create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/Kconfig create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/README.rst create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/app.overlay create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/prj.conf create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml create mode 100644 samples/boards/mimxrt595_evk_cm33/system_off/src/main.c diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/CMakeLists.txt b/samples/boards/mimxrt595_evk_cm33/system_off/CMakeLists.txt new file mode 100644 index 00000000000..44e9ad4d6cd --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2022, NXP +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(mimxrt595_evk_cm33_system_off) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/Kconfig b/samples/boards/mimxrt595_evk_cm33/system_off/Kconfig new file mode 100644 index 00000000000..758391f60c0 --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/Kconfig @@ -0,0 +1,7 @@ +# Copyright 2022, NXP +# +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "MIMXRT595_EVK_CM33 SYSTEM_OFF demo" + +source "Kconfig.zephyr" diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/README.rst b/samples/boards/mimxrt595_evk_cm33/system_off/README.rst new file mode 100644 index 00000000000..2acff78aefd --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/README.rst @@ -0,0 +1,142 @@ +.. _mimxrt595_evk-system-off-sample: + +RT595 System Off demo +##################### + +Overview +******** + +This sample can be used for basic power measurement and as an example of +soft off on NXP i.MX RT platforms. The functional behavior is: + +* Busy-wait for 2 seconds +* Turn the system off after enabling wakeup through RTC and set alarm + 10 seconds in the future to wake up the processor + +Requirements +************ + +This application uses MIMXRT595-EVK for the demo. + +Building, Flashing and Running +****************************** + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/mimxrt595_evk_cm33/system_off + :board: mimxrt595_evk_cm33 + :goals: build flash + :compact: + +Running: + +1. Open UART terminal. +2. Power Cycle Device. +3. Device will turn on and idle for 2 seconds +4. Device will turn itself off using deep power down mode. RTC alarm + will wake device and restart the application from a warm reset. + +Sample Output +================= +MIMXRT595-EVK core output +-------------------------- + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.2.0-1045-g07228f716c78 *** + + mimxrt595_evk_cm33 system off demo + RTC Alarm set for 10 seconds to wake from soft-off. + Entering system off + +OTP Fuse setting to wake from Deep Power Down and reset flash +############################################################# + +Background +********** + +This sample will not resume the application after waking from Deep Power +Down (DPD) mode on an EVK with default settings. The reason is that the +flash is not normally reset when waking from DPD. This sample +eXecutes-In-Place (XIP) from the external flash. When the MCU wakes from +DPD, it wakes through the reset flow. But if the external flash is not +reset, the MCU and flash are no longer in sync, and the MCU cannot XIP. +In this default state, one can confirm the RTC is waking the MCU from +DPD because the MCU will set the PMIC_MODE pins to 0b00 requesting the +PMIC to enter the default boot mode, and the PMIC will enable the +regulator driving the VDDCORE rail at 1.0V. However, the MCU will not be +able to XIP from the flash to resume. One can press the Reset button in +this state to restart the app. + +To wake from DPD and resume XIP from the flash, the MCU needs to be +configured to reset the external flash. This can be done by programming +the One-Time-Programmable (OTP) fuses in the MCU. The steps below detail +how program the OTP BOOT_CFG1 fuses to use GPIO pin PIO4_5 as the flash +reset. This fuse setting instructs the ROM bootloader to toggle PIO4_5 +when resetting the flash. Note that the MIMXRT595-EVK board is designed +to have PIO4_5 drive the octal flash reset pin on FlexSPI0. Other boards +using this MCU may use a different GPIO pin, and the setting in the OTP +fuses must match the GPIO pin connected to reset. Before programming +fuses, it is best to write the OTP shadow registers first and confirm +the operation. Then program the OTP fuses after confirming the correct +settings. For more details on OTP fuses and shadow registers, refer to +the Reference Manual for this MCU, and the OTP Fuse Map spreadsheet +included as an attachment in the Reference Manual PDF. + +Tools needed +************ +These steps use the blhost tool that runs on a host computer running +Linux, Windows, or MacOS. Download blhost, find the appropriate blhost +executable for your host OS, and use the command-line steps below to +program the OTP fuses. To download, go to https://www.nxp.com/mcuboot, +and find the Blhost package under Downloads. + +Steps to program OTP fuses on MIMXRT595-EVK +******************************************* +These steps detail using USB as the interface between blhost and the +ROM bootloader. UART is another option, for more details see the +blhost documentation and the Boot ROM chapter in the MCU Reference +Manual. + + 1. Power the EVK and connect USB J38 to host computer. J38 is for the + USB peripheral of the MCU, and will also power the EVK. + + 2. Set the DIP switches of SW7 to On-Off-On (123) to boot in ISP USB + HID mode. + + 3. Press the Reset button SW3 to boot in ISP mode. The EVK should + enumerate as a USB HID device in the host computer. + + 4. This command confirms the current settings of BOOT_CFG1 fuses: + blhost -u 0x1fc9,0x0023 -- efuse-read-once 0x61 + + 5. This command programs BOOT_CFG1 to enable the flash reset pin using + PIO4_5: + blhost -u 0x1fc9,0x0023 -- efuse-program-once 0x61 0x164000 + + 6. This command confirms the programmed fuses in BOOT_CFG1: + blhost -u 0x1fc9,0x0023 -- efuse-read-once 0x61 + + 7. Set the DIP switches of SW7 to Off-Off-On (123) to boot from the + external flash on FlexSPI0. + + 8. Press the Reset button SW3 to boot from flash and run the app. + +Expected results from blhost +**************************** + +>blhost -u 0x1fc9,0x0023 -- efuse-read-once 0x61 +Inject command 'efuse-read-once' +Response status = 0 (0x0) Success. +Response word 1 = 4 (0x4) +Response word 2 = 0 (0x0) + +>blhost -u 0x1fc9,0x0023 -- efuse-program-once 0x61 0x164000 +Inject command 'efuse-program-once' +Successful generic response to command 'efuse-program-once' +Response status = 0 (0x0) Success. + +>blhost -u 0x1fc9,0x0023 -- efuse-read-once 0x61 +Inject command 'efuse-read-once' +Response status = 0 (0x0) Success. +Response word 1 = 4 (0x4) +Response word 2 = 1458176 (0x164000) diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/app.overlay b/samples/boards/mimxrt595_evk_cm33/system_off/app.overlay new file mode 100644 index 00000000000..dc0592b275e --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/app.overlay @@ -0,0 +1,10 @@ +/* + * Copyright 2022, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&rtc { + status = "okay"; + wakeup-source; +}; diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/prj.conf b/samples/boards/mimxrt595_evk_cm33/system_off/prj.conf new file mode 100644 index 00000000000..092a01da88d --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/prj.conf @@ -0,0 +1,14 @@ +# +# Copyright 2022, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_PM=y + +# Turn on Device Level Power Management as we wish +# to reconfigure the FlexSPI pins for power savings +# when transitioning the SoC to Deep Low Power modes. +CONFIG_PM_DEVICE=y + +# Enable the RTC +CONFIG_COUNTER=y diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml b/samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml new file mode 100644 index 00000000000..58c906414b3 --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml @@ -0,0 +1,13 @@ +# +# Copyright 2022, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +sample: + name: Deep Power Down State Sample for mimxrt595_evk +common: + tags: power +tests: + sample.boards.mimxrt595_evk_cm33.system_off: + build_only: true + platform_allow: mimxrt595_evk_cm33 diff --git a/samples/boards/mimxrt595_evk_cm33/system_off/src/main.c b/samples/boards/mimxrt595_evk_cm33/system_off/src/main.c new file mode 100644 index 00000000000..01bb11b5b0f --- /dev/null +++ b/samples/boards/mimxrt595_evk_cm33/system_off/src/main.c @@ -0,0 +1,68 @@ +/* + * Copyright 2022, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BUSY_WAIT_S 2U +#define SLEEP_S 2U +#define SOFT_OFF_S 10U + +#define RTC_NODE DT_NODELABEL(rtc) +#if !DT_NODE_HAS_STATUS(RTC_NODE, okay) +#error "Unsupported board: rtc node is not enabled" +#endif + +#define RTC_CHANNEL_ID 0 + +static const struct device *const rtc_dev = DEVICE_DT_GET(RTC_NODE); + +void main(void) +{ + int ret; + + printk("\n%s system off demo\n", CONFIG_BOARD); + + uint32_t sleep_ticks = counter_us_to_ticks(rtc_dev, SOFT_OFF_S * 1000ULL * 1000ULL); + + counter_start(rtc_dev); + + if (sleep_ticks == 0) { + /* counter_us_to_ticks will round down the number of ticks to the nearest int. */ + /* Ensure at least one tick is used in the RTC */ + sleep_ticks++; + } + const struct counter_alarm_cfg alarm_cfg = { + .ticks = sleep_ticks, + .flags = 0, + }; + + ret = counter_set_channel_alarm(rtc_dev, RTC_CHANNEL_ID, &alarm_cfg); + if (ret != 0) { + printk("Could not rtc alarm.\n"); + return; + } + printk("RTC Alarm set for %llu seconds to wake from soft-off.\n", + counter_ticks_to_us(rtc_dev, alarm_cfg.ticks) / (1000ULL * 1000ULL)); + printk("Entering system off"); + + pm_state_force(0u, &(struct pm_state_info){ PM_STATE_SOFT_OFF, 0, 0 }); + + /* Now we need to go sleep. This will let the idle thread runs and + * the pm subsystem will use the forced state. + */ + k_sleep(K_SECONDS(SLEEP_S)); + + printk("ERROR: System off failed\n"); + while (true) { + /* spin to avoid fall-off behavior */ + } +}