diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 1f3c76ddd4de52e1664aa3e935df556a7084b32b..8f5b7b32fea3dffcef93387c4abf3d4ad5a45275 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -66,7 +66,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), - txp, + (void**)txp, spp_eth, fp->nb_antennas_tx, 0); @@ -86,7 +86,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), - rxp, + (void**)rxp, spp_eth, fp->nb_antennas_rx, 0); @@ -131,7 +131,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, packet_id, - &tx_buffer, + (void**)&tx_buffer, db_fulllength, 1, IF5_MOBIPASS)) < 0) { @@ -177,7 +177,7 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - txp, + (void**)txp, spp_eth, fp->nb_antennas_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); @@ -197,7 +197,7 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - rxp, + (void**)rxp, spp_eth, fp->nb_antennas_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 7bcc3810ae66fc16317b6a3eec3f5640d362413a..8e88fba00d55a5c213b3e9f0b80d1bb027bf5793 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -252,10 +252,12 @@ typedef struct eNB_proc_t_s { /// \brief Instance count for rx processing thread. /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; + /// \internal This variable is protected by \ref mutex_asynch_rxtx. + int instance_cnt_asynch_rxtx; /// pthread structure for FH processing thread pthread_t pthread_FH; - /// pthread structure for asychronous RX processing thread - pthread_t pthread_asynch_rx; + /// pthread structure for asychronous RX/TX processing thread + pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition int first_rx; /// pthread attributes for FH processing thread @@ -263,23 +265,27 @@ typedef struct eNB_proc_t_s { /// pthread attributes for prach processing thread pthread_attr_t attr_prach; /// pthread attributes for asynchronous RX thread - pthread_attr_t attr_asynch_rx; + pthread_attr_t attr_asynch_rxtx; /// scheduling parameters for FH thread struct sched_param sched_param_FH; /// scheduling parameters for prach thread struct sched_param sched_param_prach; - /// scheduling parameters for asynch_rx thread - struct sched_param sched_param_asynch_rx; - /// condition variable for FH thread + /// scheduling parameters for asynch_rxtx thread + struct sched_param sched_param_asynch_rxtx; + /// pthread structure for PRACH thread pthread_t pthread_prach; /// condition variable for FH thread pthread_cond_t cond_FH; /// condition variable for PRACH processing thread; pthread_cond_t cond_prach; + /// condition variable for asynch RX/TX thread + pthread_cond_t cond_asynch_rxtx; /// mutex for FH pthread_mutex_t mutex_FH; /// mutex for PRACH thread pthread_mutex_t mutex_prach; + /// mutex for asynch RX/TX thread + pthread_mutex_t mutex_asynch_rxtx; /// set of scheduling variables RXn-TXnp4 threads eNB_rxtx_proc_t proc_rxtx[2]; /// number of slave threads diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ed8cfefecb50801aec738c0d46713af18cd74ccc..732fec7a4ff706c226872fab07d8a7535260d63b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -641,21 +641,22 @@ static void wait_system_ready (char *message, volatile int *start_flag) { #endif /*! - * \brief The Asynchronous RX FH thread of RAU/RCC/eNB. + * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU. * This handles the RX FH for an asynchronous RRU/UE * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_asynch_rx( void* param ) { +static void* eNB_thread_asynch_rxtx( void* param ) { - static int eNB_thread_asynch_rx_status; + static int eNB_thread_asynch_rxtx_status; eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - openair0_timestamp timestamp_rx; - int frame_rx,subframe_rx; + openair0_timestamp timestamp_rx,timestamp_tx; + int frame_rx,subframe_rx=0,subframe_tx=0; static int first_rx = 1; + static int first_tx = 1; uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; @@ -768,40 +769,67 @@ static void* eNB_thread_asynch_rx( void* param ) { printf( "got sync (eNB_thread_asynch_rx)\n" ); - if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF - - if (eNB->rfdevice.trx_read_func) - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - (void**)dummy_rx, - fp->samples_per_tti, - fp->nb_antennas_rx); - else { - printf("eNB asynch RX\n"); - sleep(1); - } - if (rxs!=fp->samples_per_tti) { - exit_fun("error receiving samples\n"); + + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for devices (eNB_thread_asynch_rx)\n"); + pthread_mutex_lock( &proc->mutex_asynch_rxtx); + + while (proc->instance_cnt_asynch_rxtx<0) + pthread_cond_wait( &proc->cond_asynch_rxtx, &proc->mutex_asynch_rxtx ); + + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + + printf( "devices ok (eNB_thread_asynch_rx)\n"); + + while (!oai_exit) { + if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF + + if (eNB->rfdevice.trx_read_func) + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &proc->timestamp_rx, + (void**)dummy_rx, + fp->samples_per_tti, + fp->nb_antennas_rx); + else { + printf("eNB asynch RX\n"); + sleep(1); + } + if (rxs!=fp->samples_per_tti) { + exit_fun("error receiving samples\n"); + } } - } - else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF + else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - if (first_rx == 1) { - first_rx = 0; - subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; - } - else { - // check timestamp - if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) - printf("RX overflow ...\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + if (first_rx == 1) { + first_rx = 0; + subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; + } + else { + // check timestamp + if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) + printf("RX overflow ...\n"); + + } + } // eNodeB_3GPP_BBU + + else if (eNB->node_function == NGFI_RRU_IF5) { + /// **** recv_IF5 of rxdata from RRH **** /// + + subframe_tx = (subframe_tx+1)%10; + + recv_IF5(eNB, ×tamp_tx, subframe_tx, IF5_RRH_GW_DL); + printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); + if (first_tx == 1) { + first_tx = 0; + subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; + } + } - } // eNodeB_3GPP_BBU - - else if (eNB->node_function == NGFI_RCC_IF4p5) { + else if (eNB->node_function == NGFI_RCC_IF4p5) { /// **** recv_IF4p5 of rxdataF from RRU **** /// /// **** recv_IF4p5 of rxsigF from RRU **** /// // get frame/subframe information from IF4p5 interface @@ -811,10 +839,10 @@ static void* eNB_thread_asynch_rx( void* param ) { symbol_mask = 0; symbol_mask_full = (1<<fp->symbols_per_tti)-1; prach_rx = 0; - + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); - + if (packet_type == IF4p5_PULFFT) { symbol_mask = symbol_mask | (1<<symbol_number); prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0; @@ -834,9 +862,9 @@ static void* eNB_thread_asynch_rx( void* param ) { else { // should not get here AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } - - eNB_thread_asynch_rx_status=0; - return(&eNB_thread_asynch_rx_status); + } + eNB_thread_asynch_rxtx_status=0; + return(&eNB_thread_asynch_rxtx_status); } void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { @@ -848,16 +876,17 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { if (proc->first_rx==0) { - // Transmit TX buffer based on timestamp from RX + // Transmit TX buffer based on timestamp from RX + printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers for (i=0; i<fp->nb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+2)%10)*fp->samples_per_tti]; txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice, - proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + proc->timestamp_rx+(2*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, txp, fp->samples_per_tti, fp->nb_antennas_tx, @@ -877,7 +906,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][*subframe*fp->samples_per_tti]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, &(proc->timestamp_rx), rxp, @@ -888,6 +917,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + printf("trx_read <- USRP TS %llu (sf %d, first_rx %d)\n", proc->timestamp_rx,proc->subframe_rx,proc->first_rx); if (proc->first_rx == 0) { if (proc->subframe_rx != *subframe){ @@ -1232,6 +1262,12 @@ static void* eNB_thread_FH( void* param ) { if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); + // unlock asnych_rxtx thread + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { @@ -1527,6 +1563,7 @@ void init_eNB_proc(int inst) { proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; proc->instance_cnt_FH = -1; + proc->instance_cnt_asynch_rxtx = -1; proc->CC_id = CC_id; proc->first_rx=4; @@ -1534,24 +1571,27 @@ void init_eNB_proc(int inst) { pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); + pthread_cond_init( &proc->cond_asynch_rxtx, NULL); #ifndef DEADLINE_SCHEDULER pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); + if ((eNB->node_timing == synch_to_other) || + (eNB->node_function == NGFI_RRU_IF5)) + pthread_create( &proc->pthread_asynch_rxtx, &proc->attr_asynch_rxtx, eNB_thread_asynch_rxtx, &eNB->proc ); #else pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); + pthread_create( &proc->pthread_asynch_rxtx, NULL, eNB_thread_asynch_rxtx, &eNB->proc ); #endif char name[16]; @@ -1767,7 +1807,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = NULL; eNB->fep = eNB_fep_rru_if5; eNB->proc_uespec_rx = NULL; - eNB->proc_tx = proc_tx_rru_if5; + eNB->proc_tx = NULL; eNB->tx_fh = NULL; eNB->rx_fh = rx_rf; eNB->start_rf = start_rf;