From d83c935e4217f77584854c3c5730de6e53015622 Mon Sep 17 00:00:00 2001 From: WANG Tsu-Han Date: Fri, 21 Feb 2020 16:19:43 +0100 Subject: [PATCH] add trx write thread --- executables/nr-ru.c | 6 + targets/ARCH/COMMON/common_lib.h | 36 +++++ targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 154 ++++++++++++++----- 3 files changed, 161 insertions(+), 35 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 0003cf770d..21a62678cf 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1444,6 +1444,9 @@ static void *ru_thread( void *param ) { // if this is a slave RRU, try to synchronize on the DL frequency if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); + + // start trx write thread + start_write_thread(ru); } pthread_mutex_lock(&proc->mutex_FH1); @@ -1651,6 +1654,9 @@ int stop_rf(RU_t *ru) { return 0; } +int start_write_thread(RU_t *ru) { + return(ru->rfdevice.trx_write_init(&ru->rfdevice)); +} void init_RU_proc(RU_t *ru) { int i=0; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 03ab4da5f9..d92c38a2a7 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -276,8 +276,38 @@ typedef struct { void *rx; } if_buffer_t; +typedef struct { + openair0_timestamp timestamp; + void **buff;// buffer to be write; + int nsamps; + int cc; + signed char first_packet; + signed char last_packet; +} openair0_write_package_t; + +typedef struct { + openair0_write_package_t write_package[10]; + /// write package number + int num_package; + int start; + int end; + /// \internal This variable is protected by \ref mutex_write + int instance_cnt_write; + /// pthread struct for trx write thread + pthread_t pthread_write; + /// pthread attributes for trx write thread + pthread_attr_t attr_write; + /// condition varible for trx write thread + pthread_cond_t cond_write; + /// mutex for trx write thread + pthread_mutex_t mutex_write; +} openair0_thread_t; + /*!\brief structure holds the parameters to configure USRP devices */ struct openair0_device_t { + /*!tx write thread*/ + openair0_thread_t write_thread; + /*!brief Module ID of this device */ int Mod_id; @@ -400,6 +430,12 @@ struct openair0_device_t { * \param arg pointer to capabilities or configuration */ void (*configure_rru)(int idx, void *arg); + + /*! \brief RRU Configuration callback + * \param idx RU index + * \param arg pointer to capabilities or configuration + */ + int (*trx_write_init)(openair0_device *device); }; /* type of device init function, implemented in shared lib */ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index eb8c6ec010..798b6b6b4d 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -406,37 +406,9 @@ static int trx_usrp_write_recplay(openair0_device *device, openair0_timestamp ti */ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int ret=0; - usrp_state_t *s = (usrp_state_t *)device->priv; - int nsamps2; // aligned to upper 32 or 16 byte boundary -#if defined(__x86_64) || defined(__i386__) - #ifdef __AVX2__ - nsamps2 = (nsamps+7)>>3; - __m256i buff_tx[8][nsamps2]; - #else - nsamps2 = (nsamps+3)>>2; - __m128i buff_tx[8][nsamps2]; - #endif -#elif defined(__arm__) - nsamps2 = (nsamps+3)>>2; - int16x8_t buff_tx[8][nsamps2]; -#else -#error Unsupported CPU architecture, USRP device cannot be built -#endif - - // bring RX data into 12 LSBs for softmodem RX - for (int i=0; iwrite_thread; + openair0_write_package_t *write_package = write_thread->write_package; boolean_t first_packet_state=false,last_packet_state=false; @@ -469,9 +441,98 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, last_packet_state = true; } + pthread_mutex_lock(&write_thread->mutex_write); + write_thread->end = (write_thread->end + 1)% write_thread->num_package; + end = write_thread->end; + write_package[end].timestamp = timestamp; + write_package[end].nsamps = nsamps; + write_package[end].cc = cc; + write_package[end].first_packet = first_packet_state; + write_package[end].last_packet = last_packet_state; + write_package[end].buff = buff; + write_thread->instance_cnt_write = 0; + pthread_cond_signal(&write_thread->cond_write); + printf("trx_usrp_write signal end\n"); + pthread_mutex_unlock(&write_thread->mutex_write); + + + return ret; +} + +//-----------------------start-------------------------- +/*! \brief Called to send samples to the USRP RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at which the first sample MUST be sent + @param buff Buffer which holds the samples + @param nsamps number of samples to be sent + @param antenna_id index of the antenna if the device has multiple antennas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied +*/ +void *trx_usrp_write_thread(void * arg){ + int ret=0; + openair0_device *device=(openair0_device *)arg; + openair0_thread_t *write_thread = &device->write_thread; + openair0_write_package_t *write_package = write_thread->write_package; + + + + while(1){ + pthread_mutex_lock(&write_thread->mutex_write); + printf("waiting for signal \n"); + while (write_thread->instance_cnt_write < 0) { + pthread_cond_wait(&write_thread->cond_write,&write_thread->mutex_write); // this unlocks mutex_rxtx while waiting and then locks it again + } + printf("signal unlock\n"); + int start = write_thread->start; + printf("start = %d, end = %d\n", start, write_thread->end); + openair0_timestamp timestamp = write_package[start].timestamp; + void **buff = write_package[start].buff; + int nsamps = write_package[start].nsamps; + int cc = write_package[start].cc; + bool first_packet = write_package[start].first_packet; + bool last_packet = write_package[start].last_packet; + if(write_thread->end == (write_thread->start + 1)% write_thread->num_package){ + write_thread->instance_cnt_write = -1; + } + write_thread->start = (write_thread->start + 1)% write_thread->num_package; + pthread_mutex_unlock(&write_thread->mutex_write); + printf("end of write thread signal getting \n"); + + usrp_state_t *s = (usrp_state_t *)device->priv; + int nsamps2; // aligned to upper 32 or 16 byte boundary + #if defined(__x86_64) || defined(__i386__) + #ifdef __AVX2__ + nsamps2 = (nsamps+7)>>3; + __m256i buff_tx[8][nsamps2]; + #else + nsamps2 = (nsamps+3)>>2; + __m128i buff_tx[8][nsamps2]; + #endif + #elif defined(__arm__) + nsamps2 = (nsamps+3)>>2; + int16x8_t buff_tx[8][nsamps2]; + #else + #error Unsupported CPU architecture, USRP device cannot be built + #endif + + // bring RX data into 12 LSBs for softmodem RX + for (int i=0; itx_md.has_time_spec = true; - s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet_state; - s->tx_md.end_of_burst = last_packet_state; + s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet; + s->tx_md.end_of_burst = last_packet; s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); s->tx_count++; @@ -483,11 +544,33 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); } else ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); - if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); + if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); - return ret; + if(0) break; + } + + return NULL; } +int trx_write_init(openair0_device *device){ + + uhd::set_thread_priority_safe(1.0); + openair0_thread_t *write_thread = &device->write_thread; + printf("initializing tx write thread\n"); + + write_thread->num_package = 10; + write_thread->start = 0; + write_thread->end = 0; + write_thread->instance_cnt_write = -1; + printf("end of tx write thread\n"); + + pthread_create(&write_thread->pthread_write,NULL,trx_usrp_write_thread,(void *)device); + + return(0); +} + +//---------------------end------------------------- + /*! \brief Receive samples from iq file. * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for * the first channel. *ptimestamp is the time at which the first sample @@ -917,6 +1000,7 @@ extern "C" { device->trx_stop_func = trx_usrp_stop; device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_gains_func = trx_usrp_set_gains; + device->trx_write_init = trx_write_init; if ( s->recplay_mode == RECPLAY_REPLAYMODE) { // Replay subframes from from file