srsLTE 源码分析 UE_011 随机接入之 RAR处理

前言

前面一篇文章用了思维导图的方式,发现思维导图对代码流程的展现的确比较清晰,后续将继续延续思维导图的方式,由于图片较长,读者可以保存下来细细琢磨。LTE的系统还是一个比较大的系统,由于写文章的时间不多,更新会比较慢。如果项目中有用到srsLTE的代码或者希望得到相关培训的读者,可以私信作者。码字不易,请喜欢本系列文章的读者 点赞+收藏+关注!

代码流程思维导图

本篇文章主要将介绍srsLTE的RAR相关代码,先看一张RAR流程的代码流程图,可以结合后面的分析代码,再看一下这张图,收获可能会更大。
在这里插入图片描述

RAR(MSG2)的结构

在这里插入图片描述

RAR MAC header

MAC头大小可变,由下列域组成:
——E:扩展域,扩展域是一个标志位,指示MAC头中是否还有其他的域。如果E域设定为“1”,则表示其后至少还有另一组E/T/RAPID域。如果E域设置为“0”,表示从其后的字节起为MAC RAR或者填充;
——T:类型域,类型域是一个标志位,指示MAC子头中包含的是一个随机接入前导码ID还是一个Backoff指示。如果T域为“0”,指示子头中存在一个Backoff指示(BI)域。如果T域为“1”,指示子头中存在一个随机接入前导码ID(RAPID)域;
——R::预留比特,设置为 “0”;
——BI:Backoff指示域表明小区处于过载状态。BI域的长度为4bits;
——RAPID:随机接入前导码标识域指明了已发送的随机接入前导码, RAPID域的长度为6bits。UE会根据这个RAPID和自己发送的preamble进行比较,如果相同,则说明这个RAR是发给自己的,否则,丢弃这次的RAR
MAC头和子头都是字节对齐。

RAR MAC payload

MAC RAR长度固定,包含下列域:
——R::预留比特,设置为 “0”;
——Timing Advance Command:时间提前命令域,指示用于UE时间调整量的索引值, TA (0, 1, 2… 1282) 。时间提前命令域的长度是11bits;UE收到RAR之后,需要将TA的值配置给物理层,由物理层控制后续MSG3在空口的时延,以保证不同UE的信号到达基站的时间大致是一致的
——UL Grant:上行授权域,指示用于上行传输的资源 。上行授权域的长度是20 bits,MSG3实际上就是使用该资源发送
——Temporary C-RNTI:临时C-RNTI 域,指示UE在随机接入过程中使用的临时C-RNTI,临时C-RNTI 域的长度是16 bits,TC-RNTI在MSG3的加扰和解扰中会用到
MAC RAR字节对齐。

RA-RNTI

LTE常见RNTI用途

在这里插入图片描述

RA-RNTI的计算

RA-RNTI的用途仅用于随机接入响应这条消息,基站往UE发送RAR时,PDCCH和PDSCH需要使用RA-RNTI进行加扰,UE也需要使用RA-RNTI进行解扰。这里有一个问题,UE和基站是如何使用相同的RA-RNTI的呢?答案是UE和基站会使用相同的公式独立进行计算,由于输入的参数是相同的,因此,得到RA-RNTI也是一致的

公式: RA-RNTI= 1 + t_id+10*f_id
t_id为指定PRACH资源第一个子帧的索引,取值范围为(0≤ t_id <10);f_id为该子帧指定的PRACH以频域递增顺序的索引,取值范围为(0≤ f_id< 6)。

RAR的接收窗口

一旦随机接入前导码被传输,不考虑是否有测量间隔,为接收到随机接入响应,UE应在随机接入响应窗中监测以RA-RNTI为标识的PDCCH。随机接入响应窗始于包含前导码发送结束的子帧加上3个子帧,窗长为ra-ResponseWindowSize个子帧长。
这里有的读者可能比较难以理解为什么要加上3个子帧,因为从prach被发送开始计算,基站需要处理prach,并且基站还要调度RAR,这都是需要时间的,也就是说在prach之后的3个TTI,UE不会得到RAR

代码流程分析

这里需要搞清楚的一点是,随机接入的整个流程是由MAC层控制的,物理层在哪个TTI需要解哪个RNTI等都受MAC的控制。

cc_worker::work_dl_regular()

bool cc_worker::work_dl_regular()
{
  bool dl_ack[SRSLTE_MAX_CODEWORDS] = {};

  mac_interface_phy_lte::tb_action_dl_t dl_action = {};

  bool found_dl_grant = false;

  sf_cfg_dl.sf_type = SRSLTE_SF_NORM;

  // Set default channel estimation
  ue_dl_cfg.chest_cfg = chest_default_cfg;

  /* For TDD, when searching for SIB1, the ul/dl configuration is unknown and need to do blind search over
   * the possible mi values
   */
  uint32_t mi_set_len;
  if (cell.frame_type == SRSLTE_TDD && !sf_cfg_dl.tdd_config.configured) {
    mi_set_len = 3;
  } else {
    mi_set_len = 1;
  }

  // Blind search PHICH mi value
  for (uint32_t i = 0; i < mi_set_len && !found_dl_grant; i++) {

    if (mi_set_len == 1) {
      srslte_ue_dl_set_mi_auto(&ue_dl);
    } else {
      srslte_ue_dl_set_mi_manual(&ue_dl, i);
    }

    /* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */
    if (srslte_ue_dl_decode_fft_estimate(&ue_dl, &sf_cfg_dl, &ue_dl_cfg) < 0) {
      Error("Getting PDCCH FFT estimate\n");
      return false;
    }

    /* Look for DL and UL dci(s) if this is PCell, or no cross-carrier scheduling is enabled */
    if ((cc_idx == 0) || (!ue_dl_cfg.cfg.dci.cif_present)) {
      //解下行的DCI
      found_dl_grant = decode_pdcch_dl() > 0;
      //解上行的DCI
      decode_pdcch_ul();
    }
  }

  srslte_dci_dl_t dci_dl       = {};
  uint32_t        grant_cc_idx = 0;
  bool            has_dl_grant = phy->get_dl_pending_grant(CURRENT_TTI, cc_idx, &grant_cc_idx, &dci_dl);

  // If found a dci for this carrier, generate a grant, pass it to MAC and decode the associated PDSCH
  if (has_dl_grant) {

    // Read last TB from last retx for this pid
    for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
      ue_dl_cfg.cfg.pdsch.grant.last_tbs[i] = phy->last_dl_tbs[dci_dl.pid][cc_idx][i];
    }
    // Generate PHY grant
    if (srslte_ue_dl_dci_to_pdsch_grant(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, &dci_dl, &ue_dl_cfg.cfg.pdsch.grant)) {
      Error("Converting DCI message to DL dci\n");
      return -1;
    }

    // Save TB for next retx
    for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
      phy->last_dl_tbs[dci_dl.pid][cc_idx][i] = ue_dl_cfg.cfg.pdsch.grant.last_tbs[i];
    }

    // Set RNTI
    ue_dl_cfg.cfg.pdsch.rnti = dci_dl.rnti;

    // Generate MAC grant
    mac_interface_phy_lte::mac_grant_dl_t mac_grant = {};
    dl_phy_to_mac_grant(&ue_dl_cfg.cfg.pdsch.grant, &dci_dl, &mac_grant);

    // Save ACK resource configuration
    srslte_pdsch_ack_resource_t ack_resource = {dci_dl.dai, dci_dl.location.ncce, grant_cc_idx, dci_dl.tpc_pucch};

    // Send grant to MAC and get action for this TB, then call tb_decoded to unlock MAC
    //new_grant_dl会分配空间,下行的数据会存放在该空间,分配时需要下行DCI的信息
    phy->stack->new_grant_dl(cc_idx, mac_grant, &dl_action);
     //物理层根据DCI信息解decode_pdsch,并将数据放在指定的位置
    decode_pdsch(ack_resource, &dl_action, dl_ack);
    //通知高层进行tb的处理,如HARQ等,这里是高层协议栈处理数据的总的入口
    phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack);
  }

  /* Decode PHICH */
  decode_phich();

  return true;
}

cc_worker::decode_pdcch_dl()



int cc_worker::decode_pdcch_dl()
{
  int nof_grants = 0;
  //得到需要解扰需要的RNTI,不同的RNTI的搜索空间不一样,这个和TM模式,TS方式有关,在后续专题再介绍。
  uint16_t dl_rnti = phy->stack->get_dl_sched_rnti(CURRENT_TTI);
  if (dl_rnti != SRSLTE_INVALID_RNTI) {
    srslte_dci_dl_t dci[SRSLTE_MAX_CARRIERS] = {};

    /* Blind search first without cross scheduling then with it if enabled */
    for (int i = 0; i < (ue_dl_cfg.cfg.dci.cif_present ? 2 : 1) && !nof_grants; i++) {
      Debug("PDCCH looking for rnti=0x%x\n", dl_rnti);
      ue_dl_cfg.cfg.dci.cif_enabled = i > 0;
      //物理层会根据输入在不同的搜索空间尝试搜索下行DCI
      nof_grants                    = srslte_ue_dl_find_dl_dci(&ue_dl, &sf_cfg_dl, &ue_dl_cfg, dl_rnti, dci);
      if (nof_grants < 0) {
        Error("Looking for DL grants\n");
        return -1;
      }
    }

    // If RAR dci, save TTI
    if (nof_grants > 0 && SRSLTE_RNTI_ISRAR(dl_rnti)) {
    //设置RAR的RNTI
      phy->set_rar_grant_tti(CURRENT_TTI);
    }

    for (int k = 0; k < nof_grants; k++) {
      // Save dci to CC index
      phy->set_dl_pending_grant(CURRENT_TTI, dci[k].cif_present ? dci[k].cif : cc_idx, cc_idx, &dci[k]);

      // Logging
      if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) {
        char str[512];
        srslte_dci_dl_info(&dci[k], str, 512);
        log_h->info("PDCCH: cc=%d, %s, snr=%.1f dB\n", cc_idx, str, ue_dl.chest_res.snr_db);
      }
    }
  }
  return nof_grants;
}

cc_worker::work_dl_regular()

// Process Timing Advance Command as defined in Section 5.2
void ra_proc::process_timeadv_cmd(uint32_t ta)
{
  if (preambleIndex == 0) {
    // Preamble not selected by UE MAC
    phy_h->set_timeadv_rar(ta);
    // Only if timer is running reset the timer
    if (time_alignment_timer->is_running()) {
      time_alignment_timer->run();
    }
    Debug("Applying RAR TA CMD %d\n", ta);
  } else {
    // Preamble selected by UE MAC
    if (!time_alignment_timer->is_running()) {
      //TA下发给物理层,后续通过MAC-CE下发的TA也要下发物理层
      phy_h->set_timeadv_rar(ta);
      time_alignment_timer->run();
      Debug("Applying RAR TA CMD %d\n", ta);
    } else {
      // Ignore TA CMD
      Warning("Ignoring RAR TA CMD because timeAlignmentTimer still running\n");
    }
  }
}

/* Called upon the reception of a DL grant for RA-RNTI
 * Configures the action and softbuffer for the reception of the associated TB
 */
void ra_proc::new_grant_dl(mac_interface_phy_lte::mac_grant_dl_t grant, mac_interface_phy_lte::tb_action_dl_t* action)
{
  bzero(action, sizeof(mac_interface_phy_lte::tb_action_dl_t));

  if (grant.tb[0].tbs < MAX_RAR_PDU_LEN) {
    rDebug("DL dci found RA-RNTI=%d\n", ra_rnti);
    action->tb[0].enabled       = true;
    //指定TB解码的位置,后续的处理从这里取数据
    action->tb[0].payload       = rar_pdu_buffer;
    action->tb[0].rv            = grant.tb[0].rv;
    action->tb[0].softbuffer.rx = &softbuffer_rar;
    rar_grant_nbytes            = grant.tb[0].tbs;
    if (action->tb[0].rv == 0) {
      srslte_softbuffer_rx_reset(&softbuffer_rar);
    }
  } else {
    rError("Received RAR dci exceeds buffer length (%d>%d)\n", grant.tb[0].tbs, MAX_RAR_PDU_LEN);
  }
}

/* Called upon the successful decoding of a TB addressed to RA-RNTI.
 * Processes the reception of a RAR as defined in 5.1.4
 */
void ra_proc::tb_decoded_ok(const uint8_t cc_idx, const uint32_t tti)
{
  if (pcap) {
    pcap->write_dl_ranti(rar_pdu_buffer, rar_grant_nbytes, ra_rnti, true, tti, cc_idx);
  }

  rDebug("RAR decoded successfully TBS=%d\n", rar_grant_nbytes);

  rar_pdu_msg.init_rx(rar_grant_nbytes);
  rar_pdu_msg.parse_packet(rar_pdu_buffer);

  // Set Backoff parameter
  if (rar_pdu_msg.has_backoff()) {
    backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff() % 16];
  } else {
    backoff_param_ms = 0;
  }

  current_ta = 0;

  while (rar_pdu_msg.next()) {
   //判断RAR是否是属于自己的
    if (rar_pdu_msg.get()->has_rapid() && rar_pdu_msg.get()->get_rapid() == sel_preamble) {

      rar_received = true;
      //处理TA
      process_timeadv_cmd(rar_pdu_msg.get()->get_ta_cmd());

      // TODO: Indicate received target power
      // phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep);

      uint8_t grant[srslte::rar_subh::RAR_GRANT_LEN];
      rar_pdu_msg.get()->get_sched_grant(grant);

      rntis->rar_rnti = 0;
      phy_h->set_rar_grant(grant, rar_pdu_msg.get()->get_temp_crnti());

      current_ta = rar_pdu_msg.get()->get_ta_cmd();

      rInfo("RAPID=%d, TA=%d, T-CRNTI=0x%x\n",
            sel_preamble,
            rar_pdu_msg.get()->get_ta_cmd(),
            rar_pdu_msg.get()->get_temp_crnti());

      if (preambleIndex > 0) {
      	//非竞争
        // Preamble selected by Network
        complete();
      } else {
        // Preamble selected by UE MAC
        //准备发送MSG3
        mux_unit->msg3_prepare();
        //保存TC-RNTI
        rntis->temp_rnti = rar_pdu_msg.get()->get_temp_crnti();

        // If this is the first successfully received RAR within this procedure, Msg3 is empty
        if (mux_unit->msg3_is_empty()) {

          // Save transmitted C-RNTI (if any)
          transmitted_crnti = rntis->crnti;

          // If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission
          if (transmitted_crnti) {
          	//MSG3是MAC-CE CRNTI的情况
            rInfo("Appending C-RNTI MAC CE 0x%x in next transmission\n", transmitted_crnti);
            mux_unit->append_crnti_ce_next_tx(transmitted_crnti);
          }
        }

        // Save transmitted UE contention id, as defined by higher layers
        //保存竞争ID,后续收到MSG4之后,判断是否竞争解决
        transmitted_contention_id = rntis->contention_id;

        rDebug("Waiting for Contention Resolution\n");
        state = CONTENTION_RESOLUTION;
      }
    } else {
      if (rar_pdu_msg.get()->has_rapid()) {
        rInfo("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
      }
    }
  }
}
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值