Merge remote-tracking branch 'origin/fhi-72-cleanup-doc' into integration_2025_w12 (!3285)
Update FHI 7.2 documentation, minor code cleanup - remove some unused functions - make one function static - add callback function documentation - provide some developer function
This commit is contained in:
@@ -1059,10 +1059,10 @@ section](.#build-oai-gnb)) to see if it resolves the problem.
|
||||
# Operation with multiple RUs
|
||||
|
||||
It is possible to connect up to 4 RUs to one DU at the same time and operate
|
||||
them as a (single) distributed antenna (array). This works since all RUs and
|
||||
the DU are synchronized onto a common clock using PTP. The assumed
|
||||
configuration is that with N RUs each having an M×M configuration, we
|
||||
effectively reach an (N×M)×(N×M) configuration.
|
||||
them either with a single antenna array or a distributed antenna array. This
|
||||
works since all RUs and the DU are synchronized onto a common clock using PTP.
|
||||
The assumed configuration is that with N RUs each having an M×M configuration,
|
||||
we effectively reach an (N×M)×(N×M) configuration.
|
||||
|
||||
Some caveats:
|
||||
- Since it's a distributed antenna, this implies that this setup will deploy a
|
||||
|
||||
@@ -117,6 +117,7 @@ Some directories under `radio` contain READMEs:
|
||||
- [USRP](../radio/USRP/README.md)
|
||||
- [BladeRF](../radio/BLADERF/README)
|
||||
- [IQPlayer](../radio/iqplayer/DOC/iqrecordplayer_usage.md), and [general documentation](./iqrecordplayer_usage.md)
|
||||
- [fhi_72](../radio/fhi_72/README.md)
|
||||
|
||||
The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
This document describes the driver for the xran driver, implementing O-RAN FHI
|
||||
7.2 interface. This is for developers; for user documentation, consider the
|
||||
[O-RAN 7.2 tutorial instead](../../doc/ORAN_FHI7.2_Tutorial.md).
|
||||
|
||||
The main source files and their purpose are as follows:
|
||||
|
||||
- `oaioran.c`: definition of xran-specific callback functions.
|
||||
- `oran-config.c`: reading of 7.2-specific configuration and preparing xran
|
||||
configration.
|
||||
- `oran-init.c`: initialization of xran.
|
||||
- `oran_isolate.c`: main entry point and definition of function pointers for OAI
|
||||
callbacks.
|
||||
|
||||
The entry point for the driver library is `transport_init()` in `oran_isolate.c`.
|
||||
This function is concerned with setting necessary function pointers for OAI
|
||||
integration, and prepares xran configuration through `get_xran_config()`. This
|
||||
function reads 7.2 specific configuration and deduces some of the parameters
|
||||
(e.g., frequency) from OAI-provided radio configuration in `openair0_config_t`.
|
||||
|
||||
Actual xran initialization happens in `oai_oran_initialize()` in `oran-init.c`.
|
||||
It calls various helper function in the same file to set up DPDK memory buffer
|
||||
(pools). Notably, these callbacks are installed:
|
||||
|
||||
- `oai_xran_fh_rx_callback()` through `xran_5g_fronthault_config()`: callback
|
||||
for PUSCH data; used to provide timing data.
|
||||
- `oai_xran_fh_rx_prach_callback()` through `xran_5g_prach_req()`: callback for
|
||||
PRACH data; not currently used and implemented in PUSCH data callback.
|
||||
- `oai_physide_dl_tti_call_back()` through `xran_reg_physide_cb()`: only used
|
||||
to unblock timing in `oai_xran_fh_rx_callback()` upon first xran call.
|
||||
|
||||
More detailed information about the xran callbacks can be taken from the xran
|
||||
documentation.
|
||||
|
||||
During normal operation, OAI calls into the driver through functions
|
||||
`oran_fh_if4p5_south_in()` for PUSCH/PRACH and `oran_fh_if4p5_south_out()` for
|
||||
PDSCH.
|
||||
|
||||
For PDSCH, `oran_fh_if4p5_south_out()` calls `xran_fh_tx_send_slot()` that
|
||||
optionally compresses IQ data, then writes it into IQ buffers of xran.
|
||||
|
||||
For PUSCH/PRACH, `oran_fh_if4p5_south_in()` calls `xran_fh_rx_read_slot()` that
|
||||
blocks and waits for the next slot. This is done through either a message
|
||||
queue, or through polling, which in both cases depends on xran calling the
|
||||
callback `oai_xran_fh_rx_callback()` as installed during xran initialization.
|
||||
Once unblocked, it reads first PRACH data, then PUSCH data, before returning to
|
||||
OAI.
|
||||
+34
-24
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
|
||||
// Declare variable useful for the send buffer function
|
||||
volatile uint8_t first_call_set = 0;
|
||||
volatile bool first_call_set = false;
|
||||
|
||||
int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id);
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -54,6 +54,12 @@ extern notifiedFIFO_t oran_sync_fifo;
|
||||
#else
|
||||
volatile oran_sync_info_t oran_sync_info = {0};
|
||||
#endif
|
||||
|
||||
/** @details xran-specific callback, called when all packets for given CC and
|
||||
* 1/4, 1/2, 3/4, all symbols of a slot arrived. Currently, only used to get
|
||||
* timing information and unblock another thread in xran_fh_rx_read_slot()
|
||||
* through either a message queue, or writing in global memory with polling, on
|
||||
* a full slot boundary. */
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
{
|
||||
struct xran_cb_tag *callback_tag = (struct xran_cb_tag *)pCallbackTag;
|
||||
@@ -150,36 +156,23 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
last_frame = frame;
|
||||
} // rx_sym == 7
|
||||
}
|
||||
void oai_xran_fh_srs_callback(void *pCallbackTag, xran_status_t status)
|
||||
{
|
||||
rte_pause();
|
||||
}
|
||||
void oai_xran_fh_rx_prach_callback(void *pCallbackTag, xran_status_t status)
|
||||
{
|
||||
rte_pause();
|
||||
}
|
||||
|
||||
/** @details Only used to unblock timing in oai_xran_fh_rx_callback() on first
|
||||
* call. */
|
||||
int oai_physide_dl_tti_call_back(void *param)
|
||||
{
|
||||
if (!first_call_set)
|
||||
printf("first_call set from phy cb first_call_set=%p\n", &first_call_set);
|
||||
first_call_set = 1;
|
||||
LOG_I(HW, "first_call set from phy cb\n");
|
||||
first_call_set = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int oai_physide_ul_half_slot_call_back(void *param)
|
||||
{
|
||||
rte_pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int oai_physide_ul_full_slot_call_back(void *param)
|
||||
{
|
||||
rte_pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
/** @brief Reads PRACH data from xran buffers.
|
||||
*
|
||||
* @details Reads PRACH data from xran-specific buffers and, if I/Q compression
|
||||
* (bitwidth < 16 bits) is configured, uncompresses the data. Places PRACH data
|
||||
* in OAI buffer. */
|
||||
static int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
{
|
||||
/* calculate tti and subframe_id from frame, slot num */
|
||||
int sym_idx = 0;
|
||||
@@ -248,6 +241,11 @@ int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** @brief Check if symbol in slot is UL.
|
||||
*
|
||||
* @param frame_conf xran frame configuration
|
||||
* @param slot the current (absolute) slot (number)
|
||||
* @param sym_idx the current symbol index */
|
||||
static bool is_tdd_ul_symbol(const struct xran_frame_config *frame_conf, int slot, int sym_idx)
|
||||
{
|
||||
/* in FDD, every symbol is also UL */
|
||||
@@ -259,11 +257,20 @@ static bool is_tdd_ul_symbol(const struct xran_frame_config *frame_conf, int slo
|
||||
return frame_conf->sSlotConfig[slot_in_period].nSymbolType[sym_idx] == 1 /* UL */;
|
||||
}
|
||||
|
||||
/** @brief Check if current slot is DL or guard/mixed without UL (i.e., current
|
||||
* slot is not UL). */
|
||||
static bool is_tdd_dl_guard_slot(const struct xran_frame_config *frame_conf, int slot)
|
||||
{
|
||||
return !is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
|
||||
}
|
||||
|
||||
/** @details Read PRACH and PUSCH data from xran buffers. If
|
||||
* I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data
|
||||
* before writing. Prints ON TIME counters every 128 frames.
|
||||
*
|
||||
* Function is blocking and waits for next frame/slot combination. It is unblocked
|
||||
* by oai_xran_fh_rx_callback(). It writes the current slot into parameters
|
||||
* frame/slot. */
|
||||
int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
@@ -458,6 +465,9 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If
|
||||
* I/Q compression (bitwidth < 16 bits) is configured, compresses the data
|
||||
* before writing. */
|
||||
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
int tti = /*frame*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME+*/ 20 * frame
|
||||
|
||||
@@ -31,7 +31,9 @@ typedef struct {
|
||||
uint32_t f;
|
||||
} oran_sync_info_t;
|
||||
|
||||
/** @brief xran callback for fronthaul RX, see xran_5g_fronthault_config(). */
|
||||
void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status);
|
||||
/** @brief xran callback for time alignment, see xran_reg_physide_cb(). */
|
||||
int oai_physide_dl_tti_call_back(void *param);
|
||||
|
||||
#endif /* OAIORAN_H */
|
||||
|
||||
@@ -443,7 +443,7 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi
|
||||
pi->prach_tag = tag;
|
||||
pi->pusch_tag = tag;
|
||||
#ifdef E_RELEASE
|
||||
LOG_W(PHY, "Please be aware that E release support will be removed by the end of January 2025. Instead, F release will be mandatory.\n");
|
||||
LOG_W(PHY, "Please be aware that E release support will be removed in the future. Consider switching to F release.\n");
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]);
|
||||
#elif defined F_RELEASE
|
||||
oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, xran_fh_init->mtu, &xran_fh_config[o_xu_id]);
|
||||
|
||||
@@ -45,9 +45,13 @@ typedef struct ru_info_s {
|
||||
int16_t **prach_buf;
|
||||
} ru_info_t;
|
||||
|
||||
/** @brief Reads RX data (PRACH/PUSCH) of next slot.
|
||||
*
|
||||
* @param ru pointer to structure keeping pointers to OAI data.
|
||||
* @param frame output of the frame which has been read.
|
||||
* @param slot output of the slot which has been read. */
|
||||
int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot);
|
||||
/** @brief Writes TX data (PDSCH) of given slot. */
|
||||
int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp);
|
||||
|
||||
int compute_xran_statistics();
|
||||
|
||||
#endif /* _ORAN_ISOLATE_H_ */
|
||||
|
||||
Reference in New Issue
Block a user