Hi
I have a nordic NRF52833 interfacing an IMU using I2C and an interrupt signal going to GPIO 13 on the NRF device.
I am using Zephyr and I was able to integrate the IMU driver LISD2/3H including the wake up interrupt. However, when trying to put the NRF to sleep and configuring the same pin as interrupt/GPIO, I don't get the interrupt. Wondering if I am missing a step.
Here is the main file:
/* main.c - Application main entry point */ /* * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/types.h> #include <stddef.h> #include <sys/printk.h> #include <sys/util.h> #include <device.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> #include <drivers/sensor.h> #include <drivers/gpio.h> #include <stdio.h> #include <device.h> #include <init.h> #include <pm/pm.h> #include <pm/device.h> #include <zephyr.h> #include <hal/nrf_gpio.h> #define DEVICE_NAME "VTTI_Beacon" #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) /* TWI instance ID. */ #define TWI_INSTANCE_ID 0 #define MAX_PENDING_TRANSACTIONS 33 #define LIS2DH12_MIN_QUEUE_SIZE 32 #define CONSOLE_LABEL DT_LABEL(DT_CHOSEN(zephyr_console)) #define BUSY_WAIT_S 2U #define SLEEP_S 2U #define SLEEP_S1 5U /* Prevent deep sleep (system off) from being entered on long timeouts * or `K_FOREVER` due to the default residency policy. * * This has to be done before anything tries to sleep, which means * before the threading system starts up between PRE_KERNEL_2 and * POST_KERNEL. Do it at the start of PRE_KERNEL_2. */ static int disable_ds_1(const struct device *dev) { ARG_UNUSED(dev); pm_constraint_set(PM_STATE_SOFT_OFF); return 0; } SYS_INIT(disable_ds_1, PRE_KERNEL_2, 0); static int imu_flag = 0; static void fetch_and_display(const struct device *sensor) { static unsigned int count; struct sensor_value accel[3]; struct sensor_value temperature; struct sensor_value value_x; const char *overrun = ""; int rc = sensor_sample_fetch(sensor); struct sensor_trigger trig; ++count; if (rc == -EBADMSG) { /* Sample overrun. Ignore in polled mode. */ if (IS_ENABLED(CONFIG_LIS2DH_TRIGGER)) { overrun = "[OVERRUN] "; } rc = 0; } if (rc == 0) { /*rc = sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_XYZ, accel);*/ rc = sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_X, &value_x); } if (rc < 0) { printf("ERROR: Update failed: %d\n", rc); } else { /*printf("#%u @ %u ms: %sx %f , y %f , z %f", count, k_uptime_get_32(), overrun, value_x.val2, sensor_value_to_double(&accel[1]), sensor_value_to_double(&accel[2]));*/ if(imu_flag==0) { printf("Accel X Data: %d %d \n", value_x.val1, value_x.val2); imu_flag = 1; } } } #ifdef CONFIG_LIS2DH_TRIGGER static void trigger_handler(const struct device *dev, const struct sensor_trigger *trig) { fetch_and_display(dev); } #endif /* * Set Advertisement data. Based on the Eddystone specification: * https://github.com/google/eddystone/blob/master/protocol-specification.md * https://github.com/google/eddystone/tree/master/eddystone-url */ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), BT_DATA_BYTES(BT_DATA_SVC_DATA16, 0xaa, 0xfe, /* Eddystone UUID */ 0x10, /* Eddystone-URL frame type */ 0x00, /* Calibrated Tx power at 0m */ 0x00, /* URL Scheme Prefix http://www. */ 'v', 't', 't', 'i', '.', 'v','t','.', 'e', 'd', 'u', 0x08) /* .org */ }; /* Set Scan Response data */ static const struct bt_data sd[] = { BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), }; static void bt_ready(int err) { char addr_s[BT_ADDR_LE_STR_LEN]; bt_addr_le_t addr = {0}; size_t count = 1; if (err) { printk("Bluetooth init failed (err %d)\n", err); return; } printk("Bluetooth initialized\n"); /* Start advertising */ err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; } /* For connectable advertising you would use * bt_le_oob_get_local(). For non-connectable non-identity * advertising an non-resolvable private address is used; * there is no API to retrieve that. */ bt_id_get(&addr, &count); bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s)); printk("Beacon started, advertising as %s\n", addr_s); } void main(void) { int err; printk("Starting Beacon Demo\n"); const struct device *sensor = DEVICE_DT_GET_ANY(st_lis2dh); if (sensor == NULL) { printf("No device found\n"); return; } if (!device_is_ready(sensor)) { printf("Device %s is not ready\n", sensor->name); return; } struct sensor_value value_x; sensor_sample_fetch(sensor); sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_X, &value_x); /* Initialize the Bluetooth Subsystem */ err = bt_enable(bt_ready); if (err) { printk("Bluetooth init failed (err %d)\n", err); } struct sensor_trigger trig; int rc; #if CONFIG_LIS2DH_TRIGGER { trig.type = SENSOR_TRIG_DATA_READY; trig.chan = SENSOR_CHAN_ACCEL_XYZ; if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) { struct sensor_value odr = { .val1 = 1, }; rc = sensor_attr_set(sensor, trig.chan, SENSOR_ATTR_SAMPLING_FREQUENCY, &odr); if (rc != 0) { printf("Failed to set odr: %d\n", rc); return; } printf("Sampling at %u Hz\n", odr.val1); } rc = sensor_trigger_set(sensor, &trig, trigger_handler); if (rc != 0) { printf("Failed to set trigger: %d\n", rc); return; } printf("Waiting for triggers\n"); /*while (true) { k_sleep(K_MSEC(2000)); if(imu_flag==1) { rc = sensor_trigger_set(sensor, &trig, trigger_handler); if (rc != 0) { printf("Failed to set trigger: %d\n", rc); return; } imu_flag = 0; } }*/ } //int rc; const struct device *cons = device_get_binding(CONSOLE_LABEL); /* Configure to generate PORT event (wakeup) on button 1 press. */ nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button1), gpios), NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button1), gpios), NRF_GPIO_PIN_SENSE_LOW); printk("Busy-wait %u s\n", BUSY_WAIT_S); k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); printk("Sleep %u s\n", SLEEP_S); k_sleep(K_SECONDS(SLEEP_S)); printk("Sleep %u s with UART off\n", SLEEP_S); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND); k_sleep(K_SECONDS(SLEEP_S)); rc = pm_device_action_run(cons, PM_DEVICE_ACTION_RESUME); printk("Sleep %u s\n", SLEEP_S1); k_sleep(K_SECONDS(SLEEP_S1)); printk("Entering system off; press BUTTON1 to restart\n"); trig.type = SENSOR_TRIG_DATA_READY; trig.chan = SENSOR_CHAN_ACCEL_XYZ; if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) { struct sensor_value odr = { .val1 = 1, }; rc = sensor_attr_set(sensor, trig.chan, SENSOR_ATTR_SAMPLING_FREQUENCY, &odr); if (rc != 0) { printf("Failed to set odr: %d\n", rc); return; } printf("Sampling at %u Hz\n", odr.val1); } rc = sensor_trigger_set(sensor, &trig, trigger_handler); if (rc != 0) { printf("Failed to set trigger: %d\n", rc); return; } /* Configure to generate PORT event (wakeup) on button 1 press. */ nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button1), gpios), NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button1), gpios), NRF_GPIO_PIN_SENSE_LOW); /* Above we disabled entry to deep sleep based on duration of * controlled delay. Here we need to override that, then * force entry to deep sleep on any delay. */ pm_power_state_force(0u, (struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}); printk("ERROR: System off failed\n"); while (true) { if(imu_flag==1) { rc = sensor_trigger_set(sensor, &trig, trigger_handler); if (rc != 0) { printf("Failed to set trigger: %d\n", rc); return; } imu_flag = 0; } /* spin to avoid fall-off behavior */ } #else /* CONFIG_LIS2DH_TRIGGER */ while (true) { sensor_sample_fetch(sensor); sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_X, &value_x); printf("Accel X Data: %d %d \n", value_x.val1, value_x.val2); k_sleep(K_MSEC(100)); } #endif /* CONFIG_LIS2DH_TRIGGER */ }