From 3a011155dbf371a80f79676934177235e742abaf Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 7 Jun 2021 18:16:56 +0200 Subject: [PATCH] SRSUE: Make sure PHY reset is done when SYNC is IDLE --- srsue/hdr/phy/sync.h | 13 +++++++--- srsue/src/phy/phy.cc | 14 ++++++++-- srsue/src/phy/phy_common.cc | 15 ++++++----- srsue/src/phy/sync.cc | 51 ++++++++++++++++--------------------- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 09b177770..9d8fe476b 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -73,6 +73,13 @@ public: bool cell_select_start(phy_cell_t cell); bool cell_is_camping(); + /** + * @brief Interface for monitoring UE's synchronization transition to IDLE. In addition to IDLE transitioning, this + * method waits for workers to finish processing and ends the current RF transmission burst. + * @return true if SYNC transitioned to IDLE, false otherwise + */ + bool wait_idle(); + // RRC interface for controlling the neighbour cell measurement void set_cells_to_meas(uint32_t earfcn, const std::set& pci); void set_inter_frequency_measurement(uint32_t cc_idx, uint32_t earfcn_, srsran_cell_t cell_); @@ -190,7 +197,7 @@ private: bool set_cell(float cfo); std::atomic running = {false}; - bool is_overflow = false; + bool is_overflow = false; srsran::rf_timestamp_t last_rx_time; bool forced_rx_time_init = true; // Rx time sync after first receive from radio @@ -232,7 +239,7 @@ private: std::atomic sfo = {}; // SFO estimate updated after each sync-cycle std::atomic cfo = {}; // CFO estimate updated after each sync-cycle std::atomic ref_cfo = {}; // provided adjustment value applied before sync - sync_metrics_t metrics = {}; + sync_metrics_t metrics = {}; // in-sync / out-of-sync counters std::atomic out_of_sync_cnt = {0}; @@ -274,7 +281,7 @@ private: const static int MIN_TTI_JUMP = 1; ///< Time gap reported to stack after receiving subframe const static int MAX_TTI_JUMP = 1000; ///< Maximum time gap tolerance in RF stream metadata const uint8_t SYNC_CC_IDX = 0; ///< From the sync POV, the CC idx is always the first - const uint32_t TIMEOUT_TO_IDLE_MS = 2; ///< Timeout in milliseconds for transitioning to IDLE + const uint32_t TIMEOUT_TO_IDLE_MS = 2000; ///< Timeout in milliseconds for transitioning to IDLE }; } // namespace srsue diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index ada8d8083..3c22ade56 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -304,10 +304,15 @@ bool phy::cell_select(phy_cell_t cell) { sfsync.scell_sync_stop(); if (sfsync.cell_select_init(cell)) { - reset(); // Update PCI before starting the background command to make sure PRACH gets the updated value selected_cell.id = cell.pci; cmd_worker_cell.add_cmd([this, cell]() { + // Wait SYNC transitions to IDLE + sfsync.wait_idle(); + + // Reset worker once SYNC is IDLE to flush any PHY state including measurements, pending ACKs and pending grants + reset(); + bool ret = sfsync.cell_select_start(cell); if (ret) { srsran_cell_t sync_cell; @@ -330,8 +335,13 @@ bool phy::cell_search() { sfsync.scell_sync_stop(); if (sfsync.cell_search_init()) { - reset(); cmd_worker_cell.add_cmd([this]() { + // Wait SYNC transitions to IDLE + sfsync.wait_idle(); + + // Reset worker once SYNC is IDLE to flush any PHY state including measurements, pending ACKs and pending grants + reset(); + phy_cell_t found_cell = {}; rrc_interface_phy_lte::cell_search_ret_t ret = sfsync.cell_search_start(&found_cell); stack->cell_search_complete(ret, found_cell); diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 062abd5a8..0b70dbddf 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -873,12 +873,15 @@ void phy_common::reset() pcell_report_period = 20; last_ri = 0; - ZERO_OBJECT(pathloss); - ZERO_OBJECT(avg_sinr_db); - ZERO_OBJECT(avg_snr_db); - ZERO_OBJECT(avg_rsrp); - ZERO_OBJECT(avg_rsrp_dbm); - ZERO_OBJECT(avg_rsrq_db); + { + std::unique_lock lock(meas_mutex); + ZERO_OBJECT(pathloss); + ZERO_OBJECT(avg_sinr_db); + ZERO_OBJECT(avg_snr_db); + ZERO_OBJECT(avg_rsrp); + ZERO_OBJECT(avg_rsrp_dbm); + ZERO_OBJECT(avg_rsrq_db); + } cell_state.reset(); reset_neighbour_cells(); diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 945bdc2fd..b3fae553f 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -219,18 +219,6 @@ rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* fou rrc_proc_state = PROC_SEARCH_RUNNING; - // Wait for SYNC thread to transition to IDLE (max. 2000ms) - if (not phy_state.wait_idle(TIMEOUT_TO_IDLE_MS)) { - Error("SYNC: Error transitioning to IDLE. Cell search cannot start."); - return ret; - } - - // Wait for workers to finish PHY processing - worker_com->semaphore.wait_all(); - - // Reset worker once SYNC is IDLE to flush any worker states such as ACKs and pending grants - worker_com->reset(); - if (srate_mode != SRATE_FIND) { srate_mode = SRATE_FIND; radio_h->set_rx_srate(1.92e6); @@ -392,6 +380,26 @@ bool sync::cell_is_camping() return phy_state.is_camping(); } +bool sync::wait_idle() +{ + // Wait for SYNC thread to transition to IDLE (max. 2000ms) + if (not phy_state.wait_idle(TIMEOUT_TO_IDLE_MS)) { + Error("SYNC: Failed transitioning to IDLE"); + return false; + } + + // Reset UE sync. Attention: doing this reset when the FSM is NOT IDLE can cause PSS/SSS out-of-sync + srsran_ue_sync_reset(&ue_sync); + + // Wait for workers to finish PHY processing + worker_com->semaphore.wait_all(); + + // As workers have finished, make sure the Tx burst is ended + radio_h->tx_end(); + + return true; +} + void sync::run_cell_search_state() { cell_search_ret = search_p.run(&cell, mib); @@ -802,23 +810,8 @@ void sync::set_ue_sync_opts(srsran_ue_sync_t* q, float cfo) srsran_sync_set_sss_algorithm(&q->sfind, (sss_alg_t)sss_alg); } -bool sync::set_cell(float cfo) +bool sync::set_cell(float cfo_in) { - // Wait for SYNC thread to transition to IDLE (max. 2000ms) - if (not phy_state.wait_idle(TIMEOUT_TO_IDLE_MS)) { - Error("SYNC: Can not change Cell while not in IDLE"); - return false; - } - - // Reset UE sync. Attention: doing this reset when the FSM is NOT IDLE can cause PSS/SSS out-of-sync - srsran_ue_sync_reset(&ue_sync); - - // Wait for workers to finish PHY processing - worker_com->semaphore.wait_all(); - - // Reset worker once SYNC is IDLE to flush any worker states such as ACKs and pending grants - worker_com->reset(); - if (!srsran_cell_isvalid(&cell)) { Error("SYNC: Setting cell: invalid cell (nof_prb=%d, pci=%d, ports=%d)", cell.nof_prb, cell.id, cell.nof_ports); return false; @@ -851,7 +844,7 @@ bool sync::set_cell(float cfo) } // Set options defined in expert section - set_ue_sync_opts(&ue_sync, cfo); + set_ue_sync_opts(&ue_sync, cfo_in); // Reset ue_sync and set CFO/gain from search procedure srsran_ue_sync_reset(&ue_sync);