fix(gps): make acquisition and reacquisition deterministic

This commit is contained in:
2026-07-24 20:13:33 +03:00
parent e57b19b4ee
commit 86dfbeafac
18 changed files with 1274 additions and 241 deletions
@@ -0,0 +1,83 @@
#ifndef GPS_ACQ_MANAGER_H
#define GPS_ACQ_MANAGER_H
#include <stdbool.h>
#include <stdint.h>
#define GPS_ACQ_MANAGER_PRN_COUNT 32u
#define GPS_ACQ_MANAGER_INVALID_PRN 0xffu
typedef enum {
GPS_ACQ_PRN_DISABLED = 0,
GPS_ACQ_PRN_COLD,
GPS_ACQ_PRN_HOT,
GPS_ACQ_PRN_ACQUIRING,
GPS_ACQ_PRN_ACQUIRED,
GPS_ACQ_PRN_TRACKING,
GPS_ACQ_PRN_STALE
} gps_acq_prn_state_t;
typedef struct {
uint64_t retry_delay_ticks;
uint64_t hot_retry_delay_ticks;
uint64_t hot_window_ticks;
unsigned int max_hot_streak;
} gps_acq_manager_config_t;
typedef struct {
gps_acq_prn_state_t state;
uint64_t last_attempt_tick;
uint64_t hot_until_tick;
bool has_attempted;
bool attempt_was_hot;
} gps_acq_prn_entry_t;
typedef struct {
gps_acq_manager_config_t config;
gps_acq_prn_entry_t prn[GPS_ACQ_MANAGER_PRN_COUNT];
unsigned int cold_cursor;
unsigned int hot_cursor;
unsigned int hot_streak;
} gps_acq_manager_t;
void gps_acq_manager_init(
gps_acq_manager_t* manager,
const gps_acq_manager_config_t* config);
bool gps_acq_manager_enable_cold(
gps_acq_manager_t* manager,
unsigned int prn);
gps_acq_prn_state_t gps_acq_manager_state(
const gps_acq_manager_t* manager,
unsigned int prn);
const char* gps_acq_manager_state_name(gps_acq_prn_state_t state);
void gps_acq_manager_mark_acquired(
gps_acq_manager_t* manager,
unsigned int prn);
void gps_acq_manager_mark_tracking(
gps_acq_manager_t* manager,
unsigned int prn);
void gps_acq_manager_mark_stale(
gps_acq_manager_t* manager,
unsigned int prn);
void gps_acq_manager_mark_lost(
gps_acq_manager_t* manager,
unsigned int prn,
uint64_t now);
void gps_acq_manager_mark_failed(
gps_acq_manager_t* manager,
unsigned int prn,
uint64_t now);
bool gps_acq_manager_start_next(
gps_acq_manager_t* manager,
uint64_t now,
unsigned int* prn_out,
bool* hot_out);
unsigned int gps_acq_manager_count_state(
const gps_acq_manager_t* manager,
gps_acq_prn_state_t state);
unsigned int gps_acq_manager_count_searchable(
const gps_acq_manager_t* manager);
#endif
@@ -0,0 +1,37 @@
#ifndef GPS_EPHEMERIS_CACHE_H
#define GPS_EPHEMERIS_CACHE_H
#include <stdbool.h>
#include <stdint.h>
#include "gps/gps_ip_defines.h"
typedef struct {
gps_ephemeris_t ephemeris;
uint64_t committed_tick;
bool valid;
} gps_ephemeris_cache_entry_t;
typedef struct {
gps_ephemeris_cache_entry_t entry[GPS_PRN_COUNT];
uint64_t max_age_ticks;
} gps_ephemeris_cache_t;
void gps_ephemeris_cache_init(
gps_ephemeris_cache_t* cache,
uint64_t max_age_ticks);
bool gps_ephemeris_cache_store(
gps_ephemeris_cache_t* cache,
unsigned int prn,
const gps_ephemeris_t* ephemeris,
uint64_t now);
bool gps_ephemeris_cache_restore(
gps_ephemeris_cache_t* cache,
unsigned int prn,
uint64_t now,
gps_ephemeris_t* ephemeris_out);
void gps_ephemeris_cache_invalidate(
gps_ephemeris_cache_t* cache,
unsigned int prn);
#endif
@@ -14,6 +14,8 @@
uint32_t how_anchor_rejected_total;
uint32_t satellite_connected_total;
uint32_t satellite_lost_total;
uint32_t ephemeris_cache_store_total;
uint32_t ephemeris_cache_restore_total;
uint32_t last_connected_prn;
uint32_t last_lost_prn;
uint64_t last_connected_tick;
@@ -42,6 +44,9 @@
gps_external_irq_handler_t handler);
void gps_irq_handler(void) GPS_IRQ_HANDLER_ATTR;
void gps_process_isr_events(void);
void gps_acq_configure_prns(
const unsigned char* prns,
unsigned int count);
void gps_acq_scheduler_run(void);
void gps_background_task(void);
bool gps_take_nav_epoch_snapshot(gps_nav_epoch_snapshot_t* snapshot);
@@ -9,7 +9,11 @@
#include "gps/matrixLib.h"
#include "gps/gps_macros.h"
#ifdef __riscv
#define GPS_IRQ_HANDLER_ATTR __attribute__((interrupt("machine"), aligned(4)))
#else
#define GPS_IRQ_HANDLER_ATTR
#endif
@@ -58,7 +62,14 @@
#define GPS_NAV_ENABLE_FDE 0u
#define GPS_PROFILE_CPU_HZ 50000000ULL
#define GPS_ACQ_RETRY_DELAY_TICKS (GPS_SYSTICK_HZ / 2u)
#define GPS_ACQ_STUCK_WARN_TICKS (GPS_SYSTICK_HZ * 2u)
#define GPS_ACQ_HOT_RETRY_DELAY_TICKS (GPS_SYSTICK_HZ * 30u)
#define GPS_ACQ_REACQ_PRIORITY_TICKS \
(GPS_SYSTICK_HZ * 2u * 60u * 60u)
#define GPS_ACQ_MAX_HOT_STREAK 4u
#define GPS_ACQ_STUCK_WARN_TICKS (GPS_SYSTICK_HZ * 8u)
#define GPS_EPHEMERIS_CACHE_MAX_AGE_TICKS \
(GPS_SYSTICK_HZ * 2u * 60u * 60u)
#define GPS_ACQ_STATUS_LOG_PERIOD_TICKS (GPS_SYSTICK_HZ * 5u)
#define GPS_NAV_STATUS_LOG_PERIOD_TICKS GPS_SYSTICK_HZ
#define GPS_TRK_MEASUREMENT_STALE_TICKS (GPS_SYSTICK_HZ * 3u)
#define GPS_NAV_ABS_SAMPLE_SYNC_WINDOW_MS 25u
@@ -223,15 +234,6 @@
uint32_t REM_CODE_PHASE_REG; // 'h4c
}gps_trck_t;
typedef enum {
GPS_SAT_NOT_SEEN = 0,
GPS_SAT_ACQUIRING,
GPS_SAT_ACQUIRED,
GPS_SAT_TRACKING,
GPS_SAT_LOST,
GPS_SAT_STALE
} gps_satellite_state_t;
typedef enum {
GPS_ACQ_ENGINE_IDLE = 0,
GPS_ACQ_ENGINE_BUSY
@@ -458,9 +460,13 @@
uint64_t gps_get_systick(void);
static inline uint64_t gps_read_cycle_counter(void)
{
#ifdef __riscv
uint64_t cycles;
asm volatile("rdcycle %0" : "=r"(cycles));
return cycles;
#else
return 0u;
#endif
}
bool gps_get_ionoutc(ionoutc_t* ionoutc);
void gps_background_task(void);
@@ -5,8 +5,8 @@
/*
* Verbosity is cumulative:
* 1: navigation result (position and all DOP values) plus tracked
* satellite count/PRN summary
* 1: navigation result (position and all DOP values), tracked
* satellite summary and low-rate acquisition/reacquisition status
* 2: reserved for additional status detail
* 3: state transitions, warnings/errors and integrity summary
* 4: performance, NAV satellite and low-level diagnostic detail
@@ -29,13 +29,7 @@ typedef struct gps_ephem_ll {
volatile bool gps_measurement_valid;
} gps_ephem_ll_t;
typedef struct gps_acq_ll {
unsigned int prn_no;
struct gps_acq_ll* next;
} gps_acq_ll_t;
extern volatile gps_ephem_ll_t* tracking_node;
extern volatile gps_acq_ll_t* acquisition_node;
bool insert_element(volatile gps_ephem_ll_t** node,
volatile gps_ephemeris_t* data_p,
@@ -45,8 +39,4 @@ bool trck_ip_exists(volatile gps_ephem_ll_t** node, unsigned char trck_ip_no);
volatile gps_ephem_ll_t* get_element_by_ip_number(volatile gps_ephem_ll_t** node,
unsigned char trck_ip_no);
bool insert_acq_element(volatile gps_acq_ll_t** node, unsigned int prn_no);
bool delete_acq_element_by_prn_number(volatile gps_acq_ll_t** node, unsigned int prn_no);
bool acq_prn_exists(volatile gps_acq_ll_t** node, unsigned int prn_no);
#endif