frame resynchronization in RAU and RRU
This commit is contained in:
+11
-3
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+96
-69
@@ -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);
|
||||
}
|
||||
else { // all RUs have provided their information so continue on and wakeup eNB processing
|
||||
proc->RU_mask = 0;
|
||||
pthread_mutex_unlock(&proc->mutex_RU);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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->wait_cnt > 0) {
|
||||
ru->wait_cnt--;
|
||||
|
||||
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) {
|
||||
wakeup_prach_ru(ru);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user