I am using a custom board with a nRF52832 (inside a BMD-300 from ublox) that I can't seem to get to a lower power state. The lowest I've been able to get is 2.2mA even using bare-bones firmware (see below for code). Can anyone shine some light on why this is? From what I can tell, I've turned all of the important settings off in my prj.config and my code is doing barely anything.
My custom board is connected to the "Debug Out" connector on the nRF52 DK. I'm using this to power the custom board with the DK 5V out. My multimeter is connected between the 5V out and the input pin on my custom board.
I have tried power cycling the device in case it's stuck in debug mode.
In addition to the code, I've attached both my prj.conf and my .dts file.
I am using NCS 2.1.2 and Zephyr 3.1.99.
Please let me know if I can provide more information that may be helpful in tracking this down.
#include <zephyr.h> #include <logging/log.h> #include <stdio.h> #include <zephyr/drivers/uart.h> #include <zephyr/pm/pm.h> #include <zephyr/pm/policy.h> #include <zephyr/pm/state.h> #include <zephyr/pm/device.h> #include <device.h> #include <drivers/gpio.h> #include <hal/nrf_gpio.h> #include <hal/nrf_clock.h> #include <hal/nrf_power.h> #define LOG_MODULE_NAME stylus_main LOG_MODULE_REGISTER(LOG_MODULE_NAME); // Is it necessary to disable this in order to manually go to sleep? Examples vary. static int disable_ds_1(const struct device *dev) { ARG_UNUSED(dev); pm_policy_state_lock_get(PM_STATE_SOFT_OFF, PM_ALL_SUBSTATES); return 0; } SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0); void main(void) { k_usleep(1); k_sleep(K_MSEC(10)); nrf_clock_lf_src_set(NRF_CLOCK, NRF_CLOCK_LFCLK_RC); nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART); // This seems to have the same effect as pm_state_force below on the current. // nrf_power_system_off(NRF_POWER); bool success = pm_state_force(0, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}); k_sleep(K_SECONDS(2U)); if (success) { // We successfully went to sleep // This is never called because we're asleep - that's expected. // blink_with_colors(1000, 0, 0, 0, 250, 5); } else { printf("Failed to go to sleep."); } // Should never be reached while (1) { } }
Here is my prj.conf:
# Bluetooth CONFIG_BT=n # CONFIG_BT_PERIPHERAL=n # CONFIG_BT_DEVICE_NAME="Stylus" # CONFIG_BT_DEVICE_APPEARANCE=0 # CONFIG_BT_MAX_CONN=1 # CONFIG_BT_LL_SOFTDEVICE=n CONFIG_GPIO=n # CONFIG_DK_LIBRARY=n CONFIG_ASSERT=n # DFU CONFIG_MCUMGR=n # CONFIG_MCUMGR_CMD_IMG_MGMT=n # CONFIG_MCUMGR_CMD_OS_MGMT=n # CONFIG_BT_L2CAP_TX_MTU=253 # CONFIG_BT_BUF_ACL_RX_SIZE=256 # CONFIG_MCUMGR_SMP_BT=n # CONFIG_MCUMGR_SMP_BT_AUTHEN=n CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1024 CONFIG_INIT_STACKS=n CONFIG_THREAD_STACK_INFO=n CONFIG_MAIN_STACK_SIZE=1024 # CONFIG_BT_RX_STACK_SIZE=2048 CONFIG_ADC=n # CONFIG_ADC_NRFX_SAADC=n # CONFIG_BT_BUF_ACL_TX_COUNT=74 # CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6 # CONFIG_BT_PERIPHERAL_PREF_MAX_INT=20 # CONFIG_STDOUT_CONSOLE=n CONFIG_I2C=n CONFIG_SENSOR=n CONFIG_BMI270=n CONFIG_BMM150=n CONFIG_BMM150_PRESET_LOW_POWER=y # CONFIG_BMM150_PRESET_HIGH_ACCURACY=n # Storage CONFIG_FLASH=n CONFIG_FLASH_PAGE_LAYOUT=n CONFIG_NVS=n # CONFIG_NVS_LOG_LEVEL_DBG=n CONFIG_REBOOT=n CONFIG_MPU_ALLOW_FLASH_WRITE=n # Comment this out if you need to print floats # CONFIG_NEWLIB_LIBC=n CONFIG_CBPRINTF_FP_SUPPORT=n CONFIG_PRINTK=n CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n # MCUBoot CONFIG_BOOTLOADER_MCUBOOT=n # Debugging CONFIG_UART_CONSOLE=n # CONFIG_RTT_CONSOLE=n CONFIG_USE_SEGGER_RTT=n CONFIG_LOG=n CONFIG_LOG_DEFAULT_LEVEL=0 # CONFIG_DEBUG_OPTIMIZATIONS=n # CONFIG_DEBUG_THREAD_INFO=n CONFIG_SENSOR_LOG_LEVEL_DBG=n CONFIG_SERIAL=n CONFIG_RTT_CONSOLE=n # Power Management CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_PM_DEVICE_POWER_DOMAIN=y # Test CONFIG_CONSOLE=n CONFIG_SPI_NOR_IDLE_IN_DPD=y CONFIG_SPI=n CONFIG_TICKLESS_KERNEL=y CONFIG_ADC_NRFX_SAADC=n # Minimize boot time CONFIG_BOOT_DELAY=0 # Disable unused hardware CONFIG_NFCT_PINS_AS_GPIOS=y CONFIG_PWM=n
And here is my .dts file:
/dts-v1/; #include <nordic/nrf52832_qfaa.dtsi> #include "mydevice-pinctrl.dtsi" / { model = "MyDevice"; compatible = "nordic,mydevice"; chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; }; buttons { compatible = "gpio-keys"; capbutton: cap_button { //gpios = <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; // Incorrect, but used for testing charger gpios = <&gpio0 24 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; // Correct label = "Button on the top of the stylus cap"; }; battcharge: batt_charge { //gpios = <&gpio0 24 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; // Incorrect, but used for testing charger gpios = <&gpio0 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; // Correct label = "Charge pin connected to the battery"; }; battfault: batt_fault { gpios = <&gpio0 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; label = "Fault pin connected to the battery"; }; dockstatus: dock_status { gpios = <&gpio0 30 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; label = "Hall effect sensor output that determines if the device is docked on the base station"; }; }; // These pins are not used but can't be left in a floating electrical state. // If they are, the device will leak current. extras { compatible = "gpio-keys"; // BMI270 imu_int1: imu_int1 { gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "IMU Interrupt 1"; }; imu_int2: imu_int2 { gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "IMU Interrupt 2"; }; // End BMI 270 // BMM150 mag_drdy: mag_drdy { gpios = <&gpio0 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Magnetometer Data Ready"; }; mag_int: mag_int { gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Magnetometer Interrupt"; }; }; aliases { capbutton = &capbutton; battcharge = &battcharge; battfault = &battfault; dockstatus = &dockstatus; backupstorage = &backupstorage; imu-int1 = &imu_int1; imu-int2 = &imu_int2; mag-drdy = &mag_drdy; mag-int = &mag_int; }; }; &adc { status = "disabled"; #address-cells = <1>; #size-cells = <0>; // Force Sensor // NOTE: If any issues are encountered with the force sensor, note this changed from AIN5 (P0.29) to AIN0 (P0.02) channel@0 { reg = <0>; zephyr,gain = "ADC_GAIN_1_5"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>; zephyr,input-positive = <NRF_SAADC_AIN0>; status = "disabled"; }; // Battery VBatt Divided channel@1 { reg = <1>; zephyr,gain = "ADC_GAIN_1_5"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>; zephyr,input-positive = <NRF_SAADC_AIN2>; status = "disabled"; }; }; &gpiote { status = "disabled"; }; &gpio0 { status = "disabled"; }; &uart0 { status = "disabled"; compatible = "nordic,nrf-uarte"; current-speed = <115200>; pinctrl-0 = <&uart0_default>; pinctrl-1 = <&uart0_sleep>; pinctrl-names = "default", "sleep"; }; &i2c0 { compatible = "nordic,nrf-twi"; status = "disabled"; pinctrl-0 = <&i2c0_default>; pinctrl-1 = <&i2c0_sleep>; pinctrl-names = "default", "sleep"; clock-frequency = <400000>; bmi270: bmi270@68 { compatible = "bosch,bmi270"; reg = <0x68>; label = "BMI270"; status = "disabled"; }; bmm150: bmm150@10 { compatible = "bosch,bmm150"; reg = <0x10>; label = "BMM150"; status = "disabled"; }; ledctrl: ledctrl@58 { compatible = "i2c-device"; reg = <0x58>; label = "ledctrl"; status = "disabled"; }; }; &spi1 { status = "disabled"; compatible = "nordic,nrf-spi"; cs-gpios = <&gpio0 13 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; backupstorage: backupstorage@0 { compatible = "issi,is66wvs4m8bll"; reg = <0>; spi-max-frequency = <1600000>; label = "backupstorage"; }; }; &flash0 { partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; boot_partition: partition@0 { label = "mcuboot"; reg = <0x00000000 0xc000>; }; slot0_partition: partition@c000 { label = "image-0"; reg = <0x0000C000 0x32000>; }; slot1_partition: partition@3e000 { label = "image-1"; reg = <0x0003E000 0x32000>; }; scratch_partition: partition@70000 { label = "image-scratch"; reg = <0x00070000 0xa000>; }; // 0x0007a000 0x00006000 = 475136 // 475136 = 464KB storage_partition: partition@7a000 { label = "storage"; reg = <0x0007a000 0x00006000>; }; }; };