Skip to content
Merged
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
14 changes: 14 additions & 0 deletions drivers/gnss/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ module = U_BLOX_M10_I2C
module-str = u-blox M10
source "subsys/logging/Kconfig.template.log_config"

config GNSS_U_BLOX_M10_PIPE_SIZE
int "UBX modem pipe size"
range 128 2048
default 512
help
Maximum number of bytes that can be stored in the pipe buffer.

config GNSS_U_BLOX_M10_MAX_MSG_SIZE
int "UBX modem pipe size"
range 128 512
default 256
help
Maximum size of a UBX message that driver can handle.

config GNSS_U_BLOX_M10_NO_API_COMPAT
bool "Drop compatibility with the Zephyr GNSS API"
help
Expand Down
85 changes: 63 additions & 22 deletions drivers/gnss/gnss_ubx_modem.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,42 +112,83 @@ static void ubx_msg_handle(struct ubx_modem_data *modem, struct ubx_frame *frame
static void fifo_read_runner(struct k_work *work)
{
struct ubx_modem_data *modem = CONTAINER_OF(work, struct ubx_modem_data, fifo_read_worker);

struct ubx_frame *frame;
struct ubx_frame *frame = (void *)(modem->rx_buffer);
uint16_t payload_len;
uint16_t message_len;
uint16_t to_read;
int received;

/* Read data from pipe */
received = modem_pipe_receive(modem->pipe, modem->rx_buffer, sizeof(modem->rx_buffer));
if (received <= 0) {
LOG_ERR("Failed to receive (%d)", received);
return;
}
while (true) {
/* Pull single bytes until sync bytes found */
while (modem->rx_buffer_pending < 2) {
if (modem_pipe_receive(modem->pipe,
modem->rx_buffer + modem->rx_buffer_pending,
1) <= 0) {
return;
}

/* Process received data for UBX frames (don't handle partial frames) */
for (int i = 0; i < received - sizeof(*frame); i++) {
frame = (void *)(modem->rx_buffer + i);
/* Skip until we find the sync characters */
if ((frame->preamble_sync_char_1 != UBX_PREAMBLE_SYNC_CHAR_1) ||
(frame->preamble_sync_char_2 != UBX_PREAMBLE_SYNC_CHAR_2)) {
continue;
if ((modem->rx_buffer_pending) == 0 &&
(frame->preamble_sync_char_1 != UBX_PREAMBLE_SYNC_CHAR_1)) {
continue;
}
if ((modem->rx_buffer_pending) == 1 &&
(frame->preamble_sync_char_2 != UBX_PREAMBLE_SYNC_CHAR_2)) {
modem->rx_buffer_pending = 0;
continue;
}
modem->rx_buffer_pending++;
}

/* Pull remainder of frame header */
if (modem->rx_buffer_pending < sizeof(*frame)) {
to_read = sizeof(*frame) - modem->rx_buffer_pending;
received = modem_pipe_receive(
modem->pipe, modem->rx_buffer + modem->rx_buffer_pending, to_read);
if (received < 0) {
return;
}
modem->rx_buffer_pending += received;
if (received != to_read) {
return;
}
}

payload_len = (((uint16_t)frame->payload_size_high) << 8) | frame->payload_size_low;
message_len = sizeof(*frame) + payload_len + sizeof(uint16_t);

/* Validate complete message can fit */
if (message_len >= sizeof(modem->rx_buffer)) {
LOG_ERR("RX MSG: %02X:%02X too large (%d)", frame->message_class,
frame->message_id, message_len);
/* Consume any part of the message still in queue */
modem_pipe_receive(modem->pipe, modem->rx_buffer, sizeof(modem->rx_buffer));
/* Reset stored buffer and exit */
modem->rx_buffer_pending = 0;
return;
}

/* Attempt to pull remaining message payload */
to_read = message_len - modem->rx_buffer_pending;
received = modem_pipe_receive(modem->pipe,
modem->rx_buffer + modem->rx_buffer_pending, to_read);
if (received < 0) {
return;
}
modem->rx_buffer_pending += received;
if (received != to_read) {
LOG_DBG("Waiting on %d", to_read - received);
return;
}

LOG_DBG("RX MSG: CLS=0x%02x ID=0x%02x LEN=%d", frame->message_class,
frame->message_id, payload_len);
LOG_HEXDUMP_DBG(frame->payload_and_checksum, payload_len, "Payload");
if (i + sizeof(*frame) + payload_len + sizeof(uint16_t) > received) {
LOG_WRN("Partial frame (%02x.%02x) received, dropping!",
frame->message_class, frame->message_id);
break;
}

/* Process frame */
ubx_msg_handle(modem, frame, payload_len);

/* Header, payload, checksum, -1 to account for loop incr */
i += sizeof(*frame) + payload_len + sizeof(uint16_t) - 1;
/* Complete */
modem->rx_buffer_pending = 0;
}
}

Expand Down
1 change: 1 addition & 0 deletions include/infuse/gnss/ubx/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ static inline void ubx_msg_prepare_valset(struct net_buf_simple *buf, uint8_t la
*
* @param buf Buffer to prepare
* @param layer Layer to query configuration for
* @param offset Start value offset for query
*/
static inline void ubx_msg_prepare_valget(struct net_buf_simple *buf, uint8_t layer, uint8_t offset)
{
Expand Down
5 changes: 4 additions & 1 deletion include/infuse/gnss/ubx/modem.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <zephyr/kernel.h>
#include <zephyr/net/buf.h>
#include <zephyr/modem/pipe.h>
#include <zephyr/sys/ring_buffer.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -81,7 +82,9 @@ struct ubx_modem_data {
/* List of message handlers */
sys_slist_t handlers;
/* Data buffer to read bytes into */
uint8_t rx_buffer[1024];
uint8_t rx_buffer[CONFIG_GNSS_U_BLOX_M10_MAX_MSG_SIZE];
/* Bytes pending in rx_buffer */
uint16_t rx_buffer_pending;
};

/**
Expand Down
9 changes: 7 additions & 2 deletions include/infuse/modem/backend/u_blox_i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/ring_buffer.h>

#include <zephyr/modem/pipe.h>

Expand All @@ -25,8 +26,10 @@ struct modem_backend_ublox_i2c {
const struct gpio_dt_spec *data_ready;
/* Communication pipe */
struct modem_pipe pipe;
/* Worker that polls the number of pending FIFO bytes */
struct k_work_delayable pending_bytes_query;
/* Ring buffer for holding pipe data stream */
struct ring_buf pipe_ring_buf;
/* Worker that reads the FIFO */
struct k_work_delayable fifo_read;
/* Signal to notify when FIFO read completes */
struct k_poll_signal read_result;
/* Callback for data ready GPIO */
Expand All @@ -39,6 +42,8 @@ struct modem_backend_ublox_i2c {
uint16_t bytes_pending;
/* Internal state flags */
uint8_t flags;
/* Backing memory for pipe data stream */
uint8_t pipe_memory[CONFIG_GNSS_U_BLOX_M10_PIPE_SIZE];
};

struct modem_backend_ublox_i2c_config {
Expand Down
1 change: 1 addition & 0 deletions subsys/modem/backends/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ config MODEM_BACKEND_U_BLOX_I2C
bool "u-blox I2C modem backend"
select MODEM_PIPE
select POLL
select RING_BUFFER
depends on I2C_RTIO
Loading
Loading