Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
GNSS change only: add support for Data Ready, AKA TXReady, pin. (#1201)
Browse files Browse the repository at this point in the history
GNSS devices support toggling a TXReady pin when there is data available. This can be useful for power saving, allowing an MCU to sleep, or perform other tasks under the OS, while waiting for position from the GNSS device. Building on 128a72b, which added interrupt support to the GPIO API of the port layer, GNSS Data Ready is now supported using the fields pinDataReady and devicePioDataReady of the device configuration structure passed to uDeviceOpen() for a GNSS device. Note that pinDataReady was already present in the configuration structure, normally set to -1, but for this feature to work the PIO of the GNSS device that this MCU pin is connected to must also be known, hence the addition of devicePioDataReady, which must be set to a valid value if pinDataReady is not -1.

Note that this is only supported on M9 devices and later, on I2C and SPI interfaces, and also that devicePioDataReady must not already be in use for something else on the GNSS device: where that is the case uDeviceOpen() will return the error U_GNSS_ERROR_PIO_IN_USE.
  • Loading branch information
RobMeades authored Jul 29, 2024
1 parent 6aacd7d commit 2896142
Show file tree
Hide file tree
Showing 27 changed files with 1,402 additions and 156 deletions.
29 changes: 24 additions & 5 deletions common/device/api/u_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,11 +408,18 @@ typedef struct {
configuration structure for GNSS,
#uNetworkCfgGnss_t, should be
populated instead). */
int32_t pinDataReady; /**< The input pin that is used to receive
the Data Ready state of the GNSS module;
this field is present for
forwards-compatibility only; it is
currently ignored. */
int32_t pinDataReady; /**< The input pin of this MCU that is used
to receive the Data Ready, AKA TX-Ready,
status of the GNSS module; use -1 if
there is no such connection. Note
that use of such a pin is ONLY supported
on M9 modules and later, and GNSS devices
only support this on I2C and SPI. If this
field is not -1 then devicePioDataReady
(see below) MUST ALSO BE POPULATED.
Only works if interrupts are accessible
on your platform (so not on Windows or
Linux). */
bool includeNmea; /**< \deprecated This field used to
permit NMEA messages to be included
when they were normally excluded by
Expand Down Expand Up @@ -448,6 +455,18 @@ typedef struct {
details refer to the section of the
integration manual for your GNSS device
that covers backup modes. */
int32_t devicePioDataReady; /**< The PIO of the GNSS device that is to
be used for Data Ready, AKA TX-Ready;
must be populated if pinDataReady is
not -1, ignored if pinDataReady is -1.
This is the PIO, _NOT_ the pin number,
they are different; the PIO can usually
be found in the data sheet for the GNSS
device. IMPORTANT: this PIO must not already
be in use for some other peripheral function
within the GNSS device; should that be the
case the error #U_GNSS_ERROR_PIO_IN_USE will
be returned. */
/* Add any new version 0 structure items to the end here.
*
* IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT:
Expand Down
6 changes: 6 additions & 0 deletions common/device/src/u_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ int32_t uDeviceGetDefaults(uDeviceType_t deviceType,
U_CFG_APP_PIN_GNSS_DATA_READY;
#else
-1;
#endif
pDeviceCfg->deviceCfg.cfgGnss.devicePioDataReady =
#ifdef U_CFG_APP_GNSS_DEVICE_PIO_DATA_READY
U_CFG_APP_GNSS_DEVICE_PIO_DATA_READY;
#else
-1;
#endif
pDeviceCfg->deviceCfg.cfgGnss.pinEnablePower =
#ifdef U_CFG_APP_PIN_GNSS_ENABLE_POWER
Expand Down
229 changes: 123 additions & 106 deletions common/device/src/u_device_private_gnss.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "u_gnss.h"
#include "u_gnss_pwr.h"
#include "u_gnss_cfg.h" // For uGnssCfgSetProtocolOut()
#include "u_gnss_msg.h" // For uGnssMsgSetDataReady()

#include "u_device_private.h"
#include "u_device_shared_gnss.h"
Expand Down Expand Up @@ -187,7 +188,18 @@ static int32_t addDevice(uGnssTransportHandle_t gnssTransportHandle,
U_DEVICE_INSTANCE(*pDeviceHandle)->pContext = pContext;
// Power on the GNSS chip
errorCode = uGnssPwrOn(*pDeviceHandle);
if (errorCode != 0) {
if ((errorCode == 0) && (pCfgGnss->pinDataReady >= 0)) {
// A data ready pin has been specified; set it up
errorCode = uGnssMsgSetDataReady(*pDeviceHandle,
pCfgGnss->pinDataReady,
pCfgGnss->devicePioDataReady,
-1, -1, NULL, NULL);
if (errorCode < 0) {
// Return to off state if data ready set-up has failed
uGnssPwrOff(*pDeviceHandle);
}
}
if (errorCode < 0) {
// If we failed to power on, clean up
removeDevice(*pDeviceHandle, false);
}
Expand Down Expand Up @@ -241,26 +253,54 @@ int32_t uDevicePrivateGnssAdd(const uDeviceCfg_t *pDevCfg,
if ((pDevCfg != NULL) && (pDeviceHandle != NULL)) {
pCfgGnss = &(pDevCfg->deviceCfg.cfgGnss);
if (pCfgGnss->version == 0) {
switch (pDevCfg->transportType) {
case U_DEVICE_TRANSPORT_TYPE_UART:
// fall-through
case U_DEVICE_TRANSPORT_TYPE_UART_USB:
// fall-through
case U_DEVICE_TRANSPORT_TYPE_UART_2:
pCfgUart = &(pDevCfg->transportCfg.cfgUart);
if (pCfgUart->pPrefix != NULL) {
uPortUartPrefix(pCfgUart->pPrefix);
}
if (0 == pCfgUart->baudRate) {
// Negotiate baud rate
const unsigned baudRates[] = { 1200, 2400, 4800, 9600, 14400,
19200, 38400, 57600, 115200,
230400, 460800, 921600
};

for (int32_t i = ((sizeof(baudRates) / sizeof(baudRates[0])) - 1); i >= 0; --i) {
// If a data ready pin is provided then the
// device PIO must also be provided
if ((pCfgGnss->pinDataReady < 0) ||
(pCfgGnss->devicePioDataReady >= 0)) {
switch (pDevCfg->transportType) {
case U_DEVICE_TRANSPORT_TYPE_UART:
// fall-through
case U_DEVICE_TRANSPORT_TYPE_UART_USB:
// fall-through
case U_DEVICE_TRANSPORT_TYPE_UART_2:
pCfgUart = &(pDevCfg->transportCfg.cfgUart);
if (pCfgUart->pPrefix != NULL) {
uPortUartPrefix(pCfgUart->pPrefix);
}
if (0 == pCfgUart->baudRate) {
// Negotiate baud rate
const unsigned baudRates[] = { 1200, 2400, 4800, 9600, 14400,
19200, 38400, 57600, 115200,
230400, 460800, 921600
};

for (int32_t i = ((sizeof(baudRates) / sizeof(baudRates[0])) - 1); i >= 0; --i) {
errorCode = uPortUartOpen(pCfgUart->uart,
baudRates[i], NULL,
U_GNSS_UART_BUFFER_LENGTH_BYTES,
pCfgUart->pinTxd,
pCfgUart->pinRxd,
pCfgUart->pinCts,
pCfgUart->pinRts);
if (errorCode >= 0) {
gnssTransportHandle.uart = errorCode;
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
if (errorCode < 0) {
// Clean up on error
uPortUartClose(gnssTransportHandle.uart);
} else {
// Found acceptable baudrate
break;
}
}
}
} else {
// Open a UART with the recommended buffer length
// and default baud rate.
errorCode = uPortUartOpen(pCfgUart->uart,
baudRates[i], NULL,
pCfgUart->baudRate, NULL,
U_GNSS_UART_BUFFER_LENGTH_BYTES,
pCfgUart->pinTxd,
pCfgUart->pinRxd,
Expand All @@ -274,108 +314,85 @@ int32_t uDevicePrivateGnssAdd(const uDeviceCfg_t *pDevCfg,
if (errorCode < 0) {
// Clean up on error
uPortUartClose(gnssTransportHandle.uart);
} else {
// Found acceptable baudrate
break;
}
}
}
} else {
// Open a UART with the recommended buffer length
// and default baud rate.
errorCode = uPortUartOpen(pCfgUart->uart,
pCfgUart->baudRate, NULL,
U_GNSS_UART_BUFFER_LENGTH_BYTES,
pCfgUart->pinTxd,
pCfgUart->pinRxd,
pCfgUart->pinCts,
pCfgUart->pinRts);
break;
case U_DEVICE_TRANSPORT_TYPE_I2C:
pCfgI2c = &(pDevCfg->transportCfg.cfgI2c);
// Open the I2C instance.
errorCode = uDevicePrivateI2cOpen(pCfgI2c);
if (errorCode >= 0) {
gnssTransportHandle.uart = errorCode;
gnssTransportHandle.i2c = errorCode;
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
if (errorCode < 0) {
if (errorCode >= 0) {
// Log that the device is using the given I2C HW
x = uDevicePrivateI2cIsUsedBy(*pDeviceHandle, pCfgI2c);
if (x < 0) {
errorCode = x;
// Clean up if there's no room
removeDevice(*pDeviceHandle, true);
}
} else {
// Clean up on error
uPortUartClose(gnssTransportHandle.uart);
uDevicePrivateI2cCloseCfgI2c(pCfgI2c);
}
}
}
break;
case U_DEVICE_TRANSPORT_TYPE_I2C:
pCfgI2c = &(pDevCfg->transportCfg.cfgI2c);
// Open the I2C instance.
errorCode = uDevicePrivateI2cOpen(pCfgI2c);
if (errorCode >= 0) {
gnssTransportHandle.i2c = errorCode;
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
break;
case U_DEVICE_TRANSPORT_TYPE_SPI:
pCfgSpi = &(pDevCfg->transportCfg.cfgSpi);
// Open SPI.
errorCode = uPortSpiOpen(pCfgSpi->spi,
pCfgSpi->pinMosi,
pCfgSpi->pinMiso,
pCfgSpi->pinClk,
true);
if (errorCode >= 0) {
// Log that the device is using the given I2C HW
x = uDevicePrivateI2cIsUsedBy(*pDeviceHandle, pCfgI2c);
if (x < 0) {
errorCode = x;
// Clean up if there's no room
removeDevice(*pDeviceHandle, true);
gnssTransportHandle.spi = errorCode;
if (pCfgSpi->maxSegmentSize > 0) {
if (uPortSpiSetMaxSegmentSize(gnssTransportHandle.spi,
pCfgSpi->maxSegmentSize) < 0) {
// Return a meaningful error code
errorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
}
}
} else {
// Clean up on error
uDevicePrivateI2cCloseCfgI2c(pCfgI2c);
}
}
break;
case U_DEVICE_TRANSPORT_TYPE_SPI:
pCfgSpi = &(pDevCfg->transportCfg.cfgSpi);
// Open SPI.
errorCode = uPortSpiOpen(pCfgSpi->spi,
pCfgSpi->pinMosi,
pCfgSpi->pinMiso,
pCfgSpi->pinClk,
true);
if (errorCode >= 0) {
gnssTransportHandle.spi = errorCode;
if (pCfgSpi->maxSegmentSize > 0) {
if (uPortSpiSetMaxSegmentSize(gnssTransportHandle.spi,
pCfgSpi->maxSegmentSize) < 0) {
// Return a meaningful error code
errorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
if (errorCode >= 0) {
errorCode = uPortSpiControllerSetDevice(gnssTransportHandle.spi,
&(pCfgSpi->device));
if (errorCode == 0) {
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
}
}
}
if (errorCode >= 0) {
errorCode = uPortSpiControllerSetDevice(gnssTransportHandle.spi,
&(pCfgSpi->device));
if (errorCode == 0) {
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
if (errorCode < 0) {
// Clean up on error
uPortSpiClose(gnssTransportHandle.spi);
}
}
if (errorCode < 0) {
// Clean up on error
uPortSpiClose(gnssTransportHandle.spi);
}
}
break;
case U_DEVICE_TRANSPORT_TYPE_VIRTUAL_SERIAL:
pCfgVirtualSerial = &(pDevCfg->transportCfg.cfgVirtualSerial);
pDeviceSerial = pCfgVirtualSerial->pDevice;
// Open a virtual serial port with the recommended buffer length
errorCode = pDeviceSerial->open(pDeviceSerial, NULL,
U_GNSS_UART_BUFFER_LENGTH_BYTES);
if (errorCode == 0) {
gnssTransportHandle.pDeviceSerial = pDeviceSerial;
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
if (errorCode < 0) {
// Clean up on error
pDeviceSerial->close(pDeviceSerial);
break;
case U_DEVICE_TRANSPORT_TYPE_VIRTUAL_SERIAL:
pCfgVirtualSerial = &(pDevCfg->transportCfg.cfgVirtualSerial);
pDeviceSerial = pCfgVirtualSerial->pDevice;
// Open a virtual serial port with the recommended buffer length
errorCode = pDeviceSerial->open(pDeviceSerial, NULL,
U_GNSS_UART_BUFFER_LENGTH_BYTES);
if (errorCode == 0) {
gnssTransportHandle.pDeviceSerial = pDeviceSerial;
errorCode = addDevice(gnssTransportHandle,
pDevCfg->transportType,
pCfgGnss, pDeviceHandle);
if (errorCode < 0) {
// Clean up on error
pDeviceSerial->close(pDeviceSerial);
}
}
}
break;
default:
break;
break;
default:
break;
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions common/network/test/u_network_test_shared_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,16 @@ static const uDeviceCfg_t gDeviceCfgGnss = {
.cfgGnss = {
.moduleType = U_CFG_TEST_GNSS_MODULE_TYPE,
.pinEnablePower = U_CFG_APP_PIN_GNSS_ENABLE_POWER,
# ifdef U_CFG_APP_PIN_GNSS_DATA_READY
.pinDataReady = U_CFG_APP_PIN_GNSS_DATA_READY,
# ifndef U_CFG_APP_GNSS_DEVICE_PIO_DATA_READY
# error U_CFG_APP_GNSS_DEVICE_PIO_DATA_READY must be defined if U_CFG_APP_PIN_GNSS_DATA_READY is defined
# else
.devicePioDataReady = U_CFG_APP_GNSS_DEVICE_PIO_DATA_READY
# endif
# else
.pinDataReady = -1
# endif
}
},
# if (U_CFG_APP_GNSS_I2C >= 0)
Expand Down
Loading

0 comments on commit 2896142

Please sign in to comment.