Skip to content

GNSS RTK: Add basic integration #90890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1569,21 +1569,26 @@ Release Notes:
collaborators:
- tomi-font
- fabiobaltieri
- ubieda
files:
- doc/hardware/peripherals/gnss.rst
- drivers/gnss/
- include/zephyr/data/navigation.h
- include/zephyr/drivers/gnss.h
- include/zephyr/drivers/gnss/
- include/zephyr/gnss/
- dts/bindings/gnss/
- include/zephyr/dt-bindings/gnss/
- tests/drivers/build_all/gnss/
- tests/drivers/gnss/
- tests/subsys/gnss/
- samples/drivers/gnss/
- subsys/gnss/
labels:
- "area: GNSS"
tests:
- drivers.gnss
- gnss

"Drivers: Haptics":
status: maintained
Expand Down
4 changes: 4 additions & 0 deletions cmake/linker_script/common/common-rom.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,7 @@ endif()
if(CONFIG_GNSS_SATELLITES)
zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION)
endif()

if(CONFIG_GNSS_RTK)
zephyr_iterable_section(NAME gnss_rtk_data_callback KVMA RAM_REGION GROUP RODATA_REGION)
endif()
10 changes: 10 additions & 0 deletions drivers/gnss/Kconfig.u_blox_f9p
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ config GNSS_U_BLOX_F9P_SATELLITES_COUNT
default 24

endif # GNSS_SATELLITES

if GNSS_RTK

config GNSS_U_BLOX_F9P_RTK
bool "Use RTK to improve fix accuracy"
default y
depends on GNSS_RTK_PROTOCOL_RTCM3

endif # GNSS_RTK

endif # GNSS_U_BLOX_F9P
34 changes: 33 additions & 1 deletion drivers/gnss/gnss_u_blox_f9p.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <zephyr/modem/backend/uart.h>

#include "gnss_ubx_common.h"
#include <zephyr/gnss/rtk/rtk.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ubx_f9p, CONFIG_GNSS_LOG_LEVEL);
Expand Down Expand Up @@ -81,6 +82,19 @@ UBX_FRAME_DEFINE(enable_nav,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_MSG_OUT_UBX_NAV_PVT_UART1, 1));
UBX_FRAME_DEFINE(nav_fix_mode_auto,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_NAV_CFG_FIX_MODE, UBX_FIX_MODE_AUTO));
UBX_FRAME_DEFINE(enable_prot_in_ubx,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_UART1_PROTO_IN_UBX, 1));
UBX_FRAME_DEFINE(enable_prot_in_rtcm3,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_UART1_PROTO_IN_RTCM3X, 1));
UBX_FRAME_DEFINE(enable_prot_out_ubx,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_UART1_PROTO_OUT_UBX, 1));
UBX_FRAME_DEFINE(disable_prot_out_rtcm3,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_UART1_PROTO_OUT_RTCM3X, 0));
UBX_FRAME_DEFINE(enable_ubx_rtcm_rsp,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_MSG_OUT_UBX_RXM_RTCM_UART1, 1));
UBX_FRAME_DEFINE(set_rtk_fix_mode,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_NAV_HP_CFG_GNSS_MODE,
UBX_NAV_HP_DGNSS_MODE_RTK_FIXED));
#if CONFIG_GNSS_SATELLITES
UBX_FRAME_DEFINE(enable_sat,
UBX_FRAME_CFG_VAL_SET_U8_INITIALIZER(UBX_KEY_MSG_OUT_UBX_NAV_SAT_UART1, 1));
Expand All @@ -91,6 +105,8 @@ UBX_FRAME_ARRAY_DEFINE(u_blox_f9p_init_seq,
&disable_nmea_gbs, &disable_nmea_gll, &disable_nmea_gns, &disable_nmea_grs,
&disable_nmea_gsa, &disable_nmea_gst, &disable_nmea_vlw, &disable_nmea_vtg,
&disable_nmea_zda, &enable_nav, &nav_fix_mode_auto,
&enable_prot_in_ubx, &enable_prot_in_rtcm3, &enable_prot_out_ubx,
&disable_prot_out_rtcm3, &enable_ubx_rtcm_rsp, &set_rtk_fix_mode,
#if CONFIG_GNSS_SATELLITES
&enable_sat,
#endif
Expand Down Expand Up @@ -153,7 +169,7 @@ static int ubx_f9p_msg_send(const struct device *dev, const struct ubx_frame *re
data->script.inst.retry_count = wait_for_ack ? 2 : 0;
data->script.inst.match.filter.class = wait_for_ack ? UBX_CLASS_ID_ACK : 0;
data->script.inst.match.filter.id = UBX_MSG_ID_ACK;
data->script.inst.request.buf = req;
data->script.inst.request.buf = (const void *)req;
data->script.inst.request.len = len;

err = modem_ubx_run_script(&data->ubx.inst, &data->script.inst);
Expand Down Expand Up @@ -187,6 +203,19 @@ static int ubx_f9p_msg_payload_send(const struct device *dev, uint8_t class, uin
return err;
}

#if CONFIG_GNSS_U_BLOX_F9P_RTK

static void f9p_rtk_data_cb(const struct device *dev, const struct gnss_rtk_data *data)
{
/** In this case, we forward the frame directly to the modem. It can either use
* it or not depending on the RTCM3 message type and its alignment with what the
* GNSS modem has observed.
*/
(void)ubx_f9p_msg_send(dev, (const void *)data->data, data->len, false);
Copy link
Preview

Copilot AI Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast to const void * may conflict with the expected const struct ubx_frame * parameter of ubx_f9p_msg_send. Use (const struct ubx_frame *)data->data to avoid pointer-type mismatch warnings.

Suggested change
(void)ubx_f9p_msg_send(dev, (const void *)data->data, data->len, false);
(void)ubx_f9p_msg_send(dev, (const struct ubx_frame *)data->data, data->len, false);

Copilot uses AI. Check for mistakes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should cast this to an UBX frame, as it's an RTCM3 msg. See commit:
modem: ubx: Change request buffer to be void

}

#endif /* CONFIG_GNSS_U_BLOX_F9P_RTK */

static inline int init_modem(const struct device *dev)
{
int err;
Expand Down Expand Up @@ -516,6 +545,9 @@ static DEVICE_API(gnss, ublox_f9p_driver_api) = {
\
static struct ubx_f9p_data ubx_f9p_data_##inst; \
\
IF_ENABLED(CONFIG_GNSS_U_BLOX_F9P_RTK, \
(GNSS_RTK_DATA_CALLBACK_DEFINE(DEVICE_DT_INST_GET(inst), f9p_rtk_data_cb))); \
\
DEVICE_DT_INST_DEFINE(inst, \
ublox_f9p_init, \
NULL, \
Expand Down
2 changes: 1 addition & 1 deletion drivers/gnss/gnss_u_blox_m8.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ static int ubx_m8_msg_send(const struct device *dev, const struct ubx_frame *req
data->script.inst.retry_count = wait_for_ack ? 2 : 0;
data->script.inst.match.filter.class = wait_for_ack ? UBX_CLASS_ID_ACK : 0;
data->script.inst.match.filter.id = UBX_MSG_ID_ACK;
data->script.inst.request.buf = req;
data->script.inst.request.buf = (const void *)req;
data->script.inst.request.len = len;

err = modem_ubx_run_script(&data->ubx.inst, &data->script.inst);
Expand Down
24 changes: 15 additions & 9 deletions drivers/gnss/gnss_ubx_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,24 @@ void gnss_ubx_common_pvt_callback(struct modem_ubx *ubx, const struct ubx_frame
if ((nav_pvt->flags & UBX_NAV_PVT_FLAGS_GNSS_FIX_OK) &&
!(nav_pvt->nav.flags3 & UBX_NAV_PVT_FLAGS3_INVALID_LLH)) {

switch (nav_pvt->fix_type) {
case UBX_NAV_FIX_TYPE_DR:
case UBX_NAV_FIX_TYPE_GNSS_DR_COMBINED:
if (nav_pvt->flags & UBX_NAV_PVT_FLAGS_GNSS_CARR_SOLN_FLOATING) {
fix_quality = GNSS_FIX_QUALITY_FLOAT_RTK;
fix_status = GNSS_FIX_STATUS_DGNSS_FIX;
} else if (nav_pvt->flags & UBX_NAV_PVT_FLAGS_GNSS_CARR_SOLN_FIXED) {
fix_quality = GNSS_FIX_QUALITY_RTK;
fix_status = GNSS_FIX_STATUS_DGNSS_FIX;
} else if (
(nav_pvt->fix_type == UBX_NAV_FIX_TYPE_GNSS_DR_COMBINED) ||
(nav_pvt->fix_type == UBX_NAV_FIX_TYPE_DR)) {

fix_quality = GNSS_FIX_QUALITY_ESTIMATED;
fix_status = GNSS_FIX_STATUS_ESTIMATED_FIX;
break;
case UBX_NAV_FIX_TYPE_2D:
case UBX_NAV_FIX_TYPE_3D:
} else if (
(nav_pvt->fix_type == UBX_NAV_FIX_TYPE_2D) ||
(nav_pvt->fix_type == UBX_NAV_FIX_TYPE_3D)) {

fix_quality = GNSS_FIX_QUALITY_GNSS_SPS;
fix_status = GNSS_FIX_STATUS_GNSS_FIX;
break;
default:
break;
}
}

Expand Down Expand Up @@ -127,6 +132,7 @@ void gnss_ubx_common_satellite_callback(struct modem_ubx *ubx, const struct ubx_
.azimuth = ubx_sat->sat[i].azimuth,
.system = gnss_system,
.is_tracked = (ubx_sat->sat[i].flags & UBX_NAV_SAT_FLAGS_SV_USED),
.is_corrected = (ubx_sat->sat[i].flags & UBX_NAV_SAT_FLAGS_RTCM_CORR_USED)
};

data->satellites.data[i] = sat;
Expand Down
2 changes: 2 additions & 0 deletions include/zephyr/drivers/gnss.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ struct gnss_satellite {
enum gnss_system system;
/** True if satellite is being tracked */
uint8_t is_tracked : 1;
/** True if satellite tracking has RTK corrections */
uint8_t is_corrected : 1;
};

/** Template for GNSS satellites callback */
Expand Down
32 changes: 32 additions & 0 deletions include/zephyr/gnss/rtk/decoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2025 Croxel Inc.
* Copyright (c) 2025 CogniPilot Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_
#define ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_

#include <stdint.h>
#include <stddef.h>

/**
* @brief Get an RTK frame from buffer
*
* Used by RTK clients to extract frames from a data-buffer.
*
* @param[in] buf Buffer holding encoded data.
* @param[in] buf_len Buffer length.
* @param[out] data Pointer to the decoded frame.
* @param[out] data_len Length of the decoded frame
*
* @return Zero if successful.
* @return -ENOENT if no frames have been decoded successfully.
* @return -EAGAIN if there's an incomplete frame starting at the data pointer.
* @return Other negative error code if decoding failed.
*/
int gnss_rtk_decoder_frame_get(uint8_t *buf, size_t buf_len,
uint8_t **data, size_t *data_len);

#endif /* ZEPHYR_INCLUDE_GNSS_RTK_DECODER_H_ */
47 changes: 47 additions & 0 deletions include/zephyr/gnss/rtk/rtk.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2023 Trackunit Corporation
* Copyright (c) 2025 Croxel Inc.
* Copyright (c) 2025 CogniPilot Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_
#define ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stddef.h>

struct gnss_rtk_data {
const uint8_t *data;
size_t len;
};

typedef void (*gnss_rtk_data_callback_t)(const struct device *dev,
const struct gnss_rtk_data *data);

struct gnss_rtk_data_callback {
const struct device *dev;
gnss_rtk_data_callback_t callback;
};

#if CONFIG_GNSS_RTK
#define GNSS_RTK_DATA_CALLBACK_DEFINE(_dev, _callback) \
static const STRUCT_SECTION_ITERABLE(gnss_rtk_data_callback, \
_gnss_rtk_data_callback__##_callback) = { \
.dev = _dev, \
.callback = _callback, \
}
#else
#define GNSS_RTK_DATA_CALLBACK_DEFINE(_dev, _callback)
#endif

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_GNSS_RTK_RTK_H_ */
18 changes: 18 additions & 0 deletions include/zephyr/gnss/rtk/rtk_publish.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2025 Croxel Inc.
* Copyright (c) 2025 CogniPilot Foundation
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_
#define ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_

#include <stdint.h>
#include <stddef.h>
#include <zephyr/gnss/rtk/rtk.h>

/* Internal function used by RTK clients to publish data-correction. */
void gnss_rtk_publish_data(const struct gnss_rtk_data *data);

#endif /* ZEPHYR_INCLUDE_GNSS_RTK_PUBLISH_H_ */
4 changes: 4 additions & 0 deletions include/zephyr/linker/common-rom/common-rom-misc.ld
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,7 @@
#if defined(CONFIG_GNSS_SATELLITES)
ITERABLE_SECTION_ROM(gnss_satellites_callback, Z_LINK_ITERABLE_SUBALIGN)
#endif

#if defined(CONFIG_GNSS_RTK)
ITERABLE_SECTION_ROM(gnss_rtk_data_callback, Z_LINK_ITERABLE_SUBALIGN)
#endif
2 changes: 1 addition & 1 deletion include/zephyr/modem/ubx.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct modem_ubx_match {

struct modem_ubx_script {
struct {
const struct ubx_frame *buf;
const void *buf;
uint16_t len;
} request;
struct {
Expand Down
14 changes: 14 additions & 0 deletions include/zephyr/modem/ubx/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum ubx_keys_msg_out {
UBX_KEY_MSG_OUT_NMEA_ZDA_UART1 = 0x209100d9,
UBX_KEY_MSG_OUT_UBX_NAV_PVT_UART1 = 0x20910007,
UBX_KEY_MSG_OUT_UBX_NAV_SAT_UART1 = 0x20910016,
UBX_KEY_MSG_OUT_UBX_RXM_RTCM_UART1 = 0x20910269,
};

enum ubx_keys_rate {
Expand All @@ -36,4 +37,17 @@ enum ubx_keys_nav_cfg {
UBX_KEY_NAV_CFG_DYN_MODEL = 0x20110021,
};

enum ubx_keys_uart1_proto {
UBX_KEY_UART1_PROTO_IN_UBX = 0x10730001,
UBX_KEY_UART1_PROTO_IN_NMEA = 0x10730002,
UBX_KEY_UART1_PROTO_IN_RTCM3X = 0x10730004,
UBX_KEY_UART1_PROTO_OUT_UBX = 0x10740001,
UBX_KEY_UART1_PROTO_OUT_NMEA = 0x10740002,
UBX_KEY_UART1_PROTO_OUT_RTCM3X = 0x10740004,
};

enum ubx_keys_nav_hp_cfg {
UBX_KEY_NAV_HP_CFG_GNSS_MODE = 0x20140011,
};

#endif /* ZEPHYR_MODEM_UBX_KEYS_ */
8 changes: 8 additions & 0 deletions include/zephyr/modem/ubx/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,19 @@ enum ubx_nav_fix_type {
UBX_NAV_FIX_TYPE_TIME_ONLY = 5,
};

enum ubx_nav_hp_dgnss_mode {
UBX_NAV_HP_DGNSS_MODE_RTK_FLOAT = 2,
UBX_NAV_HP_DGNSS_MODE_RTK_FIXED = 3,
};

#define UBX_NAV_PVT_VALID_DATE BIT(0)
#define UBX_NAV_PVT_VALID_TIME BIT(1)
#define UBX_NAV_PVT_VALID_UTC_TOD BIT(2)
#define UBX_NAV_PVT_VALID_MAGN BIT(3)

#define UBX_NAV_PVT_FLAGS_GNSS_FIX_OK BIT(0)
#define UBX_NAV_PVT_FLAGS_GNSS_CARR_SOLN_FLOATING BIT(6)
#define UBX_NAV_PVT_FLAGS_GNSS_CARR_SOLN_FIXED BIT(7)

#define UBX_NAV_PVT_FLAGS3_INVALID_LLH BIT(0)

Expand Down Expand Up @@ -143,6 +150,7 @@ enum ubx_gnss_id {
};

#define UBX_NAV_SAT_FLAGS_SV_USED BIT(3)
#define UBX_NAV_SAT_FLAGS_RTCM_CORR_USED BIT(17)

struct ubx_nav_sat {
uint32_t itow;
Expand Down
11 changes: 11 additions & 0 deletions include/zephyr/sys/crc.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,17 @@ uint32_t crc24_pgp(const uint8_t *data, size_t len);
*/
uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len);

/**
* @brief Calculate an RTCM3 CRC24Q frame checksum
*
* @param[in] data RTCM3 Frame
* @param[in] len Frame length in bytes.
*
* @return 0 if the data-frame contains a checksum and it matches.
* @return Result if data-frame does not contain checksum.
*/
uint32_t crc24q_rtcm3(const uint8_t *data, size_t len);

/**
* @brief Compute a CRC checksum, in a generic way.
*
Expand Down
Loading