Skip to content

Commit 1fd2bdb

Browse files
committed
gnss: rtk: Add basic integration
This patch incorporates the basic RTK API as well as a basic client integration (Serial) as a way to receive and publish the RTK data. Specifically, this patch includes: - API additions. - RTCM3 frame decoding. - Unit testsuite for RTCM3 frame decoding. - Serial client to receive and publish RTK data corrections. - GNSS RTK sample with simple base-station script over serial and Zephyr app displaying data-corrections applied. Signed-off-by: Luis Ubieda <luisf@croxel.com>
1 parent c576464 commit 1fd2bdb

29 files changed

+732
-0
lines changed

cmake/linker_script/common/common-rom.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,7 @@ endif()
258258
if(CONFIG_GNSS_SATELLITES)
259259
zephyr_iterable_section(NAME gnss_satellites_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
260260
endif()
261+
262+
if(CONFIG_GNSS_RTK)
263+
zephyr_iterable_section(NAME rtk_data_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
264+
endif()

include/zephyr/linker/common-rom/common-rom-misc.ld

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@
6868
#if defined(CONFIG_GNSS_SATELLITES)
6969
ITERABLE_SECTION_ROM(gnss_satellites_callback, Z_LINK_ITERABLE_SUBALIGN)
7070
#endif
71+
72+
#if defined(CONFIG_GNSS_RTK)
73+
ITERABLE_SECTION_ROM(rtk_data_callback, Z_LINK_ITERABLE_SUBALIGN)
74+
#endif

include/zephyr/rtk/decoder.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_INCLUDE_RTK_DECODER_H_
9+
#define ZEPHYR_INCLUDE_RTK_DECODER_H_
10+
11+
#include <stdint.h>
12+
#include <stddef.h>
13+
14+
/**
15+
* @brief Get an RTK frame from buffer
16+
*
17+
* Used by RTK clients to extract frames from a data-buffer.
18+
*
19+
* @param[in] buf Buffer holding encoded data.
20+
* @param[in] buf_len Buffer length.
21+
* @param[out] data Pointer to the decoded frame.
22+
* @param[out] data_len Length of the decoded frame
23+
*
24+
* @return Zero if successful.
25+
* @return -ENOENT if no frames have been decoded successfully.
26+
* @return -EAGAIN if there's an incomplete frame starting at the data pointer.
27+
* @return Other negative error code if decoding failed.
28+
*/
29+
int rtk_decoder_frame_get(uint8_t *buf, size_t buf_len,
30+
uint8_t **data, size_t *data_len);
31+
32+
#endif /* ZEPHYR_INCLUDE_RTK_DECODER_H_ */

include/zephyr/rtk/rtk.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2023 Trackunit Corporation
3+
* Copyright (c) 2025 Croxel Inc.
4+
* Copyright (c) 2025 CogniPilot Foundation
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#ifndef ZEPHYR_INCLUDE_RTK_RTK_H_
10+
#define ZEPHYR_INCLUDE_RTK_RTK_H_
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#include <stdint.h>
17+
#include <stddef.h>
18+
19+
struct rtk_data {
20+
const uint8_t *data;
21+
size_t len;
22+
};
23+
24+
typedef void (*rtk_data_callback_t)(const struct device *dev, const struct rtk_data *data);
25+
26+
struct rtk_data_callback {
27+
const struct device *dev;
28+
rtk_data_callback_t callback;
29+
};
30+
31+
#if CONFIG_GNSS_RTK
32+
#define RTK_DATA_CALLBACK_DEFINE(_dev, _callback) \
33+
static const STRUCT_SECTION_ITERABLE(rtk_data_callback, \
34+
_rtk_data_callback__##_callback) = { \
35+
.dev = _dev, \
36+
.callback = _callback, \
37+
}
38+
#else
39+
#define RTK_DATA_CALLBACK_DEFINE(_dev, _callback)
40+
#endif
41+
42+
/**
43+
* @}
44+
*/
45+
46+
#ifdef __cplusplus
47+
}
48+
#endif
49+
50+
51+
#endif /* ZEPHYR_INCLUDE_RTK_RTK_H_ */

include/zephyr/rtk/rtk_publish.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_INCLUDE_RTK_RTK_PUBLISH_H_
9+
#define ZEPHYR_INCLUDE_RTK_RTK_PUBLISH_H_
10+
11+
#include <stdint.h>
12+
#include <stddef.h>
13+
#include <zephyr/rtk/rtk.h>
14+
15+
/* Internal function used by RTK clients to publish data-correction. */
16+
void rtk_publish_data(const struct rtk_data *data);
17+
18+
#endif /* ZEPHYR_INCLUDE_RTK_RTK_H_ */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2023 Trackunit Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
cmake_minimum_required(VERSION 3.20.0)
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(gnss_sample)
7+
8+
target_sources(app PRIVATE src/main.c)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright (c) 2025, Croxel Inc
2+
# Copyright (c) 2025, CogniPilot Foundation
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
import pyrtcm
7+
import pyubx2
8+
import serial
9+
10+
11+
def enableBaseStationMode(serialEndpoint: serial.Serial):
12+
13+
frame = pyubx2.UBXMessage.config_set(layers=1, transaction=0,
14+
cfgData=[
15+
("CFG_MSGOUT_RTCM_3X_TYPE1005_USB", 1),
16+
("CFG_MSGOUT_RTCM_3X_TYPE1074_USB", 1),
17+
("CFG_MSGOUT_RTCM_3X_TYPE1077_USB", 1),
18+
("CFG_MSGOUT_RTCM_3X_TYPE1084_USB", 1),
19+
("CFG_MSGOUT_RTCM_3X_TYPE1087_USB", 1),
20+
("CFG_MSGOUT_RTCM_3X_TYPE1094_USB", 1),
21+
("CFG_MSGOUT_RTCM_3X_TYPE1097_USB", 1),
22+
("CFG_MSGOUT_RTCM_3X_TYPE1124_USB", 1),
23+
("CFG_MSGOUT_RTCM_3X_TYPE1127_USB", 1),
24+
("CFG_MSGOUT_RTCM_3X_TYPE1230_USB", 1)])
25+
serialEndpoint.write(frame.serialize())
26+
27+
frame = pyubx2.UBXMessage.config_set(layers=1, transaction=0,
28+
cfgData=[
29+
("CFG_TMODE_MODE", 1),
30+
("CFG_TMODE_SVIN_ACC_LIMIT", 250),
31+
("CFG_TMODE_SVIN_MIN_DUR", 60)])
32+
serialEndpoint.write(frame.serialize())
33+
34+
with serial.Serial("/dev/ttyACM0", 115200) as serialIn, \
35+
serial.Serial("/dev/ttyUSB0", 115200) as serialOut:
36+
37+
enableBaseStationMode(serialIn)
38+
39+
for raw, parsed in pyrtcm.RTCMReader(serialIn):
40+
print(parsed)
41+
serialOut.write(raw)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_SHELL=n
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2024 (c) NXP
3+
* Copyright 2025 (c) Croxel Inc.
4+
* Copyright 2025 (c) CogniPilot Foundation
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
/ {
10+
aliases {
11+
gnss = &gnss;
12+
};
13+
chosen {
14+
zephyr,rtk-serial = &lpuart1;
15+
};
16+
};
17+
18+
&lpuart3 {
19+
status = "okay";
20+
current-speed = <115200>;
21+
22+
gnss: gnss {
23+
status = "okay";
24+
compatible = "u-blox,f9p";
25+
};
26+
};

samples/drivers/gnss_rtk/prj.conf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2023 Trackunit Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
CONFIG_GNSS=y
5+
CONFIG_GNSS_SATELLITES=y
6+
7+
CONFIG_GNSS_RTK=y
8+
CONFIG_GNSS_RTK_SERIAL=y
9+
10+
CONFIG_LOG=y
11+
CONFIG_LOG_BUFFER_SIZE=8192
12+
CONFIG_GNSS_DUMP_TO_LOG=y
13+
CONFIG_GNSS_DUMP_TO_LOG_BUF_SIZE=1024
14+
CONFIG_GNSS_LOG_LEVEL_DBG=y
15+
CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y

0 commit comments

Comments
 (0)