From 570ac353f1205bb2baf84430227ddebfb653ea27 Mon Sep 17 00:00:00 2001 From: Raymond Knopp <raymond.knopp@eurecom.fr> Date: Sun, 4 Mar 2018 18:38:43 +0100 Subject: [PATCH] frame resynchronization in RAU and RRU --- openair1/PHY/defs.h | 14 +++- targets/RT/USER/lte-enb.c | 17 ++-- targets/RT/USER/lte-ru.c | 167 ++++++++++++++++++++++---------------- 3 files changed, 117 insertions(+), 81 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 8b868222895..8e89433b70c 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -559,7 +559,9 @@ typedef struct eNB_proc_t_s { /// mutex for RU access to eNB processing (PRACH BR) pthread_mutex_t mutex_RU_PRACH_br; /// mask for RUs serving eNB (PDSCH/PUSCH) - int RU_mask; + int RU_mask[10]; + /// time measurements for RU arrivals + struct timespec t[10]; /// mask for RUs serving eNB (PRACH) int RU_mask_prach; #ifdef Rel14 @@ -687,7 +689,8 @@ typedef enum { /// Some commamds to RRU. Not sure we should do it like this ! typedef enum { EMPTY = 0, - STOP_RU = 1 + STOP_RU = 1, + RU_FRAME_RESYNCH = 2 } rru_cmd_t; typedef struct RU_t_s{ @@ -709,6 +712,8 @@ typedef struct RU_t_s{ int rx_offset; /// flag to indicate the RU is a slave to another source int is_slave; + /// counter to delay start of processing of RU until HW settles + int wait_cnt; /// Total gain of receive chain uint32_t rx_total_gain_dB; /// number of bands that this device can support @@ -812,6 +817,8 @@ typedef struct RU_t_s{ rru_state_t state; /// Command to do rru_cmd_t cmd; + /// value to be passed using command + uint16_t cmdval; /// process scheduling variables RU_proc_t proc; /// stats thread pthread descriptor @@ -1501,7 +1508,8 @@ typedef enum { RRU_config_ok=4, RRU_start=5, RRU_stop=6, - RRU_sync_ok=7 + RRU_sync_ok=7, + RRU_frame_resynch=8 } rru_config_msg_type_t; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index b300aac83eb..e36bde783c0 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -225,6 +225,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam // UE-specific RX processing for subframe n if (nfapi_mode == 0 || nfapi_mode == 1) { + LOG_I(PHY,"Calling RX procedures for SFNSF %d.%d\n",proc->frame_rx,proc->subframe_rx); phy_procedures_eNB_uespec_RX(eNB, proc, no_relay ); } @@ -250,7 +251,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam if (oai_exit) return(-1); - LOG_D(PHY,"Calling eNB_procedures_TX for SFN.SF %d.%d\n",proc->frame_tx,proc->subframe_tx); + LOG_I(PHY,"Calling eNB_procedures_TX for SFN.SF %d.%d\n",proc->frame_tx,proc->subframe_tx); phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1); stop_meas( &softmodem_stats_rxtx_sf ); @@ -416,21 +417,21 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) { pthread_mutex_lock(&proc->mutex_RU); for (i=0;i<eNB->num_RU;i++) { if (ru == eNB->RU_list[i]) { - if ((proc->RU_mask&(1<<i)) > 0) + if ((proc->RU_mask[ru->proc.subframe_rx]&(1<<i)) > 0) LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<<i); + eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask[ru->proc.subframe_rx]); + proc->RU_mask[ru->proc.subframe_rx] |= (1<<i); }else if (eNB->RU_list[i]->state == RU_SYNC){ - proc->RU_mask |= (1<<i); + proc->RU_mask[ru->proc.subframe_rx] |= (1<<i); } } - if (proc->RU_mask != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return + if (proc->RU_mask[ru->proc.subframe_rx] != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return LOG_E(PHY,"Not all RUs have provided their info\n"); pthread_mutex_unlock(&proc->mutex_RU); return(0); } else { // all RUs have provided their information so continue on and wakeup eNB processing - proc->RU_mask = 0; + proc->RU_mask[ru->proc.subframe_rx] = 0; pthread_mutex_unlock(&proc->mutex_RU); } @@ -724,7 +725,7 @@ void init_eNB_proc(int inst) { proc->first_rx=1; proc->first_tx=1; - proc->RU_mask=0; + for (i=0;i<10;i++) proc->RU_mask[i]=0; proc->RU_mask_prach=0; pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 38ede8340da..ea89667c85a 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -584,6 +584,7 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); + if (ru->cmd == STOP_RU) break; // grab first prach information for this new subframe if (got_prach_info==0) { prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx); @@ -793,6 +794,12 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ru->nb_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + + if (ru->cmd==RU_FRAME_RESYNCH) { + ru->ts_offset += (proc->frame_rx - ru->cmdval)*fp->samples_per_tti*10; + *frame = ru->cmdval; + ru->cmd=EMPTY; + } proc->timestamp_rx = ts-ru->ts_offset; @@ -1240,6 +1247,7 @@ void wakeup_eNBs(RU_t *ru) { PHY_VARS_eNB **eNB_list = ru->eNB_list; PHY_VARS_eNB *eNB=eNB_list[0]; eNB_proc_t *proc = &eNB->proc; + struct timespec t; LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d (state %s)ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru_states[ru->state],ru->eNB_top); @@ -1248,32 +1256,36 @@ void wakeup_eNBs(RU_t *ru) { char string[20]; sprintf(string,"Incoming RU %d",ru->idx); - LOG_D(PHY,"Frame %d, Subframe %d: RU %d Waking up eNB,RU_mask %x\n",ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,proc->RU_mask); pthread_mutex_lock(&proc->mutex_RU); + LOG_D(PHY,"Frame %d, Subframe %d: RU %d done,RU_mask[%d] %x\n",ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx]); + + if (proc->RU_mask[ru->proc.subframe_rx] == 0) + clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]); for (i=0;i<eNB->num_RU;i++) { LOG_D(PHY,"RU %d state %s\n",eNB->RU_list[i]->idx,ru_states[eNB->RU_list[i]->state]); if (ru == eNB->RU_list[i]) { // AssertFatal((proc->RU_mask&(1<<i)) == 0, "eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",eNB->Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<<i); - }else if (eNB->RU_list[i]->state == RU_SYNC){ - proc->RU_mask |= (1<<i); + proc->RU_mask[ru->proc.subframe_rx] |= (1<<i); + }else if (eNB->RU_list[i]->state == RU_SYNC || eNB->RU_list[i]->wait_cnt > 0){ + proc->RU_mask[ru->proc.subframe_rx] |= (1<<i); } } - LOG_D(PHY,"RU mask is now %x\n",proc->RU_mask); - if (proc->RU_mask != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU); - return(0); + LOG_D(PHY,"RU mask is now %x\n",proc->RU_mask[ru->proc.subframe_rx]); + + if (proc->RU_mask[ru->proc.subframe_rx] == (1<<eNB->num_RU)-1) { + proc->RU_mask[ru->proc.subframe_rx] = 0; + clock_gettime(CLOCK_MONOTONIC,&t); + AssertFatal(t.tv_nsec > proc->t[ru->proc.subframe_rx].tv_nsec+500000, + "Time difference for subframe %d => %d > 5ms\n", + ru->proc.subframe_rx,t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec); } - else { // all RUs have provided their information so continue on and wakeup eNB processing - proc->RU_mask = 0; - pthread_mutex_unlock(&proc->mutex_RU); - } - + + pthread_mutex_unlock(&proc->mutex_RU); LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx); ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string); } - else { + else { // multiple eNB case for later LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB); @@ -1564,9 +1576,8 @@ static void* ru_thread_control( void* param ) { break; case RRU_capabilities: // RAU - if (ru->if_south == LOCAL_RF){ - LOG_I(PHY,"Received RRU_capab msg...Ignoring\n"); - } + if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_capab msg...Ignoring\n"); + else{ msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); @@ -1629,15 +1640,13 @@ static void* ru_thread_control( void* param ) { "RU %d failed send CONFIG_OK to RAU\n",ru->idx); reset_proc(ru); ru->state = RU_READY; - }else{ - LOG_I(PHY,"Received RRU_config msg...Ignoring\n"); - } + } else LOG_E(PHY,"Received RRU_config msg...Ignoring\n"); + break; case RRU_config_ok: // RAU - if (ru->if_south == LOCAL_RF){ - LOG_I(PHY,"Received RRU_config_ok msg...Ignoring\n"); - }else{ + if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n"); + else{ if (setup_RU_buffers(ru)!=0) { printf("Exiting, cannot initialize RU Buffers\n"); @@ -1701,27 +1710,30 @@ static void* ru_thread_control( void* param ) { break; } } - else{ - LOG_I(PHY,"RRU not ready, cannot start\n"); - } - }else{ - LOG_I(PHY,"Received RRU_start msg...Ignoring\n"); - } + else LOG_E(PHY,"RRU not ready, cannot start\n"); + + } else LOG_E(PHY,"Received RRU_start msg...Ignoring\n"); + break; case RRU_sync_ok: //RAU - if (ru->if_south == LOCAL_RF){ - LOG_I(PHY,"Received RRU_config_ok msg...Ignoring\n"); - }else{ + if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n"); + else{ if (ru->is_slave == 1){ + LOG_I(PHY,"Received RRU_sync_ok from RRU %d\n",ru->idx); // Just change the state of the RRU to unblock ru_thread() ru->state = RU_RUN; - }else{ - LOG_I(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n"); - } + }else LOG_E(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n"); } break; + case RRU_frame_resynch: //RRU + if (ru->if_south != LOCAL_RF) LOG_E(PHY,"Received RRU frame resynch message, should not happen in RAU\n"); + else { + ru->cmd = RU_FRAME_RESYNCH; + ru->cmdval = ((uint16_t*)&rru_config_msg.msg[0])[0]; + } + break; case RRU_stop: // RRU if (ru->if_south == LOCAL_RF){ @@ -1735,9 +1747,8 @@ static void* ru_thread_control( void* param ) { }else{ LOG_I(PHY,"RRU not running, can't stop\n"); } - }else{ - LOG_I(PHY,"Received RRU_stop msg...Ignoring\n"); - } + }else LOG_E(PHY,"Received RRU_stop msg...Ignoring\n"); + break; default: @@ -1778,16 +1789,17 @@ static void* ru_thread( void* param ) { LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]); - while (!oai_exit) { + if (ru->if_south != LOCAL_RF) ru->wait_cnt = 100; + else ru->wait_cnt = 0; // wait to be woken up if (wait_on_condition(&ru->proc.mutex_ru,&ru->proc.cond_ru_thread,&ru->proc.instance_cnt_ru,"ru_thread")<0) break; - if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru->state = %d != RU_RUN\n",ru->state); - else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC,"ru->state = %d != RU_SYNC\n",ru->state); + if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru-%d state = %s != RU_RUN\n",ru->idx,ru_states[ru->state]); + else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN,"ru %d state = %s != RU_SYNC or RU_RUN\n",ru->idx,ru_states[ru->state]); // Start RF device if any if (ru->start_rf) { if (ru->start_rf(ru) != 0) @@ -1826,10 +1838,6 @@ static void* ru_thread( void* param ) { subframe++; } - LOG_D(PHY,"RU thread %d, frame %d (%p), subframe %d (%p)\n", - ru->idx, frame,&frame,subframe,&subframe); - - // synchronization on input FH interface, acquire signals/data and block if (ru->stop_rf && ru->cmd == STOP_RU) { @@ -1848,43 +1856,62 @@ static void* ru_thread( void* param ) { if (ru->fh_south_in && ru->state == RU_RUN ) ru->fh_south_in(ru,&frame,&subframe); else AssertFatal(1==0, "No fronthaul interface at south port"); - - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) { - wakeup_prach_ru(ru); + if (ru->wait_cnt > 0) { + ru->wait_cnt--; + + if (ru->if_south!=LOCAL_RF && ru->wait_cnt <=20 && subframe == 5 && frame != RC.ru[0]->proc.frame_rx) { + // Send RRU_frame adjust + RRU_CONFIG_msg_t rru_config_msg; + rru_config_msg.type = RRU_frame_resynch; + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len + ((uint16_t*)&rru_config_msg.msg[0])[0] = RC.ru[0]->proc.frame_rx; + LOG_I(PHY,"Sending Frame Resynch %d to RRU\n", ru->idx,RC.ru[0]->proc.frame_rx); + AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU %d\n",ru->idx); + + } } + else { + + LOG_D(PHY,"RU thread %d, frame %d, subframe %d \n", + ru->idx,frame,subframe); + + + if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) { + wakeup_prach_ru(ru); + } #ifdef Rel14 - else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) { - wakeup_prach_ru_br(ru); - } + else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) { + wakeup_prach_ru_br(ru); + } #endif - // adjust for timing offset between RU - if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; + // adjust for timing offset between RU + if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; - // At this point, all information for subframe has been received on FH interface - // If this proc is to provide synchronization, do so - wakeup_slaves(proc); + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + wakeup_slaves(proc); - // do RX front-end processing (frequency-shift, dft) if needed - if (ru->feprx) ru->feprx(ru); + // do RX front-end processing (frequency-shift, dft) if needed + if (ru->feprx) ru->feprx(ru); - // wakeup all eNB processes waiting for this RU - if (ru->num_eNB>0) wakeup_eNBs(ru); + // wakeup all eNB processes waiting for this RU + if (ru->num_eNB>0) wakeup_eNBs(ru); - // wait until eNBs are finished subframe RX n and TX n+4 - wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread"); + // wait until eNBs are finished subframe RX n and TX n+4 + wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread"); - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru); + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru); - // do OFDM if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + // do OFDM if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); - if (ru->fh_north_out) ru->fh_north_out(ru); - + if (ru->fh_north_out) ru->fh_north_out(ru); + } } } // while !oai_exit -- GitLab