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;

Reply via email to