drivers/sensors/l86xxx: Make some dependency patches and update documentation

This commit removes the termios dependency of the command to set fix
rate. It makes the MINMEA dependency present in the Kconfig options for
the driver, and it also adds a retry limit to the boot message
verification of 3 times. The documentation has been updated to reflect
the correct signature for the registration function and fix some
formatting.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
This commit is contained in:
Matteo Golin 2025-07-08 20:26:20 -04:00 committed by Alin Jerpelea
parent 0d834b0621
commit 6ae3cc9082
3 changed files with 95 additions and 60 deletions

View file

@ -23,10 +23,14 @@ the path to the UART interface the module is connected to. You will also need to
ensure that the baud rate of the UART interface is set to 9600, which is the default
baud rate of the L86-XXX series of GNSS modules.
The driver supports changing the default baud rate and update rate of the GNSS module.
As a result, you will also need to enable serial TERMIOS support (``CONFIG_SERIAL_TERMIOS``).
The baud rate and update rate of the GNSS module can be configured using the ``L86_XXX_BAUD`` and ``L86_XXX_FIX_INT`` options respectively.
Note that a faster update rate will require a higher baud rate to support it and the supported baud rates for the L86-XXX series of GNSS modules are:
The driver supports changing the default baud rate and update rate of the GNSS
module. As a result, you will also need to enable serial TERMIOS support
(``CONFIG_SERIAL_TERMIOS``). The baud rate and update rate of the GNSS module
can be configured using the ``L86_XXX_BAUD`` and ``L86_XXX_FIX_INT`` options
respectively. Note that a faster update rate will require a higher baud rate to
support it and the supported baud rates for the L86-XXX series of GNSS modules
are:
* 4800
* 9600
* 14400
@ -34,6 +38,7 @@ Note that a faster update rate will require a higher baud rate to support it and
* 38400
* 57600
* 115200
The baud rate and update rates of the module are changed at registration time.
.. code-block:: c
@ -41,39 +46,53 @@ The baud rate and update rates of the module are changed at registration time.
#if defined(CONFIG_SENSORS_L86_XXX)
#include <nuttx/sensors/l86xxx.h>
/* Register L86-M33 on USART3 */
/* Register L86xxx device on USART2 */
ret = l86xxx_register("/dev/l86m33", "/dev/ttyS2", 0);
ret = l86xxx_register("/dev/ttyS2", 0);
if (ret < 0) {
syslog(LOG_ERR, "Failed to register L86-M33: %d\n", ret);
}
#endif
Once the driver is registered, it starts a thread that continuously reads raw output from the specified UART device and
parses the output according to `NMEA <https://en.wikipedia.org/wiki/NMEA_0183>`_ standards using the
`minmea <https://github.com/kosma/minmea>`_ library included in NuttX. The driver populates the ``sensor_gnss`` struct
and pushes it to the appropriate event once all NMEA messages in its sequence have been read.
Once the driver is registered, it starts a thread that continuously reads raw
output from the specified UART device and parses the output according to `NMEA
<https://en.wikipedia.org/wiki/NMEA_0183>`_ standards using the `minmea
<https://github.com/kosma/minmea>`_ library included in NuttX. The driver
populates the ``sensor_gnss`` struct and pushes it to the appropriate event once
all NMEA messages in its sequence have been read.
**uORB commands**
-----------------
The driver implements the ``orb_activate``, ``orb_set_interval`` and, ``orb_ioctl`` operations to interact with the device.
The latter is used to send proprietary 'PMTK' commands which are documented further below.
The driver implements the ``orb_activate``, ``orb_set_interval`` and,
``orb_ioctl`` operations to interact with the device. The latter is used to send
proprietary 'PMTK' commands which are documented further below.
**Activate**
There are 4 modes that the L86-XXX GNSS modules can be in. Those are "Full On Mode", "Standby Mode", "Backup Mode", "Periodic Mode" and, "AlwaysLocateTM Mode".
Calling ``orb_activate`` with ``enable`` set to false will enter the module into "Standby Mode".
In "Standby Mode", the module doesn't output any NMEA messages but the internal core and I/O power domain are still active.
There are 4 modes that the L86-XXX GNSS modules can be in:
The module can be re-enabled by calling ``orb_activate`` with ``enable`` set to true, which will hot start the module OR by
sending any 'PMTK' command.
* Full On Mode
* Standby Mode
* Backup Mode
* Periodic Mode
* AlwaysLocateTM Mode
Calling ``orb_activate`` with ``enable`` set to false will enter the
module into "Standby Mode". In "Standby Mode", the module doesn't output any
NMEA messages but the internal core and I/O power domain are still active.
The module can be re-enabled by calling ``orb_activate`` with ``enable`` set to
true, which will hot start the module OR by sending any 'PMTK' command.
**Set interval**
The L86-XXX GNSS modules support interval rates from 1Hz to 10Hz (100ms - 10000ms). When using ``orb_set_interval``, be aware that
increasing the interval of the module may also require and increase in baud rate. An example of how this is performed can be found in
source code of this driver in the register function.
The L86-XXX GNSS modules support interval rates from 1Hz to 10Hz (100ms -
10000ms). When using ``orb_set_interval``, be aware that increasing the interval
of the module may also require and increase in baud rate. An example of how this
is performed can be found in source code of this driver in the register
function.
Any interval rate outside of the supported range will result in a failed call to this function.
@ -82,16 +101,17 @@ Any interval rate outside of the supported range will result in a failed call to
The ``orb_ioctl`` interface allows one to send proprietary 'PMTK' commands to the L86-XXX GNSS module. It effectively works
as a wrapper for the command framework outlined by Quectel. The return value of calls to ``orb_ioctl`` follow this pattern:
* -EINVAL - Invalid packet
* -ENOSYS - Unsupported packet type
* -EIO - Valid packet, but action failed
* 0 - Valid packet, action succeeded
* Other - Command failed during writing
* ``EINVAL`` - Invalid packet
* ``ENOSYS`` - Unsupported packet type
* ``EIO`` - Valid packet, but action failed
* ``0`` - Valid packet, action succeeded
* Other - Command failed during writing
The supported commands are their arguments are listed below.
``SNIOC_HOT_START``
-------------------
Used to "Hot start" the GNSS module. Normally hot start means the GNSS module was powered down for less
than 3 hours (RTC must be alive) and its ephemeris is still valid. As there is no need for downloading
ephemeris, it is the fastest startup method.
@ -102,6 +122,7 @@ ephemeris, it is the fastest startup method.
``SNIOC_WARM_START``
--------------------
Used to "Warm start" the GNSS module. Warm start means the GNSS module has approximate information of time,
position and coarse data on satellite positions, but it needs to download ephemeris until it can get a fix.
@ -111,6 +132,7 @@ position and coarse data on satellite positions, but it needs to download epheme
``SNIOC_COLD_START``
--------------------
Used to "Cold start" the GNSS module. Using this message will force the GNSS module to be restarted without
any prior location information, including time, position, almanacs and ephemeris data.
@ -120,6 +142,7 @@ any prior location information, including time, position, almanacs and ephemeris
``SNIOC_FULL_COLD_START``
-------------------------
Used to "Full cold start" the GNSS module. This is effectively the same as a cold restart, but additionally
clears system and user configurations. In other words, this resets the GNSS module to its factory settings.
When full-cold started, the GNSS module has no information on its last location.
@ -130,7 +153,9 @@ When full-cold started, the GNSS module has no information on its last location.
``SNIOC_SET_INTERVAL``
----------------------
Used to modify the position fix interval of the GNSS module. The argument is an integer between 100 and 10000, default value is 1000.
Used to modify the position fix interval of the GNSS module. The argument is an
integer between 100 and 10000, default value is 1000.
.. code-block:: c
@ -140,7 +165,7 @@ Used to modify the position fix interval of the GNSS module. The argument is an
------------------
.. note::
This feature requires termios support to be enabled(``CONFIG_SERIAL_TERMIOS``)
This feature requires termios support to be enabled (``CONFIG_SERIAL_TERMIOS``)
Used to modify the baud rate of the GNSS module. The argument is an integer representing a supported baud rate, default value is 9600.
Upon sending this command, the baud rate of the UART interface used to communicate with the module is also modified.
@ -160,6 +185,7 @@ Supported baud rates for the L86-XXX series of GNSS modules are:
``SNIOC_SET_OPERATIONAL_MODE``
------------------------------
Used to set the navigation mode of the GNSS module. The argument is an ``L86XXX_OPERATIONAL_MODE`` enum:
* NORMAL - For general purpose
@ -173,5 +199,3 @@ Default mode is NORMAL
.. code-block:: c
orb_ioctl(sensor, SNIOC_SET_OPERATIONAL_MODE, NORMAL);

View file

@ -841,13 +841,13 @@ endif # SENSORS_KXTJ9
config SENSORS_L86_XXX
bool "Quectel L86-XXX GNSS support"
default n
depends on SERIAL && STANDARD_SERIAL && UORB
depends on SERIAL && STANDARD_SERIAL && UORB && GNSSUTILS_MINMEA_LIB
---help---
Enable driver support for the L86-XXX series of GNSS modules.
config SENSORS_L86_XXX_THREAD_STACKSIZE
int "Stack size for L86XXX module collection thread"
default 10000
default 1024
depends on SENSORS_L86_XXX
config L86_XXX_BAUD
@ -861,7 +861,7 @@ config L86_XXX_BAUD
config L86_XXX_FIX_INT
int "Quectel L86-XXX fix interval rate"
default 1000
depends on SENSORS_L86_XXX && SERIAL_TERMIOS
depends on SENSORS_L86_XXX
range 100 10000
---help---
Rate in ms at which module obtains satellite fix. Supported values

View file

@ -113,7 +113,9 @@ static int l86xxx_activate(FAR struct sensor_lowerhalf_s *lower,
static int l86xxx_set_interval(FAR struct sensor_lowerhalf_s *lower,
FAR struct file *filep,
FAR uint32_t *period_us);
#ifdef CONFIG_SERIAL_TERMIOS
static int set_baud_rate(l86xxx_dev_s *dev, int br);
#endif
static int send_command(l86xxx_dev_s *dev,
L86XXX_PMTK_COMMAND cmd, unsigned long arg);
static int read_line(l86xxx_dev_s *dev);
@ -294,9 +296,9 @@ static int send_command(l86xxx_dev_s *dev,
return err;
}
/* These commands do not send ACKs
so just return after they've been written
*/
/* These commands do not send ACKs so just return after they've been
* written
*/
if (cmd == CMD_HOT_START ||
cmd == CMD_WARM_START ||
@ -308,39 +310,50 @@ static int send_command(l86xxx_dev_s *dev,
}
/* Setting baud rate also doesn't send an ACK but the interface baud rate
needs to be updated
*/
* needs to be updated
*/
if (cmd == SET_NMEA_BAUDRATE)
{
#ifdef CONFIG_SERIAL_TERMIOS
nxsig_usleep(20000); /* Should wait for a bit before changing interface baud rate */
ret = set_baud_rate(dev, (int)arg);
#else
ret = -EINVAL;
#endif
nxmutex_unlock(&dev->devlock);
return ret;
}
/* Some commands will send ACKs,
wait for them here before unlocking the mutex
*/
* wait for them here before unlocking the mutex
*/
/* ACK message will be $PMTK001,<cmd num>,<flag>
flag num indicates success of command
0 = Invalid packet
1 = Unsupported packet type
2 = Valid packet, but action failed
3 = Valid packet, action succeeded
*/
/* ACK message will be $PMTK001,<cmd num>,<flag> flag num indicates success
* of command:
*
* 0 = Invalid packet
* 1 = Unsupported packet type
* 2 = Valid packet, but action failed
* 3 = Valid packet, action succeeded
*/
memset(buf, '\0', 50);
snprintf(buf, 50, "$PMTK001,%d", cmd);
sninfo("Waiting for ACK from L86...\n");
for (; ; )
read_line(dev);
if (strncmp(buf, dev->buffer, strlen(buf)) == 0)
{
read_line(dev);
if (strncmp(buf, dev->buffer, strlen(buf)) == 0) break;
sninfo("ACK received!\n");
}
else
{
snerr("Did not get ACK!\n");
nxmutex_unlock(&dev->devlock);
return -EIO;
}
sninfo("ACK received!\n");
nxmutex_unlock(&dev->devlock);
/* Flag num is always in position 13 of ack, subtract by '0'
@ -719,6 +732,8 @@ int l86xxx_register(FAR const char *uartpath, int devno)
FAR l86xxx_dev_s *priv = NULL;
int err;
char *buf;
FAR char *argv[2];
char arg1[32];
DEBUGASSERT(uartpath != NULL);
@ -764,21 +779,21 @@ int l86xxx_register(FAR const char *uartpath, int devno)
/* Setup sensor with configured settings */
sninfo("Waiting for GNSS to start...\n");
buf = "$PMTK010,001*2E";
for (; ; )
read_line(priv);
if (strncmp(buf, priv->buffer, strlen(buf)) == 0)
{
read_line(priv);
if (strncmp(buf, priv->buffer, strlen(buf)) == 0) break;
sninfo("GNSS module started.\n");
}
sninfo("GNSS module started.\n");
#ifdef CONFIG_SERIAL_TERMIOS
#ifdef CONFIG_SERIAL_TERMIOS
err = send_command(priv, SET_NMEA_BAUDRATE, L86_XXX_BAUD_RATE);
if (err < 0)
{
snwarn("Couldn't set baud rate of device: %d\n", err);
}
#endif
err = send_command(priv, SET_POS_FIX, CONFIG_L86_XXX_FIX_INT);
if (err < 0)
@ -786,8 +801,6 @@ int l86xxx_register(FAR const char *uartpath, int devno)
snwarn("Couldn't set position fix interval, %d\n", err);
}
#endif
/* Register UORB Sensor */
priv->lower.ops = &g_sensor_ops;
@ -800,8 +813,6 @@ int l86xxx_register(FAR const char *uartpath, int devno)
goto close_file;
}
FAR char *argv[2];
char arg1[32];
snprintf(arg1, 16, "%p", priv);
argv[0] = arg1;
argv[1] = NULL;