This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2bcc59b42f1c55d56c00272de560b4e03e796eb7 Author: raiden00pl <[email protected]> AuthorDate: Fri Jun 12 19:15:30 2026 +0200 arch/nrf91: defer GNSS start until the modem is GNSS-capable When the GNSS sensor is opened before the LTE stack has powered the modem on, the modem is not yet in a GNSS-capable functional mode. Instead of failing the activate with -EACCES, remember the request (priv->pending) and let the GNSS thread poll the modem functional mode (AT+CFUN?) and start GNSS once it becomes GNSS-capable. The LTE stack keeps ownership of modem power. Extract the configure/start sequence into nrf91_gnss_start() so it can be used both from nrf91_gnss_enable() and from the thread's CFUN poll. Signed-off-by: raiden00pl <[email protected]> --- arch/arm/src/nrf91/nrf91_modem_gnss.c | 128 +++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/arch/arm/src/nrf91/nrf91_modem_gnss.c b/arch/arm/src/nrf91/nrf91_modem_gnss.c index 95268f89599..b5539567a95 100644 --- a/arch/arm/src/nrf91/nrf91_modem_gnss.c +++ b/arch/arm/src/nrf91/nrf91_modem_gnss.c @@ -28,7 +28,10 @@ #include <nuttx/kthread.h> +#include <nuttx/clock.h> #include <nuttx/debug.h> +#include <nuttx/semaphore.h> +#include <errno.h> #include <string.h> #include <sys/param.h> #include <time.h> @@ -70,6 +73,12 @@ /* Shorten some names */ +/* While a start is deferred (modem not yet GNSS-capable), the GNSS thread + * re-checks the modem functional mode at this interval. + */ + +#define NRF91_GNSS_CFUN_POLL_TICKS (SEC2TICK(2)) + #define NRF_GNSS_PVT_FRAME_LEN (sizeof(struct nrf_modem_gnss_pvt_data_frame)) #define NRF_GNSS_NMEA_FRAME_LEN (sizeof(struct nrf_modem_gnss_nmea_data_frame)) #define NRF_GNSS_AGPS_FRAME_LEN (sizeof(struct nrf_modem_gnss_agps_data_frame)) @@ -84,6 +93,7 @@ struct nrf91_gnss_s struct gnss_lowerhalf_s lower; bool running; + bool pending; bool singlefix; int notime_cntr; sem_t rx_sem; @@ -208,6 +218,40 @@ static bool nrf91_gnss_isactive(int cfun) * Name: nrf91_gnss_enable ****************************************************************************/ +/**************************************************************************** + * Name: nrf91_gnss_start + * + * Description: + * Configure and start the GNSS engine. The caller must have verified that + * the modem is in a GNSS-capable functional mode (see nrf91_gnss_isactive). + * + ****************************************************************************/ + +static int nrf91_gnss_start(struct nrf91_gnss_s *priv) +{ + int ret; + + /* Configure GNSS modem */ + + ret = nrf91_gnss_configure(); + if (ret < 0) + { + snerr("nrf91_gnss_configure failed %d\n", ret); + return ret; + } + + ret = nrf_modem_gnss_start(); + if (ret < 0) + { + snerr("nrf_modem_gnss_start failed %d", ret); + return ret; + } + + priv->pending = false; + priv->running = true; + return OK; +} + static int nrf91_gnss_enable(struct nrf91_gnss_s *priv, bool enable) { int ret = OK; @@ -224,43 +268,44 @@ static int nrf91_gnss_enable(struct nrf91_gnss_s *priv, bool enable) goto errout; } - /* GNSS must be active */ + /* The modem must be in a GNSS-capable functional mode before GNSS can + * be started. When the sensor is opened early (e.g. before the LTE + * stack has powered the modem on), it is not yet active. Rather than + * failing the open, remember the request and let the GNSS thread start + * GNSS once the modem reaches a GNSS-capable mode (see CFUN poll in + * nrf91_gnss_thread). The LTE stack keeps ownership of modem power. + */ if (!nrf91_gnss_isactive(cfun)) { - snerr("GNSS is not activated!"); - ret = -EACCES; - goto errout; - } + sninfo("GNSS not yet active (CFUN=%d); deferring start\n", cfun); + priv->pending = true; - /* Configure GNSS modem */ + /* Kick the thread so it enters its CFUN-poll wait */ - ret = nrf91_gnss_configure(); - if (ret < 0) - { - snerr("nrf91_gnss_configure failed %d\n", ret); - return ret; + nxsem_post(&priv->rx_sem); + return OK; } - ret = nrf_modem_gnss_start(); - if (ret < 0) - { - snerr("nrf_modem_gnss_start failed %d", ret); - goto errout; - } - - priv->running = true; + ret = nrf91_gnss_start(priv); } else { - ret = nrf_modem_gnss_stop(); - if (ret < 0) + /* Cancel any pending deferred start */ + + priv->pending = false; + + if (priv->running) { - snerr("nrf_modem_gnss_stop failed %d", ret); - goto errout; - } + ret = nrf_modem_gnss_stop(); + if (ret < 0) + { + snerr("nrf_modem_gnss_stop failed %d", ret); + goto errout; + } - priv->running = false; + priv->running = false; + } } errout: @@ -624,9 +669,38 @@ static int nrf91_gnss_thread(int argc, char** argv) while (true) { - /* Read data */ + /* While a start is deferred, wait with a timeout and poll the modem + * functional mode; start GNSS once the modem becomes GNSS-capable + * (e.g. after the LTE stack has powered it on). Otherwise wait + * indefinitely for the next GNSS event. + */ + + if (priv->pending && !priv->running) + { + ret = nxsem_tickwait(&priv->rx_sem, NRF91_GNSS_CFUN_POLL_TICKS); + if (ret == -ETIMEDOUT) + { + int cfun = 0; + + if (priv->pending && !priv->running && + nrf_modem_at_scanf("AT+CFUN?", "+CFUN: %d", &cfun) >= 0 && + nrf91_gnss_isactive(cfun)) + { + sninfo("modem GNSS-capable (CFUN=%d); starting GNSS\n", + cfun); + nrf91_gnss_start(priv); + } + + continue; + } + } + else + { + /* Read data */ + + ret = nxsem_wait(&priv->rx_sem); + } - ret = nxsem_wait(&priv->rx_sem); if (ret < 0) { return ret;
