diff --git a/common/device/api/u_device.h b/common/device/api/u_device.h index 006e79f4..3da44b14 100644 --- a/common/device/api/u_device.h +++ b/common/device/api/u_device.h @@ -427,6 +427,27 @@ typedef struct { the GNSS device is using is NOT the default #U_GNSS_I2C_ADDRESS; otherwise let the compiler initialise this to 0. */ + bool powerOffToBackup; /**< Normally the GNSS device will be powered + off by the device layer with a call to + uGnssPwrOff(), however this only stops + GNSS; for least power consumption the + device should be powered off to back-up + mode with a call to uGnssPwrOffBackup(); + setting this item to true will cause + uGnssPwrOffBackup() to be called instead + of uGnssPwrOff(). HOWEVER note that the + mechanism through which the GNSS device + is restored from back-up mode may require + additional pins to be connected; e.g. + toggling the I2C pins of the GNSS device + will NOT cause it to return to normal + operation (toggling the SPI and UART + lines will). Instead, for this case + the application must toggle the RESET_N + line or a chosen GPIO line. For more + details refer to the section of the + integration manual for your GNSS device + that covers backup modes. */ /* Add any new version 0 structure items to the end here. * * IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT: diff --git a/common/device/src/u_device_private_gnss.c b/common/device/src/u_device_private_gnss.c index bf2815b9..fbea6ab8 100644 --- a/common/device/src/u_device_private_gnss.c +++ b/common/device/src/u_device_private_gnss.c @@ -91,7 +91,8 @@ const uGnssTransportType_t gDeviceToGnssTransportType[] = { // Populate the GNSS device context static void populateContext(uDeviceGnssInstance_t *pContext, uGnssTransportHandle_t gnssTransportHandle, - uDeviceTransportType_t deviceTransportType) + uDeviceTransportType_t deviceTransportType, + bool powerOffToBackup) { switch (deviceTransportType) { case U_DEVICE_TRANSPORT_TYPE_UART: @@ -114,6 +115,7 @@ static void populateContext(uDeviceGnssInstance_t *pContext, break; } pContext->deviceTransportType = deviceTransportType; + pContext->powerOffToBackup = powerOffToBackup; } // Do all the leg-work to remove a GNSS device. @@ -125,7 +127,11 @@ static int32_t removeDevice(uDeviceHandle_t devHandle, bool powerOff) if (pContext != NULL) { errorCode = (int32_t) U_ERROR_COMMON_SUCCESS; if (powerOff) { - errorCode = uGnssPwrOff(devHandle); + if (pContext->powerOffToBackup) { + errorCode = uGnssPwrOffBackup(devHandle); + } else { + errorCode = uGnssPwrOff(devHandle); + } if (errorCode == 0) { // This will destroy the instance uGnssRemove(devHandle); @@ -160,7 +166,8 @@ static int32_t addDevice(uGnssTransportHandle_t gnssTransportHandle, pContext = (uDeviceGnssInstance_t *) pUPortMalloc(sizeof(uDeviceGnssInstance_t)); if (pContext != NULL) { memset(pContext, 0, sizeof(*pContext)); - populateContext(pContext, gnssTransportHandle, deviceTransportType); + populateContext(pContext, gnssTransportHandle, deviceTransportType, + pCfgGnss->powerOffToBackup); // Add the GNSS instance, which actually creates pDeviceHandle errorCode = uGnssAdd((uGnssModuleType_t) pCfgGnss->moduleType, gnssTransportType, gnssTransportHandle, diff --git a/common/device/src/u_device_shared_gnss.h b/common/device/src/u_device_shared_gnss.h index 9b2083d9..61f94b64 100644 --- a/common/device/src/u_device_shared_gnss.h +++ b/common/device/src/u_device_shared_gnss.h @@ -53,6 +53,7 @@ typedef union { typedef struct { uDeviceGnssTransportHandle_t transportHandle; uDeviceTransportType_t deviceTransportType; + bool powerOffToBackup; } uDeviceGnssInstance_t; #ifdef __cplusplus diff --git a/port/platform/zephyr/dts/bindings/u-blox,ubxlib-device-gnss.yaml b/port/platform/zephyr/dts/bindings/u-blox,ubxlib-device-gnss.yaml index abc21c8f..1a0c5935 100644 --- a/port/platform/zephyr/dts/bindings/u-blox,ubxlib-device-gnss.yaml +++ b/port/platform/zephyr/dts/bindings/u-blox,ubxlib-device-gnss.yaml @@ -103,4 +103,8 @@ properties: gnss-uart2: type: boolean description: "Specify this flag if your UART connection is to the _second_ serial port of a GNSS device." +# request that the device layer powers the GNSS device off to back-up state + power-off-to-backup: + type: boolean + description: "Specify this flag if you want uDeviceClose(), when called with powerOff true, to call uGnssPwrOffBackup() instead of just uGnssPwrOff(); refer to the integration manual for your GNSS device, the backup or power section, for what the application must do to restore the GNSS device to normal operation afterwards." # Note: there is no associated network configuration for the GNSS case \ No newline at end of file diff --git a/port/platform/zephyr/runner/boards/ubx_evkninab3_nrf52840.overlay b/port/platform/zephyr/runner/boards/ubx_evkninab3_nrf52840.overlay index 1a5c481b..0034a6f9 100644 --- a/port/platform/zephyr/runner/boards/ubx_evkninab3_nrf52840.overlay +++ b/port/platform/zephyr/runner/boards/ubx_evkninab3_nrf52840.overlay @@ -39,6 +39,7 @@ module-type = "U_GNSS_MODULE_TYPE_M9"; pin-enable-power = <1>; pin-data-ready = <36>; + power-off-to-backup; }; cfg-device-gnss-1 { compatible = "u-blox,ubxlib-device-gnss"; diff --git a/port/platform/zephyr/src/u_port_board_cfg.c b/port/platform/zephyr/src/u_port_board_cfg.c index cee3d048..c3354e73 100644 --- a/port/platform/zephyr/src/u_port_board_cfg.c +++ b/port/platform/zephyr/src/u_port_board_cfg.c @@ -713,6 +713,16 @@ static const int32_t gDeviceCfgGnssPinDataReady[] = { pin_data_ready) }; +/** Get whether the "power-off-to-backup" property is set + * for each ubxlib-device-gnss compatible device, in the + * order they appear in the device tree. + */ +static const bool gDeviceCfgGnssPowerOffToBackup[] = { + DT_FOREACH_STATUS_OKAY_VARGS(u_blox_ubxlib_device_gnss, + U_PORT_BOARD_CFG_GET_BOOLEAN, + power_off_to_backup) +}; + #endif // #if DT_HAS_COMPAT_STATUS_OKAY(u_blox_ubxlib_device_gnss) /* ---------------------------------------------------------------- @@ -1166,11 +1176,14 @@ static void cfgGnss(uDeviceCfg_t *pCfg, int32_t index) pCfgGnss->pinEnablePower = gDeviceCfgGnssPinEnablePower[index]; pCfgGnss->pinDataReady = gDeviceCfgGnssPinDataReady[index]; pCfgGnss->i2cAddress = -1; + pCfgGnss->powerOffToBackup = gDeviceCfgGnssPowerOffToBackup[index]; uPortLog("U_PORT_BOARD_CFG: using GNSS device \"%s\" from the device tree," - " module-type %d with pin-enable-power %d (0x%02x), pin-data-ready %d (0x%02x)...\n", + " module-type %d with pin-enable-power %d (0x%02x)," + " pin-data-ready %d (0x%02x)%s...\n", gpCfgGnssDeviceName[index], pCfgGnss->moduleType, pCfgGnss->pinEnablePower, pCfgGnss->pinEnablePower, - pCfgGnss->pinDataReady, pCfgGnss->pinDataReady); + pCfgGnss->pinDataReady, pCfgGnss->pinDataReady, + pCfgGnss->powerOffToBackup ? ", power-off-to-backup" : ""); // Don't need to check for NULL here as transport is a required field for GNSS x = getPort(gpDeviceCfgGnssTransportType[index], &(pCfg->transportType)); switch (pCfg->transportType) { diff --git a/port/platform/zephyr/test/u_zephyr_port_board_cfg_test.c b/port/platform/zephyr/test/u_zephyr_port_board_cfg_test.c index 582d6ed2..e656d82d 100644 --- a/port/platform/zephyr/test/u_zephyr_port_board_cfg_test.c +++ b/port/platform/zephyr/test/u_zephyr_port_board_cfg_test.c @@ -419,6 +419,7 @@ U_PORT_TEST_FUNCTION("[zephyrPortBoardCfg]", "zephyrPortBoardCfgBasic") U_PORT_TEST_ASSERT(pCfgGnss->i2cAddress == 0x43); U_PORT_TEST_ASSERT(pCfgGnss->pinEnablePower == 1); U_PORT_TEST_ASSERT(pCfgGnss->pinDataReady == 36); + U_PORT_TEST_ASSERT(pCfgGnss->powerOffToBackup); // Set the second valid configuration setDeviceCfg(&deviceCfg, &instance, U_DEVICE_TYPE_GNSS, "cfg-device-gnss-1"); U_PORT_TEST_ASSERT(uPortBoardCfgDevice(&deviceCfg) == 0); @@ -448,6 +449,7 @@ U_PORT_TEST_FUNCTION("[zephyrPortBoardCfg]", "zephyrPortBoardCfgBasic") U_PORT_TEST_ASSERT(pCfgGnss->moduleType == U_GNSS_MODULE_TYPE_M8); U_PORT_TEST_ASSERT(pCfgGnss->pinEnablePower == 2); U_PORT_TEST_ASSERT(pCfgGnss->pinDataReady == 37); + U_PORT_TEST_ASSERT(!pCfgGnss->powerOffToBackup); // Set the final valid configuration setDeviceCfg(&deviceCfg, &instance, U_DEVICE_TYPE_GNSS, "cfg-device-gnss-2"); U_PORT_TEST_ASSERT(uPortBoardCfgDevice(&deviceCfg) == 0); @@ -468,6 +470,7 @@ U_PORT_TEST_FUNCTION("[zephyrPortBoardCfg]", "zephyrPortBoardCfgBasic") U_PORT_TEST_ASSERT(pCfgGnss->moduleType == U_GNSS_MODULE_TYPE_ANY); U_PORT_TEST_ASSERT(pCfgGnss->pinEnablePower == -1); U_PORT_TEST_ASSERT(pCfgGnss->pinDataReady == -1); + U_PORT_TEST_ASSERT(!pCfgGnss->powerOffToBackup); // Let debug printing catch up uPortTaskBlock(100);