The DFE PRACH software API uses the libmetal abstraction layer to provide a consistent interface and use model independent of any operating system in use.
Each instance of the DFE PRACH
core in the design requires a corresponding instance of an XDfePrach
API object in the software. The API object is created and bound
to the core using code such as the following.
/* Declare an instance pointer for the API object */
XDfePrach *InstancePtr = NULL;
/* Initialize an instance of the PRACH driver */
InstancePtr = XDfePrach_InstanceInit(XDFEPRACH_NODE_NAME);
The argument to XDfePrach_InstanceInit
is the
device ID. It controls how the API locates and binds to the core instance in hardware.
The symbol definitions required vary from platform to platform and are typically
generated using the Vitis development flow. When
using embedded Linux, the device ID comes from the device tree. When using a bare-metal
implementation, the device ID comes from the xparameters.h header file.
Once an API object has been created successfully, the DFE PRACH core should be reset to ensure that data processing is halted and the IP is returned to its default state prior to configuration. This can be done by the software API as follows.
/* Reset the PRACH core */
XDfePrach_Reset(InstancePtr);
In order to ensure that the expected versions of the IP core and software components are in use, the API provides a function to query the version numbers. An example of the usage of these functions is shown below. This also provides a useful initial check that the hardware registers can be read successfully by the processor.
/* Declare version number objects */
XDfePrach_Version SwVersion;
XDfePrach_Version HwVersion;
/* Get software and hardware version numbers */
XDfePrach_GetVersions(InstancePtr, &SwVersion, &HwVersion);
/* Print the version numbers to the console*/
printf("SW Version: Major %d, Minor %d\n", SwVersion.Major,
SwVersion.Minor);
printf("HW Version: Major %d, Minor %d, Revision %d, Patch %d\n",
HwVersion.Major, HwVersion.Minor, HwVersion.Revision,
HwVersion.Patch);
After a reset has been performed, call the XDfePrach_Configure
function to complete the low-level configuration of
the core. This function checks the configuration of the IP core instance against the
information in the device tree (when embedded Linux is used) or xparameters.h file (when a bare metal system is used).
XDfePrach_Configure
also releases the software
reset.
/* Declare a configuration object */
XDfePrach_Cfg Cfg;
/* Configure the IP instance */
XDfePrach_Configure(InstancePtr, &Cfg);
Once the DFE PRACH core is configured,
it must be initialized. The XDfePrach_Initialize
function prepares the core for use by setting up the features and parameters that must
remain fixed while the core is operating. The component carrier ID sequence length for
each band and the use of the static PRACH scheduler are parameters of this type. The
function is used as follows.
/* Declare and populate the initialization parameters object */
XDfePrach_Init Init;
Init.Sequence[0].Length = 16; // CCID sequence length for band 0 (must be a power of 2 and length * antenna interleave factor must be <16)
Init.Sequence[1].Length = 8; // CCID sequence length for band 1, if enabled (must be a power of 2 and length * antenna interleave factor must be <16)
Init.Sequence[2].Length = 8; // CCID sequence length for band 2, if enabled (must be a power of 2 and length * antenna interleave factor must be <16)
Init.EnableStaticSchedule = 1; // Enable static RACH scheduler
/* Initialize the IP core */
XDfePrach_Initialize(InstancePtr, &Init);
As well as setting the length of each band's sequence, the choice of static or
dynamic mode should be set here. This cannot be changed while the core is active.
Init.EnableStaticSchedule
will be used by an instance of the core
which has "Enable Dynamic Scheduling" selected. It is ignored in instances which do not
have this selected. After initialization is complete, the core is ready to be activated.
Activation brings the core into an operational state in which the core can process
data.
Activation applies across the whole core, regardless of the data from
each of the bands. Therefore, activation should be achieved using an immediate trigger.
It is possible to trigger the activate using the s_axis_din0_tuser
bus
and a single-shot trigger, but this is not recommended. The start position of the
component carrier sequence for each band is set by the FrameInit triggers.
The core activation function takes a Boolean argument which determines whether the low power mode should be enabled or disabled. An example of the core activation procedure is shown below.
/* Declare and populate a trigger configuration object */
XDfePrach_TriggerCfg TriggerCfg;
TriggerCfg.Activate.Mode = 0; // immediate trigger
/* Set the trigger configuration */
XDfePrach_SetTriggersCfg(InstancePtr, &TriggerCfg);
/* Activate the IP core (disabling the low power mode) */
XDfePrach_Activate(InstancePtr, false);
The call to XDfeMPrach_Activate
will
return immediately. The core is activated when the trigger condition is met.
To ensure that the core has successfully activated before proceeding, it is useful to check the activation status. This can be achieved by polling the Operational State register:
while (XDfePrach_ReadReg(InstancePtr, XDFEPRACH_STATE_OPERATIONAL_OFFSET )==0) {
}
This register read will check the operational status of the core and ensure that the software waits until the core has been activated.