ADRV9001 no-OS Example Project
Note: The ADRV9001 name in this document refers collectively to the ADRV9002, ADRV9003, and ADRV9004 device family. Within the document, ADRV9001 may be used interchangeably to address any of these specific models.
Supported Devices
ADRV9002 in ADRV9002NP/W2/PCBZ
Supported Carriers
ADRV9002 and ZCU102 using FMC HPC0 slot
ADRV9002 and ZC706 using FMC LPC slot
ADRV9002 and ZedBoard using FMC LPC slot
Overview
The ADRV9001 no-OS project enables integration of the ADRV9001
series (ADRV9002, ADRV9003, and ADRV9004) into embedded systems without
requiring an operating system. It employs a hardware abstraction layer
to manage SPI communication, GPIO functions, and platform-specific
settings, illustrated in no_os_platform.c and related headers.
Designed to work with Xilinx hardware platforms such as ZCU102, ZC706,
and ZedBoard, the project outlines build configurations in files like
src.mk and builds.json, detailing drivers for ADC/DAC cores and
potential IIO support. The file headless.c handles hardware
initialization, RX/TX channel configuration, and DMA management,
allowing for autonomous signal processing in a no-OS environment.
Applications
Mission critical communications
Very high frequency (VHF) applications
Ultrahigh frequency (UHF) applications
Cellular applications from 30 MHz to 6000 MHz
Time Division Duplexing (TDD) applications
Frequency Division Duplexing (FDD) applications
No-OS Build Setup
Please see: No-OS Build Guide
Project Layout and HDL Generation
This is how the adrv9001 no-OS project looks like as a file tree:
no-OS/projects/adrv9001/
├── Makefile
├── README.rst
├── src
│ ├── app
│ │ ├── headless.c
│ │ ├── Navassa_CMOS_profile.h
│ │ ├── Navassa_LVDS_profile.h
│ │ ├── ORxGainTable.h
│ │ ├── RxGainTable_GainCompensated.h
│ │ ├── RxGainTable.h
│ │ └── TxAttenTable.h
│ ├── firmware
│ │ ├── Navassa_EvaluationFw.h
│ │ └── Navassa_Stream.h
│ └── hal
│ ├── adi_platform.h
│ ├── adi_platform_types.h
│ ├── no_os_platform.c
│ ├── no_os_platform.h
│ └── parameters.h
├── src.mk
└── system_top.xsa
Note the presence of the system_top.xsa. In order to build this project, you need such an .xsa file present in the project directory, as shown above. In case you don't have one, either obtain a pre-built file or build it yourself by following the Building HDL guide.
And this is how the corresponding driver folder looks like as a file tree (the Navassa API can be found under common and devices directories):
no-OS/drivers/rf-transceiver/navassa/
├── adrv9002.c
├── adrv9002_conv.c
├── adrv9002.h
├── common
│ ├── adi_common_error.c
│ ├── adi_common_error.h
│ ├── adi_common_error_types.h
│ ├── adi_common.h
│ ├── adi_common_hal.h
│ ├── adi_common_hal_wrapper.c
│ ├── adi_common_hal_wrapper.h
│ ├── adi_common_log.c
│ ├── adi_common_log.h
│ ├── adi_common_macros.h
│ └── adi_common_types.h
├── devices
│ └── adrv9001
│ ├── private
│ │ ├── include
│ │ └── src
│ └── public
│ ├── include
│ └── src
└── third_party
├── adi_pmag_macros
└── jsmn
Switching Between Use Cases
When the implementation of a different use case than the one in the project folder is desired, the following steps have to be followed:
Implement the desired settings in ADRV9001 TES GUI and generate the files listed below:
Stream binary (e.g., TES_generated_stream.bin), by clicking on File->Generate Stream Image;
Profile JSON (e.g., TES_generated_profile.json), by clicking on File->Generate Profile File.
Since no-OS does not have mechanisms for manipulating files, create a hex dump for the stream .bin file. As can be seen in the project structure, the .bin files are added as header files to the project in the 'firmware' folder.
Use the following command for storing the hex dump in a file:
xxd -i TES_generated_stream.bin > Navassa_Stream.h
Copy the generated unsigned char array to the correspoding header file in the project's firmware folder.
The profile file also has to be transformed for being included in the project:
Generate string literals from the json files using the json2cstring.sh script:
./json2cstring path/TES_generated_profile.json
Copy the contents of the generated file to the corresponding header file in the file used as the current profile (CMOS or LVDS profile selected at build time using make
LVDS=yfor LVDS, or omitting the flag for the default CMOS profile).
Modify the code in the project so that the new settings are correctly used (e.g., headless.c).
Build the project.
No-OS Supported Examples
The demo applications highlight the functionality of the ADRV9002 evaluation board. Two examples are provided in the sample project:
DMA Example
IIO Example
DMA Example
DMA example is a standard example that sends a sinewave on Tx channels using DMA from a lookup table. If you physically loopback a Tx channel to an Rx channel via an electrical wire, you may run the DMA_EXAMPLE and read the received data at Rx from its particular memory address.
When DMA_EXAMPLE is disabled, a small LO leakage spike at the carrier frequency is normal. When DMA_EXAMPLE is enabled, a 1024-sample sine wave is transmitted in a continuous loop via cyclic DMA. The resulting spectrum shows equidistant spectral lines rather than a single clean tone, which is expected due to the repeating finite-length waveform.
The purpose of DMA_EXAMPLE is to verify that the TX and RX data paths — from memory through the DMA controller to the RF front-end and back — are functional. It is not designed to produce a spectrally pure output.
Select the example through command line arguments as below:
make IIOD=n DMA_EXAMPLE=y
To run the DMA example, you simply need to run the application as usual by:
making sure it was built with the
DMA_EXAMPLEflag (DMA_EXAMPLE=yas command line argument formake), as already mentioned,monitoring the serial terminal for messages printed by the application.
After the output from the basic example, the application will eventually print something like this:
DMA_EXAMPLE Rx2: address=0x105000 samples=32768 channels=2 bits=16
DMA_EXAMPLE Rx1: address=0xf5000 samples=32768 channels=2 bits=16
This means that the memory addresses where the data at Rx are stored are 0x105000
and 0xf5000. There are a total of 65536 (2x32768) samples, 16-bit wide across 4 channels,
which is equivalent to 32768, 16-bit samples per channel.
At this point you may use a Tcl script to retrieve data from memory and store it into .csv files for processing:
# Use the address printed by the application for DMA_EXAMPLE Rx1
# Loopback between Tx and Rx required
xsct tools/scripts/platform/xilinx/capture.tcl ZYNQ_PSU <address> 32768 2 16
You can find more information about the data here.
The data in the .csv files generated can be visualised using the plot.py script in the no-OS repository. The following command will display the data on 2 channels:
python tools/scripts/platform/xilinx/plot.py 2
IIO Example
IIO demo is a standard example, provided in most no-OS projects, that launches a IIOD server on the board so that the user may connect to it via an IIO client. Using iio-oscilloscope, the user can configure the DAC and view the ADC data on a plot.
To build the IIOD demo, add the following flags when invoking make which will build the IIOD server and the IIO section of the driver:
make IIOD=y
To run the IIOD demo, first connect to the board via UART to see the runtime output messages with the following settings:
Baud Rate: 115200bps
Data: 8 bit
Parity: None
Stop bits: 1 bit
Flow Control: none
Please note that for proper message display, you may need to convert all LF characters to CRLF, if your serial terminal supports it.
With a serial terminal correctly configured and listening to incoming messages, launch the application (make run or click the debug button in your SDK). Runtime messages specific to the application will appear on your serial terminal screen, and eventually the following message is printed, after the output from the basic example:
Running IIOD server...
If successful, you may connect an IIO client application by:
1. Disconnecting the serial terminal you use to view this message.
2. Connecting the IIO client application using the serial backend configured as shown:
Baudrate: 921600
Data size: 8 bits
Parity: none
Stop bits: 1
Flow control: none
This message implies a IIOD server is being run and you may connect to it using a serial-backend enabled iio-oscilloscope and with the settings indicated at the serial terminal.
No-OS Supported Platforms
Xilinx Platform
Hardware Used
Zynq UltraScale+™ MPSoC ZCU102 Evaluation Kit
ADRV9002NP/W2/PCBZ (Evaluation Board for ADRV9002)
Requirements
Hardware Setup:
Attach the ADRV9002 Evaluation Board to the ZCU102 through the FMC HPC0 connector.
Enable SD Card BOOT mode by switching SW6 to:
Switch
State
SW6-1
ON
SW6-2
ON
SW6-3
ON
SW6-4
ON
Connect a micro-USB cable to the ZCU102 board via the JTAG connector (J2), and the other end of the cable to the Host PC.
Connect a micro-USB cable to the ZCU102 board via the USB-UART connector (J83), and the other end of the cable to the Host PC.
Connect the power adapter to the ZCU102 board. via the power supply plug (J52).
Switch on the ZCU102 board using the SW1 switch.
Program the board via JTAG.
Observe application messages using a serial terminal.
Alternatively, a microSD card containing the BOOT.bin file generated during build
can be used for running the no-OS application.
Build Command
cp <SOME_PATH>/no-OS/projects/adrv9001/system_top.xsa .
# go to project folder
cd <SOME_PATH>/no-OS/projects/adrv9001/
# to delete current build
make reset
# to build the project
make
# to flash the code
make run
The following build flags are supported:
Flag |
Default |
Description |
|---|---|---|
|
|
Enable IIO daemon for use with IIO Oscilloscope |
|
|
Enable the DMA loopback example (sine wave TX, capture RX) |
|
|
Use the LVDS SSI profile instead of the default CMOS profile |
|
|
Enable RX2TX2 mode (combined RX1+RX2 and TX1+TX2 AXI cores) |
Example:
make DMA_EXAMPLE=y LVDS=y