mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-03 13:43:18 +00:00
ms: fix startup & shutdown of blade
One of the mystery bugs was that the blade ms needed two starts after powercycling the bladerf due to transfer timeouts. This is now fixed. Change-Id: I1cd8790191790f4861a70bc55c8f4c9993fa10c8
This commit is contained in:
@@ -293,10 +293,10 @@ struct blade_hw {
|
||||
setRxGain(rxgain, 0);
|
||||
setTxGain(txgain, 0);
|
||||
usleep(1000);
|
||||
blade_check(bladerf_enable_module, dev, BLADERF_MODULE_RX, true);
|
||||
usleep(1000);
|
||||
blade_check(bladerf_enable_module, dev, BLADERF_MODULE_TX, true);
|
||||
usleep(1000);
|
||||
|
||||
bladerf_set_stream_timeout(dev, BLADERF_TX, 10);
|
||||
bladerf_set_stream_timeout(dev, BLADERF_RX, 10);
|
||||
|
||||
blade_check(bladerf_init_stream, &rx_stream, dev, getrxcb(rxh), &buf_mgmt.rx_samples, BLADE_NUM_BUFFERS,
|
||||
BLADERF_FORMAT_SC16_Q11_META, BLADE_BUFFER_SIZE, NUM_TRANSFERS, (void *)this);
|
||||
|
||||
@@ -308,15 +308,16 @@ struct blade_hw {
|
||||
buf_mgmt.bufptrqueue.spsc_push(&cur_buffer[i]);
|
||||
}
|
||||
|
||||
|
||||
usleep(1000);
|
||||
|
||||
// bladerf_set_stream_timeout(dev, BLADERF_TX, 4);
|
||||
// bladerf_set_stream_timeout(dev, BLADERF_RX, 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void actually_enable_streams()
|
||||
{
|
||||
blade_check(bladerf_enable_module, dev, BLADERF_MODULE_RX, true);
|
||||
usleep(1000);
|
||||
blade_check(bladerf_enable_module, dev, BLADERF_MODULE_TX, true);
|
||||
}
|
||||
|
||||
bool tuneTx(double freq, size_t chan = 0)
|
||||
{
|
||||
msleep(15);
|
||||
@@ -418,8 +419,9 @@ struct blade_hw {
|
||||
auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
|
||||
{
|
||||
auto fn = [this] {
|
||||
int status;
|
||||
status = bladerf_stream(rx_stream, BLADERF_RX_X1);
|
||||
int status = 0;
|
||||
if (!stop_me_flag)
|
||||
status = bladerf_stream(rx_stream, BLADERF_RX_X1);
|
||||
if (status < 0)
|
||||
std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
|
||||
|
||||
@@ -430,8 +432,9 @@ struct blade_hw {
|
||||
auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
|
||||
{
|
||||
auto fn = [this] {
|
||||
int status;
|
||||
status = bladerf_stream(tx_stream, BLADERF_TX_X1);
|
||||
int status = 0;
|
||||
if (!stop_me_flag)
|
||||
status = bladerf_stream(tx_stream, BLADERF_TX_X1);
|
||||
if (status < 0)
|
||||
std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
|
||||
|
||||
@@ -442,9 +445,15 @@ struct blade_hw {
|
||||
|
||||
void submit_burst_ts(blade_sample_type *buffer, int len, uint64_t ts)
|
||||
{
|
||||
//get empty bufer from list
|
||||
tx_buf_q_type::elem_t rcd;
|
||||
|
||||
// exit by submitting a dummy buffer to assure the libbladerf stream mutex is happy (thread!)
|
||||
if (!buffer) {
|
||||
bladerf_submit_stream_buffer(tx_stream, (void *)BLADERF_STREAM_SHUTDOWN, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
//get empty bufer from list
|
||||
while (!buf_mgmt.bufptrqueue.spsc_pop(&rcd))
|
||||
buf_mgmt.bufptrqueue.spsc_prep_pop();
|
||||
assert(rcd != nullptr);
|
||||
|
||||
@@ -276,6 +276,8 @@ bh_fn_t ms_trx::tx_bh()
|
||||
|
||||
void ms_trx::start()
|
||||
{
|
||||
if (stop_me_flag)
|
||||
return;
|
||||
auto fn = get_rx_burst_handler_fn(rx_bh());
|
||||
rx_task = std::thread(fn);
|
||||
set_name_aff_sched(rx_task.native_handle(), sched_params::thread_names::RXRUN);
|
||||
@@ -285,6 +287,7 @@ void ms_trx::start()
|
||||
tx_task = std::thread(fn2);
|
||||
set_name_aff_sched(tx_task.native_handle(), sched_params::thread_names::TXRUN);
|
||||
|
||||
actually_enable_streams();
|
||||
}
|
||||
|
||||
void ms_trx::set_upper_ready(bool is_ready)
|
||||
@@ -294,11 +297,14 @@ void ms_trx::set_upper_ready(bool is_ready)
|
||||
|
||||
void ms_trx::stop_threads()
|
||||
{
|
||||
std::cerr << "killing threads...\r\n" << std::endl;
|
||||
std::cerr << "killing threads..." << std::endl;
|
||||
stop_me_flag = true;
|
||||
close_device();
|
||||
std::cerr << "dev closed..." << std::endl;
|
||||
rx_task.join();
|
||||
std::cerr << "L rx dead..." << std::endl;
|
||||
tx_task.join();
|
||||
std::cerr << "L tx dead..." << std::endl;
|
||||
}
|
||||
|
||||
void ms_trx::submit_burst(blade_sample_type *buffer, int len, GSM::Time target)
|
||||
|
||||
@@ -94,6 +94,17 @@ extern "C" void trxc_log_init(void *tallctx);
|
||||
|
||||
std::atomic<bool> g_exit_flag;
|
||||
|
||||
void upper_trx::stop_upper_threads()
|
||||
{
|
||||
g_exit_flag = true;
|
||||
|
||||
if (thr_control.joinable())
|
||||
thr_control.join();
|
||||
if (thr_rx.joinable())
|
||||
thr_rx.join();
|
||||
if (thr_tx.joinable())
|
||||
thr_tx.join();
|
||||
}
|
||||
void upper_trx::start_threads()
|
||||
{
|
||||
thr_control = std::thread([this] {
|
||||
@@ -101,6 +112,7 @@ void upper_trx::start_threads()
|
||||
while (!g_exit_flag) {
|
||||
driveControl();
|
||||
}
|
||||
std::cerr << "exit control!" << std::endl;
|
||||
});
|
||||
msleep(1);
|
||||
thr_tx = std::thread([this] {
|
||||
@@ -108,6 +120,7 @@ void upper_trx::start_threads()
|
||||
while (!g_exit_flag) {
|
||||
driveTx();
|
||||
}
|
||||
std::cerr << "exit tx U!" << std::endl;
|
||||
});
|
||||
|
||||
// atomic ensures data is not written to q until loop reads
|
||||
@@ -115,7 +128,8 @@ void upper_trx::start_threads()
|
||||
|
||||
set_name_aff_sched(sched_params::thread_names::U_RX);
|
||||
while (!g_exit_flag) {
|
||||
// set_upper_ready(true);
|
||||
// set_upper_ready(true) needs to happen during cmd handling:
|
||||
// the main loop is driven by rx, so unless rx is on AND transceiver is on we get stuck..
|
||||
driveReceiveFIFO();
|
||||
trxcon::osmo_select_main(1);
|
||||
|
||||
@@ -125,6 +139,9 @@ void upper_trx::start_threads()
|
||||
trxcon_phyif_handle_rsp(trxcon::g_trxcon, &r);
|
||||
}
|
||||
}
|
||||
set_upper_ready(false);
|
||||
std::cerr << "exit rx U!" << std::endl;
|
||||
mOn = false;
|
||||
|
||||
#ifdef LSANDEBUG
|
||||
std::thread([this] {
|
||||
@@ -267,8 +284,7 @@ void upper_trx::driveTx()
|
||||
|
||||
// ensure our tx cb is tickled and can exit
|
||||
if (g_exit_flag) {
|
||||
blade_sample_type dummy[10] = {};
|
||||
submit_burst_ts(dummy, 10, 1);
|
||||
submit_burst_ts(0, 1337, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -360,10 +376,9 @@ bool upper_trx::driveControl()
|
||||
set_ta(0);
|
||||
break;
|
||||
case trxcon::TRXCON_PHYIF_CMDT_POWERON:
|
||||
|
||||
if (!mOn) {
|
||||
set_upper_ready(true);
|
||||
mOn = true;
|
||||
set_upper_ready(true);
|
||||
}
|
||||
break;
|
||||
case trxcon::TRXCON_PHYIF_CMDT_POWEROFF:
|
||||
@@ -444,7 +459,7 @@ int trxcon_l1ctl_send(struct trxcon::trxcon_inst *trxcon, struct trxcon::msgb *m
|
||||
void sighandler(int sigset)
|
||||
{
|
||||
// we might get a sigpipe in case the l1ctl ud socket disconnects because mobile quits
|
||||
if (sigset == SIGPIPE) {
|
||||
if (sigset == SIGPIPE || sigset == SIGINT) {
|
||||
g_exit_flag = true;
|
||||
|
||||
// we know the flag is atomic and it prevents the trxcon cb handlers from writing
|
||||
@@ -453,6 +468,7 @@ void sighandler(int sigset)
|
||||
trxcon::internal_q_tx_buf b = {};
|
||||
trxcon::txq.spsc_push(&b);
|
||||
trxcon::cmdq_to_phy.spsc_push(&cmd);
|
||||
msleep(200);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -462,6 +478,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
auto tall_trxcon_ctx = talloc_init("trxcon context");
|
||||
signal(SIGPIPE, sighandler);
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
trxcon::msgb_talloc_ctx_init(tall_trxcon_ctx, 0);
|
||||
trxc_log_init(tall_trxcon_ctx);
|
||||
@@ -492,8 +509,11 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
// blocking, will return when global exit is requested
|
||||
trx->start_threads();
|
||||
|
||||
trx->stop_threads();
|
||||
trx->stop_upper_threads();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ class upper_trx : public ms_trx {
|
||||
public:
|
||||
void start_threads();
|
||||
void start_lower_ms();
|
||||
void stop_upper_threads();
|
||||
|
||||
upper_trx(){};
|
||||
};
|
||||
|
||||
@@ -185,6 +185,11 @@ struct uhd_hw {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void actually_enable_streams()
|
||||
{
|
||||
// nop: stream cmd in handler
|
||||
}
|
||||
|
||||
void *rx_cb(bh_fn_t burst_handler)
|
||||
{
|
||||
void *ret = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user