編譯和仿真指令
基于版本:OAI_develop_210827。對nr-softmodem,也就是 gnb進行解析。
下載下傳後編譯 先用git init指令,然後chmod 777 -R把檔案夾内權限設定一下。
develop的編譯:
sudo ./build_oai -w USRP --eNB --nrUE --gNB -g -G -V -x -P --ue-trace --ue-timing --build-lib telnetsrv --build-lib all
NR_UE_SA的編譯:
sudo ./build_oai -w USRP --eNB --nrUE --gNB -g -G -P --build-lib all
分别用-P和取消-P分别編譯一次。
gdb 調試和仿真:
ue端:
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path ./ -d
server端: (在ubuntu終端中輸入export RFSIMULATOR=server,并用env指令檢視)
sudo cgdb --args ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --rfsim --phy-test -d --command set enviroment RFSIMULATOR=server --rfsimulator.options saviq
讀取配置
調試指令:
對NR_SSB的一些配置(讀取nr_init_frame_parms()運作後的fp結構體):
{freq_range = nr_FR1, N_RB_DL = 106, N_RB_UL = 106, N_RBG = 0 '\000', N_RBGS = 0 '\000',
nr_band = 78, dl_CarrierFreq = 3619080000, ul_CarrierFreq = 3619080000, att_tx = 0, att_rx
= 0, frame_type = TDD, tdd_config = 0 '\000', Nid_cell = 0, subcarrier_spacing = 30000,
threequarter_fs = 0 '\000', ofdm_symbol_size= 2048, nb_prefix_samples = 144,
nb_prefix_samples0 = 176, first_carrier_offset = 1412, symbols_per_slot = 14,
slots_per_subframe = 2, slots_per_frame = 20, samples_per_subframe = 61440,
samples_per_slot0 = 30720, samples_per_slotN0 = 30688, samples_per_frame = 614400,
samples_per_subframe_wCP = 57344, samples_per_slot_wCP = 28672, samples_per_frame_wCP =
573440, numerology_index = 1 '\001', nb_antennas_tx = 1 '\001', nb_antennas_rx = 1 '\001',
nb_antenna_ports_gNB = 0 '\000', Ncp = NORMAL, symbol_rotation = {{0 <repeats 448 times>},
{0 <repeats 448 times>}}, nushift = 0 '\000', srs_nr = {active_srs_Resource_Set = 0 '\000',
number_srs_Resource_Set = 0 '\000', p_SRS_ResourceSetList = {0x0}}, ss_PBCH_BlockPower = 0,
p_tdd_UL_DL_Configuration = 0x0, p_tdd_UL_DL_ConfigurationCommon2 = 0x0,
p_TDD_UL_DL_ConfigDedicated = 0x0, tdd_uplink_nr = {0 <repeats 320 times>}, half_frame_bit
= 0 '\000', ssb_start_subcarrier = 0, ssb_type = nr_ssb_type_C, Lmax = 8 '\b', L_ssb =
9223372036854775808, N_ssb = 1 '\001', ssb_index = 0 '\000', pbch_polar_params = {idx = 0,
nextPtr = 0x0, n_max = 0 '\000', i_il = 0 '\000', i_seg = 0 '\000', n_pc = 0 '\000',
n_pc_wm = 0 '\000', i_bil = 0 '\000', payloadBits = 0, encoderLength = 0, crcParityBits = 0
'\000', crcCorrectionBits = 0 '\000', K = 0, N = 0, n = 0 '\000', crcBit = 0,
interleaving_pattern = 0x0, deinterleaving_pattern = 0x0, rate_matching_pattern = 0x0,
Q_0_Nminus1 = 0x0, Q_I_N = 0x0, Q_F_N = 0x0, Q_PC_N = 0x0, information_bit_pattern = 0x0,
channel_interleaver_pattern = 0x0, crc_generator_matrix = 0x0, G_N = 0x0, G_N_tab = 0x0,
groupsize = 0, rm_tab = 0x0, cprime_tab0 = {{0 <repeats 256 times>} <repeats 32 times>},
cprime_tab1 = {{0 <repeats 256 times>} <repeats 32 times>}, B_tab0 = {{0 <repeats 256
times>} <repeats 32 times>}, B_tab1 = {{0 <repeats 256 times>} <repeats 32 times>},
extended_crc_generator_matrix = 0x0, nr_polar_crc = 0x0, nr_polar_aPrime = 0x0,
nr_polar_APrime = 0x0, nr_polar_D = 0x0, nr_polar_E = 0x0, nr_polar_A = 0x0, nr_polar_CPrime = 0x0, nr_polar_B = 0x0, nr_polar_U = 0x0, tree = {root = 0x0, num_nodes =
0}}}
資料發送:
按slot來發送。一個子幀是2個,是以大多數情況是0.5ms發送一次。
tx_rf()中ru->rfdevice.trx_write_func()進行發送。這個函數指針在usrp發送指向trx_usrp_write()。在RFSIMULATOR=server仿真下,指向 rfsimulator_write_internal()進行的資料發送。
發送的資料長度為nsamps,位址為txp, 如下進行指派:
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension];
在rx_func()末尾,如果滿足下面的條件,則啟動tx_func()。
tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT
發送函數作用解釋:
- tx_func(): 生成bit幀(dci、csi,旋轉等),主要調用phy_procedures_gNB_TX()。在rx_func()末尾可以啟動。 在Tpool0_1 ~ Tpool7_-1共8個線程中來承載運作;
- ru_tx_func() : 射頻前端、OFDM調制,調用ru->fh_south_out()函數指針,指向tx_rf(),以通過射頻usrp或者仿真網口發出去。ru_tx_func()在tx_func()末尾啟動。 ofdm調制調用Tpoll線程的nr_feptx_prec來實作。 在Tpool0_1 ~ Tpool7_-1共8個線程中承載運作;
- nr_feptx_prec() :OFDM調試、波束預編碼。由線程"feptx"承載運作。 由線程Tpool0_1 ~ Tpool7_-1裡面的tx_func(),通過nr_feptx_ofdm_2thread()調用。
讀取發送儲存的檔案
運作時添加參數 --rfsimulator.options saviq。預設儲存位置為tmp/rfsimulator.iqs
matlab讀取的對應代碼為:
clear;clc;close all;
format LONGG;
fid = fopen('Z:\work\data\rfsimulator.iqs','r');
skip = 0; % by bytes
Nframe = 100;
for i = 1:Nframe
header = fread(fid,8,'uint32');
frame.header.magic = header(1) * 2^32 + header(2);
frame.header.size = header(3);
frame.header.nbAnt = header(4);
frame.header.timestamp = header(5) * 2^32 + header(6);
frame.header.option_value = header(7);
frame.header.option_flag = header(8);
skip = skip + 32;
fseek(fid,skip,1); % by bytes
size = frame.header.size;
data = fread(fid,size*2,'int16');
frame.real=data(1:2:end-1);
frame.img =data(2:2:end);
frame.cmx = frame.real + 1j * frame.img;
skip = skip + size * 4;
fseek(fid,skip,1); % by bytes
FrameS(i) = frame;
end
fclose(fid);
# 線程池及調用
發送和接收的主要函數是ru_thread(),通過thread_FH線程承載。這個線程又調用函數tx_func()和ru_tx_func()。這兩個函數都是通過Tpool0_1 ~ Tpool7_-1線程池承載。tx_func裡面的OFDM調制又通過調用nr_feptx_prec()裡面的nr_feptx_ofdm_2thread()來實作。而nr_feptx_prec是通過線程feptx來承載。
ru_thread()裡面也把接收的資料發給scope,用于顯示;
函數通過 pushTpool()如 pushTpool (gNB->threadPool, res)調用函數。如讀取 res内容可以看到線程運作的函數 ru_tx_func():
(gdb) p *res
$39 = {next = 0x0, key = 3, reponseFifo = 0x39c2c40, processingFunc = 0x6b0633 <ru_tx_func>, malloced = true, creationTime = 0, startProcessingTime = 0, endProcessingTime = 0, returnTime = 0, msgData = 0x7fffe001e6c0}
該線程池的詳解見:“線程池Code詳解" 作者 從善若水。
pullTpool() : 傳回可用的線程;pushTpool()運作線程。裡面有線程上一個處理函數和下一個處理函數
如tx_func()裡面語句:
res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
在此處斷點,列印
p *gNB->resp_RU_tx->outF
p *gNB->resp_RU_tx->inF