Commit 9bbd2522 authored by Robert Schmidt's avatar Robert Schmidt

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
parents 77cdb057 a73989b7
......@@ -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.
......
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.
......@@ -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;
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();
LOG_I(HW, "first_call set from phy cb\n");
first_call_set = true;
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_ */
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