UG-1828 Preliminary Technical Data
Rev. PrC | Page 38 of 338
SPI Access
As stated in the previous section, programming the API to use custom SPI code in execution is as easy as calling #define
CUSTOMER_PLATFORM in adi_platform.c, however some thought should be given to the SPI code provided. A common issue
encountered at this stage in development is a lack of response from the device over the SPI lines, sometimes accompanied by an “ARM
Boot Up Timed Out” error message. These issues can often be very confusing, as they happen directly after the Hw_Open() runs
successfully.
The issue arises due to a discrepancy between the “standard” bitfield control of SPI settings (CPOL, CPHA, etc.) and the approach Analog
Devices takes with SPI control of our devices. Where most devices use normal Binary encodings for their SPI control (00, 01, 10, 11), ADI
uses Grey Code for SPI control (00, 01, 11, 10).
As for register access, as has been stated previously, we do not provide the register map for this device to customers. All register access is
handled via the APIs. This means that as Register maps change and update, customer code remains valid simply by updating the SDK.
Confirming the SPI operation for custom platforms is possible with a few simple tests. Having read the SPI section of this User Guide, we
know that the ADRV9001 transceivers use 3-Byte interactions for SPI communication: {Command}{Address}{Data}. Knowing this, we
can monitor the SPI interactions using a scope and record the interactions between the default platform (ZC706 or ZCU102) and the
ADRV9001 device. We can do the same for any custom platform. Provided the device setup is identical between default platform and
custom platform, the SPI interactions should also be identical.
In the absence of any external equipment, there are also APIs one can use to verify the SPI operation. One such API is
adi_adrv9001_spi_Verify(…), which performs the following functions:
1. Reads readonly register to check SPI read operation.
2. Writes scratchpad register with 10110110, reads back the data.
3. Writes scratchpad register with 01001001, reads back the data.
APIs such as these are often described in our documentation as “This function is a helper function and does not need to be called directly
by the user”, however there’s nothing a user from calling them early in their platform setup regardless.
Raspberry Pi HAL
Below we provide some rudimentary examples of how a customer might choose to fill the above listed functions for a Raspberry Pi platform
as an example. The Broadcom SPI library for the Raspberry Pi is used to handle all configurations and interactions with the ADRV9001
product. Given that the Raspberry Pi’s connectivity is limited to the GPIO pin headers, individual pins are used for the Chip Enable signal
and the RESET signal. This is done to allow for fine control on the interaction timings.
In the _hal_open(…) function, the Raspberry Pi’s SPI interface is initialized and configured to match the desired behavior and the Chip
Enable pin is configured as an output. The _hal_close(…) function, by contrast, simply ends all SPI activity.
Next are the _hal_spi_write(…) and _hal_spi_read(…) functions. In accordance with the workings of the bcm2835 library being used, these
functions write data to the ADRV9001 product after driving the Chip Enable line low, In the case of the _hal_spi_read(…) function, data
is also accepted from the device on the DO line (MISO on the Raspberry Pi).
Lastly is the _hal_resetPin(…) function. When provided with a value (1 or 0) this function drives the RESET pin high or low.
#include "adi_adrv9001_hal_customer.h"
#include "bcm2835.h" //rpi spi library
#define CE_PIN RPI_BPLUS_GPIO_J8_37
#define RESET_PIN RPI_BPLUS_GPIO_J8_36
int32_t customer_adi_adrv9001_hal_open(void *devHalCfg)
{
/* Customer code goes here */
if (!bcm2835_init())
{
printf("bcm2835_init failed. Are you running as root??\n");
return 1;
}