New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Questions about using gpsdo #548
Comments
Hi, Many thanks for your interest. I had a look and there were a couple of mistakes. Could you try the following patch (edited): diff --git a/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp b/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
index 3eb15a14f2..89872af40c 100644
--- a/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
+++ b/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
@@ -120,7 +120,7 @@ void lower_phy_uplink_processor_impl::process_symbol_boundary(const baseband_gat
baseband_gateway_timestamp timestamp)
{
// Calculate the subframe index.
- unsigned i_sf = timestamp / nof_samples_per_subframe;
+ unsigned i_sf = static_cast<uint64_t>((timestamp / nof_samples_per_subframe) % (NOF_SFNS * NOF_SUBFRAMES_PER_FRAME));
// Calculate the sample index within the subframe.
unsigned i_sample_sf = timestamp % nof_samples_per_subframe;
diff --git a/lib/radio/uhd/radio_uhd_impl.cpp b/lib/radio/uhd/radio_uhd_impl.cpp
index d7c0b7dcb6..28b95f6bbb 100644
--- a/lib/radio/uhd/radio_uhd_impl.cpp
+++ b/lib/radio/uhd/radio_uhd_impl.cpp
@@ -259,9 +259,6 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
}
}
- bool is_locked = false;
- std::string sensor_name;
-
// Set sync source.
if (!device.set_sync_source(radio_config.clock)) {
fmt::print("Error: couldn't set sync source: {}\n", device.get_error_message());
@@ -271,21 +268,20 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
// Set GPS time if GPSDO is selected.
if (radio_config.clock.sync == radio_configuration::clock_sources::source::GPSDO) {
set_time_to_gps_time();
- }
- // Select oscillator sensor name.
- if (radio_config.clock.sync == radio_configuration::clock_sources::source::GPSDO) {
- sensor_name = "gps_locked";
- } else {
- sensor_name = "ref_locked";
+ if (!wait_sensor_locked("gps_locked", true, CLOCK_TIMEOUT_MS)) {
+ // It blocks until sync source is locked.
+ fmt::print("Could not lock reference GPS time source.\n");
+ return;
+ }
}
// Wait until external reference / GPS is locked.
if (radio_config.clock.clock == radio_configuration::clock_sources::source::GPSDO ||
radio_config.clock.clock == radio_configuration::clock_sources::source::EXTERNAL) {
- // blocks until clock source is locked
- if (not wait_sensor_locked(sensor_name, true, CLOCK_TIMEOUT_MS)) {
- fmt::print("Could not lock reference clock source. Sensor: {}={}.\n", sensor_name, is_locked ? "true" : "false");
+ // It blocks until clock source is locked.
+ if (!wait_sensor_locked("ref_locked", true, CLOCK_TIMEOUT_MS)) {
+ fmt::print("Could not lock reference clock source.\n");
return;
}
}
@@ -314,6 +310,7 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
radio_config.clock.sync != radio_configuration::clock_sources::source::GPSDO) {
device.set_time_unknown_pps(uhd::time_spec_t());
}
// Lists of stream descriptions.
std::vector<radio_uhd_tx_stream::stream_description> tx_stream_description_list;
diff --git a/lib/radio/uhd/radio_uhd_tx_stream.cpp b/lib/radio/uhd/radio_uhd_tx_stream.cpp
index 6326d42f50..d4d9e5ba0c 100644
--- a/lib/radio/uhd/radio_uhd_tx_stream.cpp
+++ b/lib/radio/uhd/radio_uhd_tx_stream.cpp
@@ -81,7 +81,8 @@ void radio_uhd_tx_stream::run_recv_async_msg()
// Enqueue the task again.
if (not async_executor.defer([this]() { run_recv_async_msg(); })) {
- fmt::print(stderr, "Unable to run recv async UHD stream task");
+ fmt::print(stderr, "Unable to run recv async UHD stream task\n");
+ state_fsm.async_task_stopped();
}
}
@@ -347,4 +348,4 @@ void radio_uhd_tx_stream::wait_stop()
unsigned radio_uhd_tx_stream::get_buffer_size() const
{
return max_packet_size;
-}
\ No newline at end of file
+}
diff --git a/lib/ru/generic/ru_controller_generic_impl.cpp b/lib/ru/generic/ru_controller_generic_impl.cpp
index 10b9d0b434..5c9d3d6eda 100644
--- a/lib/ru/generic/ru_controller_generic_impl.cpp
+++ b/lib/ru/generic/ru_controller_generic_impl.cpp
@@ -24,11 +24,14 @@ ru_controller_generic_impl::ru_controller_generic_impl(std::vector<lower_phy_con
void ru_controller_generic_impl::start()
{
- // Calculate starting time from the radio current time plus one hundred milliseconds and rounded to the next subframe.
+ // Calculate starting time from the radio current time plus one hundred milliseconds.
double delay_s = 0.1;
baseband_gateway_timestamp current_time = radio.read_current_time();
baseband_gateway_timestamp start_time = current_time + static_cast<uint64_t>(delay_s * srate_MHz * 1e6);
- start_time = divide_ceil(start_time, static_cast<uint64_t>(srate_MHz * 1e3)) * static_cast<uint64_t>(srate_MHz * 1e3);
+
+ // Round start time to the next subframe.
+ uint64_t sf_duration = static_cast<uint64_t>(srate_MHz * 1e3);
+ start_time = divide_ceil(start_time, sf_duration) * sf_duration;
radio.start(start_time); Let us know how it goes. Kind regards, |
Hi, @xavierarteaga The terminal log:
Kind regards, |
I reproduced the issue and made a larger patch that is being tested. I am sorry for the multiple iterations. My B200 takes very long to lock. This is the current patch: diff --git a/include/srsran/support/math_utils.h b/include/srsran/support/math_utils.h
index b63a4e2ba5..2518159c62 100644
--- a/include/srsran/support/math_utils.h
+++ b/include/srsran/support/math_utils.h
@@ -26,11 +26,16 @@ static constexpr float near_zero = 1e-9;
/// \brief Performs an integer division rounding up.
///
-/// \param[in] num Numerator.
-/// \param[out] den Denominator.
+/// \tparam NumType Division numerator integer type.
+/// \tparam DenType Division denominator integer type.
+/// \param[in] num Numerator.
+/// \param[out] den Denominator.
/// \return The result of the operation.
-inline constexpr unsigned divide_ceil(unsigned num, unsigned den)
+template <typename NumType, typename DenType>
+inline constexpr auto divide_ceil(NumType num, DenType den)
{
+ static_assert(std::is_integral<NumType>::value, "The numerator must be an integer.");
+ static_assert(std::is_integral<DenType>::value, "The denominator must be an integer.");
srsran_sanity_check(den != 0, "Denominator cannot be zero.");
return (num + (den - 1)) / den;
}
diff --git a/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp b/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
index 3eb15a14f2..89872af40c 100644
--- a/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
+++ b/lib/phy/lower/processors/uplink/uplink_processor_impl.cpp
@@ -120,7 +120,7 @@ void lower_phy_uplink_processor_impl::process_symbol_boundary(const baseband_gat
baseband_gateway_timestamp timestamp)
{
// Calculate the subframe index.
- unsigned i_sf = timestamp / nof_samples_per_subframe;
+ unsigned i_sf = static_cast<uint64_t>((timestamp / nof_samples_per_subframe) % (NOF_SFNS * NOF_SUBFRAMES_PER_FRAME));
// Calculate the sample index within the subframe.
unsigned i_sample_sf = timestamp % nof_samples_per_subframe;
diff --git a/lib/radio/uhd/radio_uhd_impl.cpp b/lib/radio/uhd/radio_uhd_impl.cpp
index 55101498f1..c8df3c87e8 100644
--- a/lib/radio/uhd/radio_uhd_impl.cpp
+++ b/lib/radio/uhd/radio_uhd_impl.cpp
@@ -21,7 +21,7 @@ bool radio_session_uhd_impl::set_time_to_gps_time()
const std::string sensor_name = "gps_time";
std::vector<std::string> sensors;
- if (device.get_mboard_sensor_names(sensors) != UHD_ERROR_NONE) {
+ if (!device.get_mboard_sensor_names(sensors)) {
fmt::print("Error: failed to read sensors. {}\n", device.get_error_message());
return false;
}
@@ -41,7 +41,7 @@ bool radio_session_uhd_impl::set_time_to_gps_time()
// Get time and set
fmt::print("Setting USRP time to {}s\n", frac_secs);
- if (device.set_time_unknown_pps(uhd::time_spec_t(frac_secs)) != UHD_ERROR_NONE) {
+ if (!device.set_time_unknown_pps(uhd::time_spec_t(frac_secs))) {
fmt::print("Error: failed to set time. {}\n", device.get_error_message());
return false;
}
@@ -51,8 +51,7 @@ bool radio_session_uhd_impl::set_time_to_gps_time()
bool radio_session_uhd_impl::wait_sensor_locked(const std::string& sensor_name, bool is_mboard, int timeout)
{
- bool is_locked = false;
- auto end_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout);
+ auto end_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout);
// Get sensor list
std::vector<std::string> sensors;
@@ -78,6 +77,7 @@ bool radio_session_uhd_impl::wait_sensor_locked(const std::string& sensor_name,
do {
// Get actual sensor value
+ bool is_locked = false;
if (is_mboard) {
if (!device.get_sensor(sensor_name, is_locked)) {
fmt::print("Error: reading mboard sensor {}. {}.\n", sensor_name, device.get_error_message());
@@ -90,11 +90,16 @@ bool radio_session_uhd_impl::wait_sensor_locked(const std::string& sensor_name,
}
}
- // Read value and wait
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
- } while (not is_locked and std::chrono::steady_clock::now() < end_time);
+ // Return true if the sensor is locked.
+ if (is_locked) {
+ return true;
+ }
+
+ // Sleep some time before trying it again.
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ } while (std::chrono::steady_clock::now() < end_time);
- return is_locked;
+ return false;
}
bool radio_session_uhd_impl::set_tx_gain_unprotected(unsigned port_idx, double gain_dB)
@@ -254,9 +259,6 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
}
}
- bool is_locked = false;
- std::string sensor_name;
-
// Set sync source.
if (!device.set_sync_source(radio_config.clock)) {
fmt::print("Error: couldn't set sync source: {}\n", device.get_error_message());
@@ -265,22 +267,21 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
// Set GPS time if GPSDO is selected.
if (radio_config.clock.sync == radio_configuration::clock_sources::source::GPSDO) {
- set_time_to_gps_time();
- }
+ if (!wait_sensor_locked("gps_locked", true, CLOCK_TIMEOUT_MS)) {
+ // It blocks until sync source is locked.
+ fmt::print("Could not lock reference GPS time source.\n");
+ return;
+ }
- // Select oscillator sensor name.
- if (radio_config.clock.sync == radio_configuration::clock_sources::source::GPSDO) {
- sensor_name = "gps_locked";
- } else {
- sensor_name = "ref_locked";
+ set_time_to_gps_time();
}
// Wait until external reference / GPS is locked.
- if (radio_config.clock.sync == radio_configuration::clock_sources::source::GPSDO ||
- radio_config.clock.sync == radio_configuration::clock_sources::source::EXTERNAL) {
- // blocks until clock source is locked
- if (not wait_sensor_locked(sensor_name, true, CLOCK_TIMEOUT_MS)) {
- fmt::print("Could not lock reference clock source. Sensor: {}={}.\n", sensor_name, is_locked ? "true" : "false");
+ if (radio_config.clock.clock == radio_configuration::clock_sources::source::GPSDO ||
+ radio_config.clock.clock == radio_configuration::clock_sources::source::EXTERNAL) {
+ // It blocks until clock source is locked.
+ if (!wait_sensor_locked("ref_locked", true, CLOCK_TIMEOUT_MS)) {
+ fmt::print("Could not lock reference clock source.\n");
return;
}
}
diff --git a/lib/radio/uhd/radio_uhd_tx_stream.cpp b/lib/radio/uhd/radio_uhd_tx_stream.cpp
index 6326d42f50..d4d9e5ba0c 100644
--- a/lib/radio/uhd/radio_uhd_tx_stream.cpp
+++ b/lib/radio/uhd/radio_uhd_tx_stream.cpp
@@ -81,7 +81,8 @@ void radio_uhd_tx_stream::run_recv_async_msg()
// Enqueue the task again.
if (not async_executor.defer([this]() { run_recv_async_msg(); })) {
- fmt::print(stderr, "Unable to run recv async UHD stream task");
+ fmt::print(stderr, "Unable to run recv async UHD stream task\n");
+ state_fsm.async_task_stopped();
}
}
@@ -347,4 +348,4 @@ void radio_uhd_tx_stream::wait_stop()
unsigned radio_uhd_tx_stream::get_buffer_size() const
{
return max_packet_size;
-}
\ No newline at end of file
+}
diff --git a/lib/ru/generic/ru_controller_generic_impl.cpp b/lib/ru/generic/ru_controller_generic_impl.cpp
index 10b9d0b434..5c9d3d6eda 100644
--- a/lib/ru/generic/ru_controller_generic_impl.cpp
+++ b/lib/ru/generic/ru_controller_generic_impl.cpp
@@ -24,11 +24,14 @@ ru_controller_generic_impl::ru_controller_generic_impl(std::vector<lower_phy_con
void ru_controller_generic_impl::start()
{
- // Calculate starting time from the radio current time plus one hundred milliseconds and rounded to the next subframe.
+ // Calculate starting time from the radio current time plus one hundred milliseconds.
double delay_s = 0.1;
baseband_gateway_timestamp current_time = radio.read_current_time();
baseband_gateway_timestamp start_time = current_time + static_cast<uint64_t>(delay_s * srate_MHz * 1e6);
- start_time = divide_ceil(start_time, static_cast<uint64_t>(srate_MHz * 1e3)) * static_cast<uint64_t>(srate_MHz * 1e3);
+
+ // Round start time to the next subframe.
+ uint64_t sf_duration = static_cast<uint64_t>(srate_MHz * 1e3);
+ start_time = divide_ceil(start_time, sf_duration) * sf_duration;
radio.start(start_time); This patch will go into the next release. |
Hi, @xavierarteaga There are the error messages from the open5gs core network:
|
I understand that when you set My COTS (Fairphone5) does not attach when I use Leo Bodnar GPSDO as an external reference. I still need to investigate further. Is your UE cabled to the USRP? |
Yes, your understanding is correct. My UE(Realme Q5 pro) can search for a signal called "open5gs"(the CN's name), but cannot connect to it. I'll also try to find out what the problem is. |
Hi, @xavierarteaga I would like to ask if there are any results from your investigation on this issue. I wonder if the calculation method of frame number has changed after switching to GPS signal, causing users to be unable to connect normally. |
I have not got deeper as my B200's GPSDO is not locking well. I found that the GPS time causes the overflow of some timestamps in the SFN derivation. You could try a zero time in the next PPS. |
My B200 takes a long time to lock the gps signal(GPS antenna placed outdoors), but once it locks it becomes very stable. What I understand is that when using GPS time to calculate SFN, due to the overflow problem caused by the large GPS time value, UE cannot connect normally. To solve this problem, if the GPS time used to calculate SFN is set to zero, it may be possible. To solve this problem, is my understanding correct? I use GPS signals as synchronization signals to achieve frame synchronization between base stations. If I set the GPS time to zero at the next pps, will the frame synchronization between base stations be affected? |
The idea of the experiment is to validate our hypothesis. If the UE attaches after setting the timestamp to 0, it could be there is an overflow. Otherwise, the problem is not related to the GPS time.
It would be affected but it is an experiment to discard whether the problem is related (or not) to the timestamp. For this, I suggest commenting on this section:
|
Hi, maybe something related to your issue: #554 |
Under your suggestion, I tried an experiment. After setting the time of b200 to zero, UE can access normally. There are some logs of base station:
My idea is that the GPS time is a very large number (1713345128.0s). If the remainder of this number is set to the usrp time (for example, setting the time to 45128.0s), will it not affect the frame synchronization between base stations? solve this problem. I want to know how to solve this problem to facilitate my next work. Thank you very much! |
I tried to attach my COTS UE with the following patch on the top to the code we will soon release: diff --git a/lib/radio/uhd/radio_uhd_impl.cpp b/lib/radio/uhd/radio_uhd_impl.cpp
index c8df3c87e8..2e2930b6fd 100644
--- a/lib/radio/uhd/radio_uhd_impl.cpp
+++ b/lib/radio/uhd/radio_uhd_impl.cpp
@@ -311,6 +311,14 @@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
device.set_time_unknown_pps(uhd::time_spec_t());
}
+ double full_seconds = 1713345128.0;
+
+ fmt::print("Setting USRP time to {}s\n", full_seconds);
+ device.set_time_unknown_pps(uhd::time_spec_t(full_seconds));
+
// Lists of stream descriptions.
std::vector<radio_uhd_tx_stream::stream_description> tx_stream_description_list;
std::vector<radio_uhd_rx_stream::stream_description> rx_stream_description_list; The UE has attached to the gNb and the ping went successfully. As far as I know, all the fixes related to this issue are included in the comment above. My radio configuration is the following:
|
Hi, @xavierarteaga
I tried your patch, but on my device, ue still cannot connect normally. After adding the patch, the usrp time is set to Because of this phenomenon, I guessed that when the usrp time is only a smaller value, the system can run normally. When the usrp time is set to a larger value, ue cannot connect normally. Then I did an experiment and verified this conjecture is that when the usrp time is set to a value of one hundred thousand levels, ue can connect normally. When it reaches a value of one million levels, ue cannot connect normally. I tried to attach my COTS UE with the following patch: diff --git a/lib/radio/uhd/radio_uhd_impl.cpp b/lib/radio/uhd/radio_uhd_impl.cpp
--- a/lib/radio/uhd/radio_uhd_impl.cpp
+++ b/lib/radio/uhd/radio_uhd_impl.cpp
@@ radio_session_uhd_impl::radio_session_uhd_impl(const radio_configuration::radio&
device.set_time_unknown_pps(uhd::time_spec_t());
}
- double full_seconds = 1713345128.0;
-
- fmt::print("Setting USRP time to {}s\n", full_seconds);
- device.set_time_unknown_pps(uhd::time_spec_t(full_seconds));
-
// Lists of stream descriptions.
std::vector<radio_uhd_tx_stream::stream_description> tx_stream_description_list;
std::vector<radio_uhd_rx_stream::stream_description> rx_stream_description_list;
@@ bool radio_session_uhd_impl::set_time_to_gps_time()
if (!device.get_sensor(sensor_name, frac_secs)) {
fmt::print("Error: not possible to read sensor {}. {}\n", sensor_name, device.get_error_message());
return false;
}
+ frac_secs = fmod(frac_secs, 1000000.0);
// Get time and set
fmt::print("Setting USRP time to {}s\n", frac_secs);
The UE has attached to the gNb and can connect to the Internet normally. My radio configuration is the following:
|
Issue Description
[Describe the issue in detail]
When using the GPS signal as a synchronization signal, I found that the judgment of the sensor reading in the code may be wrong. The specific problem is that the sensor can actually be read successfully and stored, but the code judgment result is that the sensor reading is unsuccessful.
I tried to modify the code. USRP can be successfully set to GPS time, but after setting it to GPS time, there will be a serious delay problem.
Setup Details
[Specify details of the test setup. This would help us reproduce the problem reliably]
e.g. Network configuration, Operation System, Hardware, RF front-end, library and driver versions
My network configuration profile :
My Operation System is Ubuntu 22.04.4 LTS, RF front-end is usrp B210, uhd version is 4.4.0
Expected Behavior
[What you expect to happen]
I want the base station to work properly when using gps signal as sync signal.
Actual Behaviour
[What happens instead e.g. error message]
When the clock is changed to gpsdo in the configuration file, an error of failure to read the sensor will be displayed (the actual sensor has been successfully read). After modifying the judgment conditions, usrp can set the time to gps time, but a serious time out occur.
Steps to reproduce the problem
[Tell us how to reproduce this issue e.g. RF setup, application config files]
Additional Information
[Any additional information, configuration or data that might be necessary to reproduce the issue]
I think the code that determines the error in reading the sensor is:
I tried to make some modifications to the code. After modification, I can set the GPS time, but there will be a time out problem.
The text was updated successfully, but these errors were encountered: