Files
gps/soc/software/gps_system/tests/test_gps_acq_manager.c
T
onur 30179df8e6 feat(gps): add timer-based assisted reacquisition
Remove the fixed pseudorange start offset, preserve per-PRN navigation assistance across RF loss and power cycles, and seed coherent navigation measurement phase on reacquisition. Add full LNAV almanac visibility scheduling, power-safe QSPI journaling, RF-domain reset isolation, and PPS Gray CDC hardening with Linux, sanitizer, RTL, and end-to-end coverage.
2026-08-04 02:58:11 +03:00

197 lines
6.5 KiB
C

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include "gps/gps_acq_manager.h"
static gps_acq_manager_t make_manager(
uint64_t retry_delay,
uint64_t hot_retry_delay,
uint64_t hot_window,
unsigned int max_hot_streak)
{
gps_acq_manager_t manager;
const gps_acq_manager_config_t config = {
.retry_delay_ticks = retry_delay,
.hot_retry_delay_ticks = hot_retry_delay,
.hot_window_ticks = hot_window,
.unknown_probe_interval_ticks = 2u,
.visibility_probe_interval_ticks = 60u,
.max_hot_streak = max_hot_streak
};
gps_acq_manager_init(&manager, &config);
return manager;
}
static unsigned int start_next(
gps_acq_manager_t* manager,
uint64_t now,
bool expected_hot)
{
unsigned int prn = GPS_ACQ_MANAGER_INVALID_PRN;
bool hot = !expected_hot;
assert(gps_acq_manager_start_next(manager, now, &prn, &hot));
assert(hot == expected_hot);
return prn;
}
static void test_cold_round_robin_and_retry_from_tick_zero(void)
{
gps_acq_manager_t manager =
make_manager(5u, 5u, 100u, 4u);
assert(gps_acq_manager_enable_cold(&manager, 0u));
assert(gps_acq_manager_enable_cold(&manager, 1u));
assert(gps_acq_manager_enable_cold(&manager, 2u));
assert(start_next(&manager, 0u, false) == 0u);
/* A tick-zero attempt is real and must still observe retry delay. */
gps_acq_manager_mark_failed(&manager, 0u, 0u);
assert(start_next(&manager, 0u, false) == 1u);
gps_acq_manager_mark_failed(&manager, 1u, 0u);
assert(start_next(&manager, 0u, false) == 2u);
gps_acq_manager_mark_failed(&manager, 2u, 0u);
unsigned int ignored;
assert(!gps_acq_manager_start_next(
&manager, 4u, &ignored, NULL));
assert(start_next(&manager, 5u, false) == 0u);
}
static void test_hot_priority_round_robin_and_cold_fairness(void)
{
gps_acq_manager_t manager =
make_manager(1u, 1u, 100u, 2u);
assert(gps_acq_manager_enable_cold(&manager, 0u));
assert(gps_acq_manager_enable_cold(&manager, 1u));
gps_acq_manager_mark_lost(&manager, 7u, 10u);
gps_acq_manager_mark_lost(&manager, 8u, 10u);
assert(start_next(&manager, 10u, true) == 7u);
gps_acq_manager_mark_failed(&manager, 7u, 11u);
assert(start_next(&manager, 11u, true) == 8u);
gps_acq_manager_mark_failed(&manager, 8u, 12u);
/* Two hot attempts force one cold discovery attempt. */
assert(start_next(&manager, 12u, false) == 0u);
gps_acq_manager_mark_failed(&manager, 0u, 13u);
assert(start_next(&manager, 13u, true) == 7u);
}
static void test_expired_hot_becomes_cold_and_tracking_is_excluded(void)
{
gps_acq_manager_t manager =
make_manager(1u, 1u, 10u, 4u);
assert(gps_acq_manager_enable_cold(&manager, 2u));
gps_acq_manager_mark_lost(&manager, 9u, 20u);
unsigned int prn = start_next(&manager, 31u, false);
assert(prn == 2u);
gps_acq_manager_mark_tracking(&manager, prn);
prn = start_next(&manager, 31u, false);
assert(prn == 9u);
gps_acq_manager_mark_acquired(&manager, prn);
unsigned int ignored;
assert(!gps_acq_manager_start_next(
&manager, 100u, &ignored, NULL));
gps_acq_manager_mark_tracking(&manager, 9u);
gps_acq_manager_mark_stale(&manager, 9u);
assert(gps_acq_manager_state(&manager, 9u) ==
GPS_ACQ_PRN_STALE);
gps_acq_manager_mark_lost(&manager, 9u, 101u);
assert(gps_acq_manager_state(&manager, 9u) ==
GPS_ACQ_PRN_HOT);
}
static void test_invalid_inputs_are_safe(void)
{
gps_acq_manager_t manager =
make_manager(1u, 1u, 10u, 0u);
assert(!gps_acq_manager_enable_cold(
&manager, GPS_ACQ_MANAGER_PRN_COUNT));
assert(gps_acq_manager_state(
&manager, GPS_ACQ_MANAGER_PRN_COUNT) ==
GPS_ACQ_PRN_DISABLED);
assert(!gps_acq_manager_start_next(NULL, 0u, NULL, NULL));
assert(gps_acq_manager_count_searchable(NULL) == 0u);
}
static void test_failed_hot_search_is_backed_off(void)
{
gps_acq_manager_t manager =
make_manager(1u, 30u, 100u, 4u);
assert(gps_acq_manager_enable_cold(&manager, 0u));
gps_acq_manager_mark_lost(&manager, 20u, 0u);
assert(start_next(&manager, 0u, true) == 20u);
gps_acq_manager_mark_failed(&manager, 20u, 5u);
assert(start_next(&manager, 5u, false) == 0u);
gps_acq_manager_mark_failed(&manager, 0u, 6u);
assert(start_next(&manager, 7u, false) == 0u);
gps_acq_manager_mark_failed(&manager, 0u, 8u);
assert(start_next(&manager, 35u, true) == 20u);
}
static void test_visibility_priority_discovery_and_safety_probe(void)
{
gps_acq_manager_t manager =
make_manager(1u, 1u, 100u, 4u);
for(unsigned int prn = 1u ; prn <= 4u ; prn++)
{
assert(gps_acq_manager_enable_cold(&manager, prn));
}
assert(gps_acq_manager_set_visibility(
&manager, 1u, true, true, 400));
assert(gps_acq_manager_set_visibility(
&manager, 2u, true, false, -100));
assert(gps_acq_manager_set_visibility(
&manager, 3u, true, true, 200));
assert(gps_acq_manager_set_visibility(
&manager, 4u, false, false, 0));
gps_acq_manager_set_visibility_mode(&manager, true, 10u);
/* Highest predicted elevation wins, independent of numeric PRN. */
assert(start_next(&manager, 10u, false) == 1u);
/* Keep the highest predicted-visible satellite absent and retryable. This
* used to starve every unknown PRN forever. */
gps_acq_manager_mark_failed(&manager, 1u, 10u);
assert(start_next(&manager, 11u, false) == 1u);
gps_acq_manager_mark_failed(&manager, 1u, 11u);
/* The independent discovery deadline overrides that failing visible
* candidate and advances through the unknown-orbit queue. */
assert(start_next(&manager, 12u, false) == 4u);
gps_acq_manager_mark_tracking(&manager, 4u);
assert(start_next(&manager, 12u, false) == 1u);
gps_acq_manager_mark_tracking(&manager, 1u);
assert(start_next(&manager, 12u, false) == 3u);
gps_acq_manager_mark_tracking(&manager, 3u);
unsigned int ignored;
assert(!gps_acq_manager_start_next(
&manager, 69u, &ignored, NULL));
/* Known below-mask PRNs are not scanned continuously. Exactly one is
* admitted when the slower stale-model safety probe becomes due. */
assert(start_next(&manager, 70u, false) == 2u);
gps_acq_manager_mark_failed(&manager, 2u, 70u);
assert(!gps_acq_manager_start_next(
&manager, 71u, &ignored, NULL));
/* Removing the position/time model restores full cold-search behavior. */
gps_acq_manager_set_visibility_mode(&manager, false, 72u);
assert(start_next(&manager, 72u, false) == 2u);
}
int main(void)
{
test_cold_round_robin_and_retry_from_tick_zero();
test_hot_priority_round_robin_and_cold_fairness();
test_expired_hot_becomes_cold_and_tracking_is_excluded();
test_invalid_inputs_are_safe();
test_failed_hot_search_is_backed_off();
test_visibility_priority_discovery_and_safety_probe();
puts("gps acquisition manager tests passed");
return 0;
}