fix(gps): recover when tracking loss IRQ is missed
This commit is contained in:
@@ -15,13 +15,17 @@ typedef struct {
|
||||
gps_ephemeris_cache_t cache;
|
||||
bool visible[GPS_ACQ_MANAGER_PRN_COUNT];
|
||||
bool tracked[GPS_ACQ_MANAGER_PRN_COUNT];
|
||||
bool hardware_busy[GPS_ACQ_MANAGER_PRN_COUNT];
|
||||
uint64_t invisible_since[GPS_ACQ_MANAGER_PRN_COUNT];
|
||||
unsigned int not_busy_polls[GPS_ACQ_MANAGER_PRN_COUNT];
|
||||
bool engine_busy;
|
||||
bool drop_completion_irq;
|
||||
bool drop_loss_irq;
|
||||
unsigned int engine_prn;
|
||||
uint64_t engine_start;
|
||||
uint64_t tick;
|
||||
unsigned int polled_completions;
|
||||
unsigned int polled_losses;
|
||||
unsigned int cache_restores;
|
||||
} receiver_sim_t;
|
||||
|
||||
@@ -100,6 +104,8 @@ static void sim_complete_engine(receiver_sim_t* sim)
|
||||
gps_acq_manager_mark_acquired(&sim->manager, prn);
|
||||
gps_acq_manager_mark_tracking(&sim->manager, prn);
|
||||
sim->tracked[prn] = true;
|
||||
sim->hardware_busy[prn] = true;
|
||||
sim->not_busy_polls[prn] = 0u;
|
||||
sim->invisible_since[prn] = 0u;
|
||||
gps_ephemeris_t restored;
|
||||
if(gps_ephemeris_cache_restore(
|
||||
@@ -119,6 +125,14 @@ static void sim_complete_engine(receiver_sim_t* sim)
|
||||
}
|
||||
}
|
||||
|
||||
static void sim_mark_tracking_lost(receiver_sim_t* sim, unsigned int prn)
|
||||
{
|
||||
sim->tracked[prn] = false;
|
||||
sim->not_busy_polls[prn] = 0u;
|
||||
gps_acq_manager_mark_lost(
|
||||
&sim->manager, prn, sim->tick);
|
||||
}
|
||||
|
||||
static void sim_update_tracking(receiver_sim_t* sim)
|
||||
{
|
||||
for(unsigned int prn = 0u;
|
||||
@@ -140,9 +154,25 @@ static void sim_update_tracking(receiver_sim_t* sim)
|
||||
else if((sim->tick - sim->invisible_since[prn]) >=
|
||||
SIM_UNLOCK_TICKS)
|
||||
{
|
||||
sim->tracked[prn] = false;
|
||||
gps_acq_manager_mark_lost(
|
||||
&sim->manager, prn, sim->tick);
|
||||
sim->hardware_busy[prn] = false;
|
||||
if(!sim->drop_loss_irq)
|
||||
{
|
||||
sim_mark_tracking_lost(sim, prn);
|
||||
}
|
||||
}
|
||||
|
||||
if(!sim->tracked[prn])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(sim->hardware_busy[prn])
|
||||
{
|
||||
sim->not_busy_polls[prn] = 0u;
|
||||
}
|
||||
else if(++sim->not_busy_polls[prn] >= 2u)
|
||||
{
|
||||
sim->polled_losses++;
|
||||
sim_mark_tracking_lost(sim, prn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,6 +337,36 @@ static void test_missed_completion_interrupt_is_polled(void)
|
||||
GPS_ACQ_PRN_TRACKING);
|
||||
}
|
||||
|
||||
static void test_missed_tracking_loss_interrupt_is_reconciled(void)
|
||||
{
|
||||
receiver_sim_t sim;
|
||||
sim_init(&sim);
|
||||
sim.visible[0] = true;
|
||||
sim_start_engine(&sim);
|
||||
sim_run(&sim, SIM_SEARCH_TICKS);
|
||||
assert(sim.tracked[0]);
|
||||
|
||||
sim.drop_loss_irq = true;
|
||||
sim.visible[0] = false;
|
||||
sim_run(&sim, SIM_UNLOCK_TICKS + 2u);
|
||||
assert(!sim.tracked[0]);
|
||||
assert(sim.polled_losses == 1u);
|
||||
assert(gps_acq_manager_state(&sim.manager, 0u) ==
|
||||
GPS_ACQ_PRN_HOT);
|
||||
|
||||
sim.visible[0] = true;
|
||||
sim.drop_loss_irq = false;
|
||||
unsigned int return_tick = (unsigned int)sim.tick;
|
||||
while(!sim.tracked[0] &&
|
||||
((sim.tick - return_tick) <= (2u * SIM_SEARCH_TICKS)))
|
||||
{
|
||||
sim_step(&sim);
|
||||
}
|
||||
assert(sim.tracked[0]);
|
||||
assert((sim.tick - return_tick) <= (2u * SIM_SEARCH_TICKS));
|
||||
assert(sim.cache_restores == 1u);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_cold_boot_and_short_signal_gap();
|
||||
@@ -314,6 +374,7 @@ int main(void)
|
||||
test_long_outage_hot_reacquisition_and_cached_nav();
|
||||
test_hot_failures_do_not_starve_cold_search();
|
||||
test_missed_completion_interrupt_is_polled();
|
||||
test_missed_tracking_loss_interrupt_is_reconciled();
|
||||
puts("gps receiver hardware-simulation scenarios passed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user