Ubxlib GNSS Sample
Overview
A sample application demonstrating how to integrate a u-blox GNSS device into a Zephyr application. The example code is rigidly configured to work with an u-blox M10 device [1]. It was tested with the SparkFun MAX-M10S Breakout [2].
Requirements
The u-blox GNSS device must be connected via UART, and a Devicetree alias
ubxlib-uart0
must exist that point towards this UART port. Also
a single GPIO line for the module reset signal have to define. To fulfil this
requirement, this sample application comes with a generic application overlay
app.overlay
that should be usable with all boards that provies an
Arduino UNO R3 edge connector. For ubxlib-uart0
the standard
Arduino UART on D0 (RX) and D1 (TX) will be used
(&arduino_serial
). The reset signal will be controlled by
D8 (GPIO) and is mapped to <&arduino_header 14 /*…*/>
. To ensure
to use the correct GPIO line for the module reset signal, the example provides
the only locally usable Devicetree binding reset-switch.yaml
. This
specifies the Devicetree compatibility string reset-switch.
Default application overlay |
Binding for the module reset signal |
---|---|
/ {
reset_switch: reset_switch {
compatible = "reset-switch";
gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>;
};
aliases {
ubxlib-uart0 = &arduino_serial;
};
};
&arduino_serial {
status = "okay";
current-speed = <9600>;
};
|
description: GPIO pin to cause a reset on an external device
compatible: "reset-switch"
properties:
gpios:
type: phandle-array
required: true
description: |
The GPIO pin connected to a reset switch.
|
Regardless of this, it is still free and open to use a specific board overlay to adapt these default settings to other hardware conditions.
Building and Running
Build and flash for different boards
Nordic nRF9160 DK (nRF9160)
west build -b nrf9160dk/nrf9160 -p -d build/nrf9160dk_nrf9160-ubx_gnss bridle/samples/ubx_gnss
west flash -d build/nrf9160dk_nrf9160-ubx_gnss
Nordic nRF52840 DK (nRF52840)
west build -b nrf52840dk/nrf52840 -p -d build/nrf52840dk_nrf52840-ubx_gnss bridle/samples/ubx_gnss
west flash -d build/nrf52840dk_nrf52840-ubx_gnss
ST Nucleo L496ZG
west build -b nucleo_l496zg -p -d build/nucleo_l496zg-ubx_gnss bridle/samples/ubx_gnss
west flash -d build/nucleo_l496zg-ubx_gnss
ST Nucleo F413ZH
west build -b nucleo_f413zh -p -d build/nucleo_f413zh-ubx_gnss bridle/samples/ubx_gnss
west flash -d build/nucleo_f413zh-ubx_gnss
ST Nucleo F767ZI
west build -b nucleo_f767zi -p -d build/nucleo_f767zi-ubx_gnss bridle/samples/ubx_gnss
west flash -d build/nucleo_f767zi-ubx_gnss
NXP MIMXRT1170-EVKB (CM7)
west build -b mimxrt1170_evk@B/mimxrt1176/cm7 -p -d build/mimxrt1170_evkb_cm7-ubx_gnss bridle/samples/ubx_gnss
west flash -r pyocd -d build/mimxrt1170_evkb_cm7-ubx_gnss
NXP MIMXRT1060-EVK
west build -b mimxrt1060_evk -p -d build/mimxrt1060_evk-ubx_gnss bridle/samples/ubx_gnss
west flash -r pyocd -d build/mimxrt1060_evk-ubx_gnss
NXP MIMXRT1010-EVK (experimental)
west build -b mimxrt1010_evk -p -S usb-console -d build/mimxrt1010_evk-ubx_gnss bridle/samples/ubx_gnss -- -DCONFIG_LOG=n
west flash -r pyocd -d build/mimxrt1010_evk-ubx_gnss
Warning
This board requires special care when using and maintaining the code base.
First of all, there is a lack of sufficient UART interfaces. The user must
decide whether he wants to use the one available LPUART1 as a console via
the on-board debug adapter (the factory default) or whether he needs it
for his own purposes on the Arduino edge connector. For this example,
the later is the case and it is extremely important that the two jumpers
JP31 for TX and JP32 for RX are removed so that there
is no longer an active connection to the on-board debug adapter (isolation).
This also removes the channel for the standard console and the on-board
USB device at J9 must be used as an alternative. This in turn
means that Zephyr needs the USB device software stack with the USB-CDC/ACM
class driver for VCOM access to the shell enabled. Note the
west build parameter -S usb-console
.
It is more luck than sense that this example works on this extremely poorly
equipped board. The word “works” should also not be overrated.
The ubxlib
software stack is extremely memory-intensive
and requires at least 16 kB RAM for the memory heap
(CONFIG_HEAP_MEM_POOL_SIZE
). That alone is already 25%
of the available RAM in this system. Together with the necessary USB device
software stack and the USB-CDC/ACM class driver, there is hardly anything
left for additional functions. This means that the Zephyr shell
can only be used in the absolute minimum configuration
(CONFIG_SHELL_MINIMAL
=y
) and the Zephyr
logging system must be omitted completely
(CONFIG_LOG
=n
).
The CMake parameter -DCONFIG_LOG=n
must be considered for
this when calling west build.
As a result of the limited memory capacity, important runtime stacks must also be reduced. That are in summary:
Board specific configuration |
Context and meaning |
---|---|
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_MAIN_STACK_SIZE=3456
CONFIG_ISR_STACK_SIZE=1024
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512
CONFIG_USB_WORKQUEUE_STACK_SIZE=512
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=512
|
|
With this heuristically determined memory configuration, the main
functions of this “simple” example can be used. One exception
is the shell command gnss single
. The subsequent function call
stack may grow to a point where the reduced ISR or main stack overflows
and, in the absence of further Zephyr functionality, the CPU simply stops
in a critical exception – with no visible notification to the user.
This is a very dynamic effect and difficult to predict,
but it happens very often.
Example console session
After power-on or hard reset, the GNSS module will be initialized automatically:
*** Booting Zephyr OS build v3.7.0… *** [00:00:02.021,000] <inf> main: GNSS Device is ready! uart:~$ _
There is a simple Shell command for some standard evaluation steps:
uart:~$ gnss -h gnss - GNSS related commands Subcommands: single :Get a one-shot position estimate stream :Start or stop streaming of position estimates reset :Reset GNSS module ttff :Measure TTFF uart:~$ _
Reset GNSS module:
uart:~$ gnss reset uart:~$ _The on-module LED for PPS signaling goes off and comes back to blink after TTFF.
Measure TTFF:
uart:~$ gnss ttff Run 1 of 1: Acquired fix after 32.26s --------------- Avg. TTFF: 32.26 uart:~$ _The on-module LED for PPS signaling goes off and comes back to blink after TTFF.
It is also possible to run several TTFF measurements sequentially. If there is also a good receiving range and a reliable position already exists, the TTFF will be correspondingly low:
uart:~$ gnss ttff 10 Run 1 of 10: Acquired fix after 0.23s Run 2 of 10: Acquired fix after 0.79s Run 3 of 10: Acquired fix after 1.00s Run 4 of 10: Acquired fix after 0.59s Run 5 of 10: Acquired fix after 0.81s Run 6 of 10: Acquired fix after 0.79s Run 7 of 10: Acquired fix after 0.80s Run 8 of 10: Acquired fix after 1.01s Run 9 of 10: Acquired fix after 0.58s Run 10 of 10: Acquired fix after 0.81s --------------- Avg. TTFF: 0.74 uart:~$ _
Get a one-shot position estimate:
uart:~$ gnss single Found position estimate after 0.8s: (lat, lon): (50.922432, 11.600015), alt: 192.05m, radius: 1.48m (15 SV used) uart:~$ _
Start or stop streaming of position estimates:
uart:~$ gnss stream start [00:01:15.687,000] <inf> main: Found position estimate: (lat, lon): (50.922447, 11.600006), alt: 192.64m, radius: 1.45m (17 SV used) [00:01:16.692,000] <inf> main: Found position estimate: (lat, lon): (50.922451, 11.600005), alt: 192.53m, radius: 1.45m (18 SV used) [00:01:17.697,000] <inf> main: Found position estimate: (lat, lon): (50.922451, 11.600004), alt: 192.63m, radius: 1.45m (18 SV used) [00:01:18.904,000] <inf> main: Found position estimate: (lat, lon): (50.922455, 11.600004), alt: 192.71m, radius: 1.46m (17 SV used) [00:01:19.658,000] <inf> main: Found position estimate: (lat, lon): (50.922455, 11.600004), alt: 192.80m, radius: 1.46m (18 SV used) [00:01:20.663,000] <inf> main: Found position estimate: (lat, lon): (50.922455, 11.600004), alt: 192.96m, radius: 1.46m (18 SV used) [00:01:21.667,000] <inf> main: Found position estimate: (lat, lon): (50.922455, 11.600003), alt: 192.89m, radius: 1.46m (18 SV used) [00:01:22.722,000] <inf> main: Found position estimate: (lat, lon): (50.922459, 11.600002), alt: 192.79m, radius: 1.47m (17 SV used) [00:01:23.929,000] <inf> main: Found position estimate: (lat, lon): (50.922459, 11.600001), alt: 192.92m, radius: 1.47m (18 SV used) [00:01:24.683,000] <inf> main: Found position estimate: (lat, lon): (50.922462, 11.600000), alt: 192.89m, radius: 1.48m (17 SV used) [00:01:25.688,000] <inf> main: Found position estimate: (lat, lon): (50.922462, 11.599999), alt: 192.77m, radius: 1.48m (18 SV used) [00:01:26.693,000] <inf> main: Found position estimate: (lat, lon): (50.922466, 11.599998), alt: 192.69m, radius: 1.48m (18 SV used) [00:01:27.697,000] <inf> main: Found position estimate: (lat, lon): (50.922466, 11.599996), alt: 192.49m, radius: 1.50m (18 SV used) uart:~$ gnss stream stop [00:01:28.905,000] <inf> main: Found position estimate: (lat, lon): (50.922470, 11.599995), alt: 192.22m, radius: 1.50m (18 SV used) [00:01:29.709,000] <inf> main: Found position estimate: (lat, lon): (50.922470, 11.599994), alt: 192.12m, radius: 1.50m (18 SV used) uart:~$ _