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 <mahesh.mahadevan@nxp.com>
This commit is contained in:
parent
3f38b011c3
commit
1a27e2bd8e
7 changed files with 263 additions and 0 deletions
|
@ -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)
|
7
samples/boards/mimxrt595_evk_cm33/system_off/Kconfig
Normal file
7
samples/boards/mimxrt595_evk_cm33/system_off/Kconfig
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright 2022, NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mainmenu "MIMXRT595_EVK_CM33 SYSTEM_OFF demo"
|
||||
|
||||
source "Kconfig.zephyr"
|
142
samples/boards/mimxrt595_evk_cm33/system_off/README.rst
Normal file
142
samples/boards/mimxrt595_evk_cm33/system_off/README.rst
Normal file
|
@ -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)
|
10
samples/boards/mimxrt595_evk_cm33/system_off/app.overlay
Normal file
10
samples/boards/mimxrt595_evk_cm33/system_off/app.overlay
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright 2022, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&rtc {
|
||||
status = "okay";
|
||||
wakeup-source;
|
||||
};
|
14
samples/boards/mimxrt595_evk_cm33/system_off/prj.conf
Normal file
14
samples/boards/mimxrt595_evk_cm33/system_off/prj.conf
Normal file
|
@ -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
|
13
samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml
Normal file
13
samples/boards/mimxrt595_evk_cm33/system_off/sample.yaml
Normal file
|
@ -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
|
68
samples/boards/mimxrt595_evk_cm33/system_off/src/main.c
Normal file
68
samples/boards/mimxrt595_evk_cm33/system_off/src/main.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2022, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/counter.h>
|
||||
#include <zephyr/pm/pm.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
|
||||
#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 */
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue