Commit 74dc4811 authored by Cedric Roux's avatar Cedric Roux

bladeRF: have it functional with libbladerf 2.0

Not much has been changed in the driver (that used libbladerf 1.0).
Some bugs have been fixed. Documentation has been added. A configuration
file has been added too, put in the directory ./configuration/bladeRF.

To use a bladeRF device, see documentation in targets/ARCH/BLADERF/README.

Only the BladeRF x40 has been tested.

Performance is not too bad at 5MHz, a bit worse at 10MHz and on the test
machine I used I face realtime problems at 20MHz when I push downlink
throughput.

So, there is still some work to do to have a good support of bladeRF.
parent 47437903
Active_eNBs = ( "eNB-Eurecom-LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
eNBs =
(
{
# real_time choice in {hard, rt-preempt, no}
real_time = "no";
////////// Identification parameters:
eNB_ID = 0xe00;
cell_type = "CELL_MACRO_ENB";
eNB_name = "eNB-Eurecom-LTEBox";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = (
{ mcc = 208; mnc = 92; mnc_length = 2; }
);
tr_s_preference = "local_mac"
////////// Physical parameters:
component_carriers = (
{
node_function = "eNodeB_3GPP";
node_timing = "synch_to_ext_device";
node_synch_ref = 0;
nb_antenna_ports = 1;
ue_TransmissionMode = 1;
frame_type = "FDD";
tdd_config = 3;
tdd_config_s = 0;
prefix_type = "NORMAL";
eutra_band = 7;
downlink_frequency = 2680000000L;
uplink_frequency_offset = -120000000;
Nid_cell = 0;
N_RB_DL = 25;
Nid_cell_mbsfn = 0;
nb_antennas_tx = 1;
nb_antennas_rx = 1;
prach_root = 0;
tx_gain = 90;
rx_gain = 115;
pbch_repetition = "FALSE";
prach_config_index = 0;
prach_high_speed = "DISABLE";
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 0;
pdsch_referenceSignalPower = -29;
pdsch_p_b = 0;
pusch_n_SB = 1;
pusch_enable64QAM = "DISABLE";
pusch_hoppingMode = "interSubFrame";
pusch_hoppingOffset = 0;
pusch_groupHoppingEnabled = "ENABLE";
pusch_groupAssignment = 0;
pusch_sequenceHoppingEnabled = "DISABLE";
pusch_nDMRS1 = 1;
phich_duration = "NORMAL";
phich_resource = "ONESIXTH";
srs_enable = "DISABLE";
/* srs_BandwidthConfig =;
srs_SubframeConfig =;
srs_ackNackST =;
srs_MaxUpPts =;*/
pusch_p0_Nominal = -96;
pusch_alpha = "AL1";
pucch_p0_Nominal = -108;
msg3_delta_Preamble = 6;
pucch_deltaF_Format1 = "deltaF2";
pucch_deltaF_Format1b = "deltaF3";
pucch_deltaF_Format2 = "deltaF0";
pucch_deltaF_Format2a = "deltaF0";
pucch_deltaF_Format2b = "deltaF0";
rach_numberOfRA_Preambles = 64;
rach_preamblesGroupAConfig = "DISABLE";
/*
rach_sizeOfRA_PreamblesGroupA = ;
rach_messageSizeGroupA = ;
rach_messagePowerOffsetGroupB = ;
*/
rach_powerRampingStep = 4;
rach_preambleInitialReceivedTargetPower = -108;
rach_preambleTransMax = 10;
rach_raResponseWindowSize = 10;
rach_macContentionResolutionTimer = 48;
rach_maxHARQ_Msg3Tx = 4;
pcch_default_PagingCycle = 128;
pcch_nB = "oneT";
bcch_modificationPeriodCoeff = 2;
ue_TimersAndConstants_t300 = 1000;
ue_TimersAndConstants_t301 = 1000;
ue_TimersAndConstants_t310 = 1000;
ue_TimersAndConstants_t311 = 10000;
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
//Parameters for SIB18
rxPool_sc_CP_Len = "normal";
rxPool_sc_Period = "sf40";
rxPool_data_CP_Len = "normal";
rxPool_ResourceConfig_prb_Num = 20;
rxPool_ResourceConfig_prb_Start = 5;
rxPool_ResourceConfig_prb_End = 44;
rxPool_ResourceConfig_offsetIndicator_present = "prSmall";
rxPool_ResourceConfig_offsetIndicator_choice = 0;
rxPool_ResourceConfig_subframeBitmap_present = "prBs40";
rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000";
rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
/* rxPool_dataHoppingConfig_hoppingParameter = 0;
rxPool_dataHoppingConfig_numSubbands = "ns1";
rxPool_dataHoppingConfig_rbOffset = 0;
rxPool_commTxResourceUC-ReqAllowed = "TRUE";
*/
// Parameters for SIB19
discRxPool_cp_Len = "normal"
discRxPool_discPeriod = "rf32"
discRxPool_numRetx = 1;
discRxPool_numRepetition = 2;
discRxPool_ResourceConfig_prb_Num = 5;
discRxPool_ResourceConfig_prb_Start = 3;
discRxPool_ResourceConfig_prb_End = 21;
discRxPool_ResourceConfig_offsetIndicator_present = "prSmall";
discRxPool_ResourceConfig_offsetIndicator_choice = 0;
discRxPool_ResourceConfig_subframeBitmap_present = "prBs40";
discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff";
discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
}
);
srb1_parameters :
{
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
timer_poll_retransmit = 80;
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
timer_reordering = 35;
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
timer_status_prohibit = 0;
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
poll_pdu = 4;
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
poll_byte = 99999;
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
max_retx_threshold = 4;
}
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// MME parameters:
mme_ip_address = ( { ipv4 = "192.168.12.148";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth1";
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.196/24";
ENB_INTERFACE_NAME_FOR_S1U = "eth1";
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.196/24";
ENB_PORT_FOR_S1U = 2152; # Spec 2152
ENB_IPV4_ADDRESS_FOR_X2C = "192.168.12.196/24";
ENB_PORT_FOR_X2C = 36422; # Spec 36422
};
log_config :
{
global_log_level ="info";
global_log_verbosity ="high";
hw_log_level ="info";
hw_log_verbosity ="medium";
phy_log_level ="info";
phy_log_verbosity ="medium";
mac_log_level ="info";
mac_log_verbosity ="high";
rlc_log_level ="debug";
rlc_log_verbosity ="high";
pdcp_log_level ="info";
pdcp_log_verbosity ="high";
rrc_log_level ="info";
rrc_log_verbosity ="medium";
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
phy_test_mode = 0;
puSch10xSnr = 210;
puCch10xSnr = 210;
}
);
THREAD_STRUCT = (
{
parallel_config = "PARALLEL_RU_L1_TRX_SPLITaaaaaa";
worker_config = "ENABLE";
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 73
att_rx = 0;
bands = [7];
max_pdschReferenceSignalPower = -28;
max_rxgain = 96;
eNB_instances = [0];
}
);
log_config :
{
global_log_level ="info";
global_log_verbosity ="high";
hw_log_level ="info";
hw_log_verbosity ="medium";
phy_log_level ="info";
phy_log_verbosity ="medium";
mac_log_level ="info";
mac_log_verbosity ="high";
rlc_log_level ="info";
rlc_log_verbosity ="high";
pdcp_log_level ="info";
pdcp_log_verbosity ="high";
rrc_log_level ="info";
rrc_log_verbosity ="medium";
};
BladeRF documentation
=====================
As of 2018-11-06, the bladeRF support is not fully automatic and requires
some manual settings before use. This documentation is the ultimate source
of information. If something described in this file does not work or does
not correspond to the reality, then contact us so we can fix the problems
and update this documentation.
1. Install bladeRF 2.0 libraries.
As of now, it's better to install from source.
So, do not run: ./build_oai -I -w BLADERF
(That is: do not include '-w BLADERF'.)
Instead, follow the instructions at: https://github.com/Nuand/bladeRF
If you already had some bladeRF software installed using automatic
methods, first remove it by hand ('apt-get purge bladeRF' or something
similar, you can get the list of installed bladeRF packages by running
'dpkg -l|grep -i blade', remove them all).
2. Update the device.
Download the latest FX3 firmware and FPGA images from Nuand's website.
As of writing, this is:
https://github.com/Nuand/bladeRF/wiki
That points to the following pages.
For FX3:
http://www.nuand.com/fx3_images/
For FPGA:
http://www.nuand.com/fpga_images/
Install FX3 firmware:
sudo bladeRF-cli -f bladeRF_fw_latest.img
Install FPGA image (this is for BladeRF x40):
sudo bladeRF-cli -L hostedx40-latest.rbf
Retrieve calibration information:
sudo bladeRF-cli -i
info
That outputs the serial number of your device.
Go to:
https://www.nuand.com/calibration
And enter your serial number.
The website tells you to run something like:
sudo bladeRF-cli -i
flash_init_cal 40 0x9271
Actual values depend on your device and serial number.
3. Calibrate the bladeRF device.
We will work with band 7 on 2.68GHz with a bandwidth of 5 MHz (25 RBs).
Plug the bladeRF device, then run:
sudo bladeRF-cli -i
set frequency tx 2680000000
set frequency rx 2560000000
set gain rx 60
set gain tx 60
set bandwidth 5000000
set samplerate 7680000
cal lms
cal lms
cal lms
cal dc rxtx
cal dc rxtx
cal dc rxtx
4. Tune the RX gain using the enb tracer.
Run the softmodem and the 'enb' tracer. For instructions, see:
https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/T/basic
In the enb window, check the 'input signal'. You should see some blue
signal as seen at:
https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/T/enb
(the 'Time signal power' plot).
The level should be around 30.
If it's not around 30 then edit your configuration file and modify
the value 'max_rxgain' in the section 'RUs'.
The configuration file to use is:
configuration/bladeRF/enb-band7-5mhz.conf
In the configuration file, you also need to set the correct values for:
- tracking_area_code
- plmn_list: mcc, mnc, mnc_length
- mme_ip_address: this is the IP address used by the computer running
the softmodem to connect to the EPC
- NETWORK_INTERFACES: all the ENB*ADDRESS* variables have to point
to the IP address of the EPC machine
5. You're good to go.
You can now connect a UE and pass some traffic. If everything is well
configured you can expect more than 16 Mb/s of throughput in the downlink
using iperf and more than 8 Mb/s in the uplink. Looking at the logs, you
should find lines containing 'PHR 40' and 'CQI 15'. If your values are
lower then your setup may need some adjustments.
6. In case of problems.
If the performance of the softmodem is very bad, you can stop it and
run the calibration again, without setting the parameters (frequencies,
gains, etc.). Just run:
sudo bladeRF-cli -i
cal lms
cal dc rxtx
That may help.
Be sure to use proper radio equipment (duplexer, antennas, clean
environment without interferences).
......@@ -116,15 +116,6 @@ int trx_brf_start(openair0_device *device) {
abort();
}
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_TX)) != 0) {
fprintf(stderr,"Failed to calibrate TX DC: %s\n", bladerf_strerror(status));
abort();
}
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_RX)) != 0) {
fprintf(stderr,"Failed to calibrate RX DC: %s\n", bladerf_strerror(status));
abort();
}
return 0;
}
......@@ -235,8 +226,6 @@ static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp,
* \param device the hardware to use
*/
void trx_brf_end(openair0_device *device) {
abort();
int status;
brf_state_t *brf = (brf_state_t*)device->priv;
// Disable RX module, shutting down our underlying RX stream
......@@ -247,6 +236,7 @@ abort();
fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status));
}
bladerf_close(brf->dev);
exit(1);
}
/*! \brief print the BladeRF statistics
......@@ -362,6 +352,8 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) {
*/
void calibrate_rf(openair0_device *device) {
/* TODO: this function does not seem to work. Disabled until fixed. */
return;
brf_state_t *brf = (brf_state_t *)device->priv;
openair0_timestamp ptimestamp;
......@@ -1005,6 +997,12 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
// RX
// Example of CLI output: RX Frequency: 2539999999Hz
if ((status=bladerf_set_gain_mode(brf->dev, BLADERF_MODULE_RX, BLADERF_GAIN_MGC))) {
fprintf(stderr, "[BRF] Failed to disable AGC\n");
brf_error(status);
}
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_freq[0])) != 0){
fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
brf_error(status);
......@@ -1096,17 +1094,14 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
// calibrate
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_TX)) != 0) {
fprintf(stderr,"Failed to calibrate TX DC: %s\n", bladerf_strerror(status));
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_LPF_TUNING)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_TX_LPF)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RX_LPF)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RXVGA2)) != 0) {
fprintf(stderr, "[BRF] error calibrating\n");
brf_error(status);
} else
printf("[BRF] TX module calibrated DC \n");
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_RX)) != 0) {
fprintf(stderr,"Failed to calibrate RX DC: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] RX module calibrated DC \n");
printf("[BRF] calibration OK\n");
bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg->log_level));
......@@ -1146,8 +1141,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
* \returns 0 on success
*/
int brf_error(int status) {
//exit(-1);
fprintf(stderr, "[BRF] brf_error: %s\n", bladerf_strerror(status));
exit(-1);
return status; // or status error code
}
......@@ -1190,7 +1185,7 @@ struct bladerf * open_bladerf_from_serial(const char *serial) {
int get_brf_log_level(int log_level){
int level=BLADERF_LOG_LEVEL_INFO;
return BLADERF_LOG_LEVEL_DEBUG; // BLADERF_LOG_LEVEL_VERBOSE;// BLADERF_LOG_LEVEL_DEBUG; //
return BLADERF_LOG_LEVEL_INFO;
switch(log_level) {
case LOG_DEBUG:
level=BLADERF_LOG_LEVEL_DEBUG;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment