Post Go back to editing

ARM Mailbox Busy – Command not executed in MYKONOS_sendArmCommand() during initialization

Thread Summary

The user encountered an 'ARM Mailbox Busy' error during initialization of AD9371 on a ZCU102-based evaluation setup. The error occurs in the `MYKONOS_loadArmFromBinary()` API, specifically when calling `MYKONOS_sendArmCommand()`. The SPI interface and power supply rails were verified to be functioning correctly. The support engineer suggested disabling SPI streaming mode and verifying SPI timings as per UG-992 (Page 20) to resolve the issue.
AI Generated Content
Category: Software
Product Number: AD9371
Software Version: Software:Mykonos No-OS drivers

Hi,

I am using ZCU102 (Ultrascale+) with AD9371 (Mykonos) and encountering the following error during initialization.

I have attached the TES-generated profile code and the initialization configuration files used for this setup for review.


Vitis Error Log Output

Please wait...
rx_clkgen: MMCM-PLL locked (76800000 Hz)
tx_clkgen: MMCM-PLL locked (153600000 Hz)
rx_os_clkgen: MMCM-PLL locked (153600000 Hz)
MCS successful
CLKPLL locked
ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()


Questions

  1. What conditions cause the ARM mailbox to remain busy?

  2. Does this indicate that the ARM firmware is not running correctly?

  3. Which debug registers should be checked before issuing ARM commands?

  4. Is there any mistake in my attached profiles?

Any suggestions or debug guidance would be greatly appreciated.

Thanks

myk.c 

/**
 * \brief Contains init setting structure declarations for the _instance API
 *
 * The top level structure mykonosDevice_t mykDevice uses keyword
 * extern to allow the application layer main() to have visibility
 * to these settings.
 * 
 * All data structures required for operation have been initialized with values which reflect these settings:
 * 
 * Device Clock:
 * 122.88MHz
 * 
 * Profiles:
 * Rx 100MHz, IQrate 153.6MSPS, Dec5
 * Tx 100/250MHz, IQrate 307.2MSPS, Dec5
 * ORX 240MHz, IQrate 307.2MSPS, Dec5
 * SRx 20MHz, IQrate 38.4MSPS, Dec5
 * 
 */

/**
  \page Disclaimer Legal Disclaimer
  Copyright 2015-2017 Analog Devices Inc.
  Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
 */

#include <stddef.h>
#include "t_mykonos.h"
#include "t_mykonos_gpio.h"
#include "myk.h"

static int16_t txFirCoefs[] = {-16,34,-95,215,-475,1136,-3455,22121,-4794,2304,-899,393,-177,76,-31,19};

static mykonosFir_t txFir =
{
    6,              /* Filter gain in dB*/
    16,             /* Number of coefficients in the FIR filter*/
    &txFirCoefs[0]  /* A pointer to an array of filter coefficients*/
};

static int16_t rxFirCoefs[] = {-16,-22,18,74,24,-132,-152,132,372,38,-598,-474,638,1178,-206,-1952,-984,2362,3152,-1612,-6544,-2164,12806,26836,26836,12806,-2164,-6544,-1612,3152,2362,-984,-1952,-206,1178,638,-474,-598,38,372,132,-152,-132,24,74,18,-22,-16};

static mykonosFir_t rxFir =
{
    -6,             /* Filter gain in dB*/
    48,             /* Number of coefficients in the FIR filter*/
    &rxFirCoefs[0]  /* A pointer to an array of filter coefficients*/
};

static int16_t obsrxFirCoefs[] = {-32,136,-348,747,-1404,2412,-3827,5730,-8371,10473,-13745,24655,27364,-16650,10146,-7384,4611,-2790,1593,-830,384,-148,43,0};
static mykonosFir_t obsrxFir =
{
    0,              /* Filter gain in dB*/
    24,             /* Number of coefficients in the FIR filter*/
    &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/
};

static int16_t snifferFirCoefs[] = {10,31,59,71,30,-92,-283,-456,-466,-175,440,1192,1683,1444,198,-1871,-3988,-4942,-3512,958,8118,16519,23993,28395,28395,23993,16519,8118,958,-3512,-4942,-3988,-1871,198,1444,1683,1192,440,-175,-466,-456,-283,-92,30,71,59,31,10};
static mykonosFir_t snifferRxFir=
{
    -12,            /* Filter gain in dB*/
    48,             /* Number of coefficients in the FIR filter*/
    &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/
};

static mykonosJesd204bFramerConfig_t rxFramer =
{
    0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
    0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
    0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
    2,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
    32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
    1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
    1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
    0x03,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
    0x04,           /* serializerLaneCrossbar*/
    22,             /* serializerAmplitude - default 22 (valid (0-31)*/
    4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
    0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
    0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
    0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
    0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
    0,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
    0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
    0,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
    0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
};

static mykonosJesd204bFramerConfig_t obsRxFramer =
{
    0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
    0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
    0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
    2,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
    32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
    1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
    1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
    0x0C,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
    0x40,           /* Lane crossbar to map framer lane outputs to physical lanes*/
    22,             /* serializerAmplitude - default 22 (valid (0-31)*/
    4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
    0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
    0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
    0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
    0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
    1,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
    0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
    1,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
    0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
};

static mykonosJesd204bDeframerConfig_t deframer =
{
    0,              /* bankId extension to Device ID (Valid 0..15)*/
    0,              /* deviceId  link identification number. (Valid 0..255)*/
    0,              /* lane0Id Lane0 ID. (Valid 0..31)*/
    2,              /* M  number of DACss (0, 2, or 4) - 2 DACs per transmit chain */
    32,             /* K  #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/
    1,              /* scramble  scrambling off if scramble= 0.*/
    1,              /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/
    0x03,           /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */
    0x04,           /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */
    1,              /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/
    0,              /* PN inversion per each lane.  bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/
    0,              /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/
    0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/
    0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
    0,              /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
    0               /* Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used*/
};

static mykonosRxGainControl_t rxGainControl =
{
    MGC,            /* Current Rx gain control mode setting*/
    255,            /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/
    255,            /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/
    255,            /* Max gain index for the currently loaded Rx1 Gain table*/
    195,            /* Min gain index for the currently loaded Rx1 Gain table*/
    255,            /* Max gain index for the currently loaded Rx2 Gain table*/
    195,            /* Min gain index for the currently loaded Rx2 Gain table*/
    0,              /* Stores Rx1 RSSI value read back from the Mykonos*/
    0               /* Stores Rx2 RSSI value read back from the Mykonos*/
};

static mykonosORxGainControl_t orxGainControl =
{
    MGC,            /* Current ORx gain control mode setting*/
    255,            /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/
    255,            /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/
    255,            /* Max gain index for the currently loaded ORx Gain table*/
    237             /* Min gain index for the currently loaded ORx Gain table*/
};

static mykonosSnifferGainControl_t snifferGainControl =
{
    MGC,            /* Current Sniffer gain control mode setting*/
    255,            /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/
    255,            /* Max gain index for the currently loaded Sniffer Gain table*/
    203             /* Min gain index for the currently loaded Sniffer Gain table*/
};

static mykonosPeakDetAgcCfg_t rxPeakAgc =
{
    0x26,	/* apdHighThresh: */
    0x16,	/* apdLowThresh */
    0xB5,	/* hb2HighThresh */
    0x72,	/* hb2LowThresh */
    0x40,	/* hb2VeryLowThresh */
    0x06,	/* apdHighThreshExceededCnt */
    0x04,	/* apdLowThreshExceededCnt */
    0x06,	/* hb2HighThreshExceededCnt */
    0x04,	/* hb2LowThreshExceededCnt */
    0x04,	/* hb2VeryLowThreshExceededCnt */
    0x4,	/* apdHighGainStepAttack */
    0x2,	/* apdLowGainStepRecovery */
    0x4,	/* hb2HighGainStepAttack */
    0x2,	/* hb2LowGainStepRecovery */
    0x4,	/* hb2VeryLowGainStepRecovery */
    0x1,	/* apdFastAttack */
    0x1,	/* hb2FastAttack */
    0x1,	/* hb2OverloadDetectEnable */
    0x1,	/* hb2OverloadDurationCnt */
    0x1	/* hb2OverloadThreshCnt */
};

static mykonosPowerMeasAgcCfg_t rxPwrAgc =
{
    0x01,	/* pmdUpperHighThresh */
    0x03,	/* pmdUpperLowThresh */
    0x0C,	/* pmdLowerHighThresh */
    0x04,	/* pmdLowerLowThresh */
    0x4,	/* pmdUpperHighGainStepAttack */
    0x2,	/* pmdUpperLowGainStepAttack */
    0x2,	/* pmdLowerHighGainStepRecovery */
    0x4,	/* pmdLowerLowGainStepRecovery */
    0x08,	/* pmdMeasDuration */
    0x02	/* pmdMeasConfig */
};

static mykonosAgcCfg_t rxAgcConfig =
{
    255,	/* agcRx1MaxGainIndex */
    195,	/* agcRx1MinGainIndex */
    255,	/* agcRx2MaxGainIndex */
    195,	/* agcRx2MinGainIndex: */
    255,	/* agcObsRxMaxGainIndex */
    203,	/* agcObsRxMinGainIndex */
    1,		/* agcObsRxSelect */
    1,		/* agcPeakThresholdMode */
    1,		/* agcLowThsPreventGainIncrease */
    30720,	/* agcGainUpdateCounter */
    3,	/* agcSlowLoopSettlingDelay */
    4,	/* agcPeakWaitTime */
    0,	/* agcResetOnRxEnable */
    0,	/* agcEnableSyncPulseForGainCounter */
    &rxPeakAgc,
    &rxPwrAgc
};

static mykonosPeakDetAgcCfg_t obsRxPeakAgc =
{
    0x2A,	/* apdHighThresh: */
    0x16,	/* apdLowThresh */
    0xB5,	/* hb2HighThresh */
    0x72,	/* hb2LowThresh */
    0x40,	/* hb2VeryLowThresh */
    0x03,	/* apdHighThreshExceededCnt */
    0x03,	/* apdLowThreshExceededCnt */
    0x03,	/* hb2HighThreshExceededCnt */
    0x03,	/* hb2LowThreshExceededCnt */
    0x03,	/* hb2VeryLowThreshExceededCnt */
    0x4,	/* apdHighGainStepAttack */
    0x2,	/* apdLowGainStepRecovery */
    0x4,	/* hb2HighGainStepAttack */
    0x2,	/* hb2LowGainStepRecovery */
    0x4,	/* hb2VeryLowGainStepRecovery */
    0x0,	/* apdFastAttack */
    0x0,	/* hb2FastAttack */
    0x1,	/* hb2OverloadDetectEnable */
    0x1,	/* hb2OverloadDurationCnt */
    0x1		/* hb2OverloadThreshCnt */
};

static mykonosPowerMeasAgcCfg_t obsRxPwrAgc =
{
    0x01,	/* pmdUpperHighThresh */
    0x03,	/* pmdUpperLowThresh */
    0x0C,	/* pmdLowerHighThresh */
    0x04,	/* pmdLowerLowThresh */
    0x0,	/* pmdUpperHighGainStepAttack */
    0x0,	/* pmdUpperLowGainStepAttack */
    0x0,	/* pmdLowerHighGainStepRecovery */
    0x0,	/* pmdLowerLowGainStepRecovery */
    0x08,	/* pmdMeasDuration */
    0x02	/* pmdMeasConfig */
};

static mykonosAgcCfg_t obsRxAgcConfig =
{
    255,	/* agcRx1MaxGainIndex */
    195,	/* agcRx1MinGainIndex */
    255,	/* agcRx2MaxGainIndex */
    195,	/* agcRx2MinGainIndex: */
    255,	/* agcObsRxMaxGainIndex */
    203,	/* agcObsRxMinGainIndex */
    1,		/* agcObsRxSelect */
    1,		/* agcPeakThresholdMode */
    1,		/* agcLowThsPreventGainIncrease */
    30720,	/* agcGainUpdateCounter */
    3,		/* agcSlowLoopSettlingDelay */
    4,		/* agcPeakWaitTime */
    0,		/* agcResetOnRxEnable */
    0,		/* agcEnableSyncPulseForGainCounter */
    &obsRxPeakAgc,
    &obsRxPwrAgc
};


static mykonosRxProfile_t rxProfile =
{/* Rx 100MHz, IQrate 153.6MSPS, Dec5 */
    1,              /* The divider used to generate the ADC clock*/
    &rxFir,         /* Pointer to Rx FIR filter structure*/
    2,              /* Rx FIR decimation (1,2,4)*/
    5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
    1,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
    1,              /* RX Half band 1 decimation (1 or 2)*/
    153600,         /* Rx IQ data rate in kHz*/
    100000000,      /* The Rx RF passband bandwidth for the profile*/
    100000,         /* Rx BBF 3dB corner in kHz*/
    NULL            /* pointer to custom ADC profile*/
};

static mykonosRxProfile_t orxProfile =
{/* ORX 240MHz, IQrate 307.2MSPS, Dec5 */
    1,              /* The divider used to generate the ADC clock*/
    &obsrxFir,      /* Pointer to Rx FIR filter structure or NULL*/
    1,              /* Rx FIR decimation (1,2,4)*/
    5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
    0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
    1,              /* RX Half band 1 decimation (1 or 2)*/
    307200,         /* Rx IQ data rate in kHz*/
    240000000,      /* The Rx RF passband bandwidth for the profile*/
    100000,         /* Rx BBF 3dB corner in kHz*/
    NULL            /* pointer to custom ADC profile*/
};


static mykonosRxProfile_t snifferProfile =
{ /* SRx 20MHz, IQrate 38.4MSPS, Dec5 */
    1,              /* The divider used to generate the ADC clock*/
    &snifferRxFir,  /* Pointer to Rx FIR filter structure or NULL*/
    4,              /* Rx FIR decimation (1,2,4)*/
    5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
    0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
    2,              /* RX Half band 1 decimation (1 or 2)*/
    38400,          /* Rx IQ data rate in kHz*/
    20000000,       /* The Rx RF passband bandwidth for the profile*/
    120000,         /* Rx BBF 3dB corner in kHz*/
    NULL            /* pointer to custom ADC profile*/
};



static mykonosTxProfile_t txProfile =
{ /* Tx 100/250MHz, IQrate 307.2MSPS, Dec5 */
    DACDIV_2p5,     /* The divider used to generate the DAC clock*/
    &txFir,         /* Pointer to Tx FIR filter structure*/
    1,              /* The Tx digital FIR filter interpolation (1,2,4)*/
    2,              /* Tx Halfband1 filter interpolation (1,2)*/
    1,              /* Tx Halfband2 filter interpolation (1,2)*/
    1,              /* TxInputHbInterpolation (1,2)*/
    307200,         /* Tx IQ data rate in kHz*/
    100000000,      /* Primary Signal BW*/
    250000000,      /* The Tx RF passband bandwidth for the profile*/
    236846,         /* The DAC filter 3dB corner in kHz*/
    125000,         /* Tx BBF 3dB corner in kHz*/
    0               /* Enable DPD, only valid for AD9373*/
};

static mykonosDigClocks_t mykonosClocks =
{
    122880,         /* CLKPLL and device reference clock frequency in kHz*/
   6144000,        /* CLKPLL VCO frequency in kHz*/
    VCODIV_1,       /* CLKPLL VCO divider*/
    4               /* CLKPLL high speed clock divider*/
};

static mykonosRxSettings_t  rxSettings =
{
    &rxProfile,     /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/
    &rxFramer,      /* Rx JESD204b framer configuration structure*/
    &rxGainControl, /* Rx Gain control settings structure*/
    &rxAgcConfig,   /* Rx AGC control settings structure*/
    1,              /* The desired Rx Channels to enable during initialization*/
    0,              /* Internal LO = 0, external LO*2 = 1*/
    900000000U,     /* Rx PLL LO Frequency (internal or external LO)*/
    0               /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/
};

static mykonosDpdConfig_t dpdConfig =
{
    5,              /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/
    1,              /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/
    2,              /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/
    1,              /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/
    20,             /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/
    0,              /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */
    512,            /* Number of samples to capture (default: 512, valid 64-32768)*/
    4096,           /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/
    0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
    255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
    {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/
};

static mykonosClgcConfig_t clgcConfig =
{
    -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/
    -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/
    0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/
    0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/
    75,             /* valid range 1-100, default 75*/
    75,             /* valid range 1-100, default 45*/
    0,              /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx1Atten automatically updated*/
    0,              /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx2Atten automatically updated*/
    0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
    255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
    600,            /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
    600,            /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
    0,              /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
    0               /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
};

static mykonosVswrConfig_t vswrConfig =
{
    0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
    255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
    0,              /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/
    1,              /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/
    0,              /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/
    0,              /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/
    50,             /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution*/
    50              /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution*/
};

static mykonosTxSettings_t txSettings =
{
    &txProfile,     /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/
    &deframer,      /* Mykonos JESD204b deframer config for the Tx data path*/
    TX1,            /* The desired Tx channels to enable during initialization*/
    0,              /* Internal LO=0, external LO*2 if =1*/
    900000000U,     /* Tx PLL LO frequency (internal or external LO)*/
    TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/
    10000,          /* Initial and current Tx1 Attenuation mdB*/
    10000,          /* Initial and current Tx2 Attenuation mdB*/
    NULL,           /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/
    NULL,           /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
    NULL            /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
};


static mykonosObsRxSettings_t obsRxSettings =
{
    &orxProfile,    /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/
    &orxGainControl,/* ObsRx gain control settings structure*/
    &obsRxAgcConfig,/* ORx AGC control settings structure*/
    &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/
    &snifferGainControl,/* SnRx gain control settings structure*/
    &obsRxFramer,   /* ObsRx JESD204b framer configuration structure */
    (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */
    OBSLO_TX_PLL,   /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */
    900000000U,     /* SnRx PLL LO frequency in Hz */
    0,              /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/
    NULL,           /* Custom Loopback ADC profile to set the bandwidth of the ADC response */
    OBS_RXOFF       /* Default ObsRx channel to enter when radioOn called */
};

static mykonosArmGpioConfig_t armGpio =
{
    0,	// useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */
    0,	// useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */
    0,	// txRxPinMode;     /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */
    0,	// orxPinMode;      /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/

    /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */
    0,	// orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */
    0,	// orxMode2Pin;   /*!< Select desired GPIO pin (valid 0-18) */
    0,	// orxMode1Pin;   /*!< Select desired GPIO pin (valid 0-18) */
    0,	// orxMode0Pin;   /*!< Select desired GPIO pin (valid 0-18) */

    /* Mykonos ARM output GPIO pins  --  always available, even when pin mode not enabled*/
    0,	// rx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// rx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// tx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// tx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// orx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// orx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0,	// srxEnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    0 	// txObsSelect;   /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
    /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is   */
    /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/
};

static mykonosGpio3v3_t gpio3v3 =
{
    0,				/*!< Oe per pin, 1=output, 0 = input */
    GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[3:0] */
    GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[7:4] */
    GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[11:8] */
};

static mykonosGpioLowVoltage_t gpio =
{
    0,/* Oe per pin, 1=output, 0 = input */
    GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */
    GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */
    GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */
    GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */
    GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */
};

static mykonosAuxIo_t mykonosAuxIo =
{
    0,	//auxDacEnableMask uint16_t
    {0,0,0,0,0,0,0,0,0,0},	 //AuxDacValue uint16[10]
    {0,0,0,0,0,0,0,0,0,0},	 //AuxDacSlope uint8[10]
    {0,0,0,0,0,0,0,0,0,0},	 //AuxDacVref uint8[10]
    &gpio3v3,	//pointer to gpio3v3 struct
    &gpio,	//pointer to gpio1v8 struct
    &armGpio
};

static spiSettings_t mykSpiSettings =
{
    2, /* chip select index - valid 1~8 */
    0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */
    1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */
    1, /* 1 = MSBFirst, 0 = LSBFirst */
    0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */
    0, /* clock polarity 0 = clock starts low, 1 = clock starts high */
    0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */
    1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */
    1  /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */
};

static mykonosTempSensorConfig_t tempSensor =
{
    7,              /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/
    67,             /* 8-bit offset that gets added to temp sensor code internally*/
    1,              /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/
    15,             /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/
};

static mykonosTempSensorStatus_t tempStatus =
{
    0,              /* 16-bit signed temperature value (in deg C) that is read back*/
    0,              /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/
    0,              /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/
    0,              /* when the reading is complete and a valid temperature value stored in tempCode.*/
};

mykonosDevice_t mykDevice =
{
    &mykSpiSettings,    /* SPI settings data structure pointer */
    &rxSettings,        /* Rx settings data structure pointer */
    &txSettings,        /* Tx settings data structure pointer */
    &obsRxSettings,     /* ObsRx settings data structure pointer */
    &mykonosAuxIo,          /* Auxiliary IO settings data structure pointer */
    &mykonosClocks,     /* Holds settings for CLKPLL and reference clock */
    0                   /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */
};

myk_ad9528init.c 

/* AD9528 data structure initialization file */

/**
* \page Disclaimer Legal Disclaimer
* Copyright 2015-2017 Analog Devices Inc.
* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
*
*/


#include <stdint.h>
#include "common.h"
#include "t_ad9528.h"

static spiSettings_t clockSpiSettings =
{
     1,         /* chip select Index */
     0,         /* Write bit polarity */
     1,         /* 16bit instruction word */
     1,         /* MSB first */
     0,         /* Clock phase */
     0,         /* Clock polarity */
     0,         /* uint8_t enSpiStreaming */
     1,         /* uint8_t autoIncAddrUp */
     1,         /* uint8_t fourWireMode */
     25000000   /* spiClkFreq_Hz */   
};

ad9528pll1Settings_t clockPll1Settings =
{
    30720000,
    1,
    3,
    0,
    1,
    0,
    122880000,
    2,
    4
};

ad9528pll2Settings_t clockPll2Settings =
{
    3,
    10,
    30
};

ad9528outputSettings_t clockOutputSettings =
{
    53237,
    {0,0,0,2,0,0,0,0,0,0,0,0,2,0},
    {0,0,0,2,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,2,0,0,0,0,0,0,0,0,0,0},
    {0,0,0,2,0,0,0,0,0,0,0,0,0,0},
    {10,10,10,10,10,10,10,10,10,10,10,10,10,10},
    {122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000}
};

ad9528sysrefSettings_t clockSysrefSettings =
{
   0,
   2,
   0,
   0,
   0,
   0,
   512
};

ad9528Device_t clockAD9528_ =
{
    &clockSpiSettings,
    &clockPll1Settings,
    &clockPll2Settings,
    &clockOutputSettings,
    &clockSysrefSettings
};

  • While I verify this profile in my setup and get back to you, can you please answer the following?

    • Is it the first time you are bringing up this ZCU102 + AD9371 setup? 
    • Is this a custom or default profile that you are using?
    • Can you please share the complete error log for reference?
    • Have you reviewed the API initialization sequence from UG-992 (page 15) and see if you are missing anything?
    • Can you try reading back the ARM version using getArmVersion()?
    • Can you confirm if the PLL are locked or not using checkPllsLockStatus() API?
    • Can you please let me know under which API as part of initialization are you getting this ARM mailbox busy error ?
  • Is it the first time you are bringing up this ZCU102 + AD9371 setup?
    This is my first time bringing up ZCU102 + AD9371. Previously, I successfully brought up ZC706 + AD9371.

    Is this a custom or default profile that you are using?
    I am using the default profile.

    Can you please share the complete error log for reference?
    Yes, below is the complete error log coming from Vitis:

    Please wait...
    rx_clkgen: MMCM-PLL locked (76800000 Hz)
    tx_clkgen: MMCM-PLL locked (153600000 Hz)
    rx_os_clkgen: MMCM-PLL locked (153600000 Hz)
    MCS successful
    CLKPLL locked
    ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()

    Have you reviewed the API initialization sequence from UG-992 (page 15) and see if you are missing anything?
    Yes, I reviewed UG-992 and my initialization sequence follows the recommended flow.

    Can you try reading back the ARM version using getArmVersion()?
    Yes, I am able to read the ARM version successfully and it shows AD9371 ARM version: 184.72.95. However, this appears to be an incorrect ARM version value

    Can you confirm if the PLLs are locked or not using checkPllsLockStatus() API?

    Yes, the PLLs are locked. I confirmed this using the checkPllsLockStatus() API.

    Under which API during initialization are you getting the ARM mailbox busy error?

    The issue occurs during MYKONOS_sendArmCommand(), specifically when calling MYKONOS_loadArmFromBinary()API.. Within this flow, the failure happens in MYKONOS_setArmGpioPins(), where MYKONOS_sendArmCommand() is invoked, and the error is reported from within the MYKONOS_setArmGpioPins() function.

    MYKONOS_loadArmFromBinary()
         → MYKONOS_setArmGpioPins()
                → MYKONOS_sendArmCommand()
                       ( ARM Mailbox Busy)

    “This is the headless.c file I am using."

    /***************************************************************************//**
     *   @file   ad9371/src/app/headless.c
     *   @brief  Implementation of Main Function.
    ********************************************************************************
     * Copyright 2017(c) Analog Devices, Inc.
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *  - Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *  - Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in
     *    the documentation and/or other materials provided with the
     *    distribution.
     *  - Neither the name of Analog Devices, Inc. nor the names of its
     *    contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *  - The use of this software may or may not infringe the patent rights
     *    of one or more patent holders.  This license does not release you
     *    from the requirement that you obtain separate licenses from these
     *    patent holders to use this software.
     *  - Use of the software either in source or binary form, must be run
     *    on or directly connected to an Analog Devices Inc. component.
     *
     * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *******************************************************************************/
    
    /******************************************************************************/
    /***************************** Include Files **********************************/
    /******************************************************************************/
    #include <stdlib.h>
    #include <stdio.h>
    #include "common.h"
    #include "ad9528.h"
    #include "mykonos.h"
    #include "Mykonos_M3.h"
    #include "mykonos_gpio.h"
    #include "parameters.h"
    #include "no_os_util.h"
    #include "no_os_error.h"
    #include "no_os_delay.h"
    #ifdef ALTERA_PLATFORM
    #include "clk_altera_a10_fpll.h"
    #include "altera_adxcvr.h"
    #else
    #include "xil_cache.h"
    #include "clk_axi_clkgen.h"
    #include "axi_adxcvr.h"
    #endif
    #include "axi_jesd204_rx.h"
    #include "axi_jesd204_tx.h"
    #include "axi_dac_core.h"
    #include "axi_adc_core.h"
    #include "dac_core.h"
    #include "axi_dmac.h"
    #include "app_config.h"
    
    #ifdef IIO_SUPPORT
    
    #include "iio_axi_adc.h"
    #include "iio_axi_dac.h"
    #include "iio_app.h"
    #include "xilinx_uart.h"
    
    #endif // IIO_SUPPORT
    
    
    /******************************************************************************/
    /************************ Variables Definitions *******************************/
    /******************************************************************************/
    extern ad9528Device_t clockAD9528_;
    extern mykonosDevice_t mykDevice;
    
    #ifdef Debug
    u32 CheckDacData(struct axi_dac *dac, u32 time_ms, u32 time_err_ms);
    u32 CheckAdcData(struct axi_adc *adc_core, u32 time_ms, u32 time_err_ms);
    #endif
    
    #if defined(DMA_EXAMPLE) || defined(IIO_SUPPORT)
    uint32_t dac_buffer[DAC_BUFFER_SAMPLES] __attribute__ ((aligned));
    uint16_t adc_buffer[ADC_BUFFER_SAMPLES * ADC_CHANNELS] __attribute__ ((
    			aligned));
    #endif
    
    #ifdef SDR_LOGICS
    u32* global_en = (u32*) XPAR_AXI_GPIO_EN_BASEADDR;
    u32* mod_type = (u32*) XPAR_AXI_GPIO_MOD_TYPE_BASEADDR;
    u32* global_rst = (u32*) XPAR_AXI_GPIO_RST_BASEADDR;
    #endif
    /***************************************************************************//**
     * @brief main
    *******************************************************************************/
    int main(void)
    {
    	ADI_ERR error;
    	ad9528Device_t *clockAD9528_device = &clockAD9528_;
    	mykonosErr_t mykError;
    	const char *errorString;
    	uint8_t pllLockStatus;
    	uint8_t mcsStatus;
    	uint8_t arm_major;
    	uint8_t arm_minor;
    	uint8_t arm_release;
    	mykonosGpioErr_t mykGpioErr;
    	uint32_t initCalMask = TX_BB_FILTER | ADC_TUNER | TIA_3DB_CORNER | DC_OFFSET |
    			       TX_ATTENUATION_DELAY | RX_GAIN_DELAY | FLASH_CAL |
    			       PATH_DELAY | TX_LO_LEAKAGE_INTERNAL | TX_QEC_INIT |
    			       LOOPBACK_RX_LO_DELAY | LOOPBACK_RX_RX_QEC_INIT |
    			       RX_LO_DELAY | RX_QEC_INIT ;
    	uint8_t errorFlag = 0;
    	uint8_t errorCode = 0;
    	uint32_t initCalsCompleted;
    	uint8_t framerStatus;
    	uint8_t obsFramerStatus;
    	uint8_t deframerStatus;
    	uint32_t trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC |
    				   TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC;
    	int32_t status;
    	int32_t ret;
    #ifdef BYPASS
    	CMB_setGPIO((uint32_t)DAC_GPIO_PLDDR_BYPASS);
    #endif
    #ifdef SDR_LOGICS
    		*mod_type = 0x00000000;
    		*global_en = 0x00000000;
    #endif
    #ifdef ALTERA_PLATFORM
    	struct altera_a10_fpll_init rx_device_clk_pll_init = {
    		"rx_device_clk_pll",
    		RX_A10_FPLL_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct altera_a10_fpll_init tx_device_clk_pll_init = {
    		"tx_device_clk_pll",
    		TX_A10_FPLL_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct altera_a10_fpll_init rx_os_device_clk_pll_init = {
    		"rx_os_device_clk_pll",
    		RX_OS_A10_FPLL_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct altera_a10_fpll *rx_device_clk_pll;
    	struct altera_a10_fpll *tx_device_clk_pll;
    	struct altera_a10_fpll *rx_os_device_clk_pll;
    #else
    	struct axi_clkgen_init rx_clkgen_init = {
    		"rx_clkgen",
    		RX_CLKGEN_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct axi_clkgen_init tx_clkgen_init = {
    		"tx_clkgen",
    		TX_CLKGEN_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct axi_clkgen_init rx_os_clkgen_init = {
    		"rx_os_clkgen",
    		RX_OS_CLKGEN_BASEADDR,
    		clockAD9528_device->outputSettings->outFrequency_Hz[1]
    	};
    	struct axi_clkgen *rx_clkgen;
    	struct axi_clkgen *tx_clkgen;
    	struct axi_clkgen *rx_os_clkgen;
    #endif
    	uint32_t rx_lane_rate_khz = mykDevice.rx->rxProfile->iqRate_kHz *
    				    mykDevice.rx->framer->M * (20 /
    						    no_os_hweight8(mykDevice.rx->framer->serializerLanesEnabled));
    	uint32_t rx_div40_rate_hz = rx_lane_rate_khz * (1000 / 40);
    	uint32_t tx_lane_rate_khz = mykDevice.tx->txProfile->iqRate_kHz *
    				    mykDevice.tx->deframer->M * (20 /
    						    no_os_hweight8(mykDevice.tx->deframer->deserializerLanesEnabled));
    	uint32_t tx_div40_rate_hz = tx_lane_rate_khz * (1000 / 40);
    	uint32_t rx_os_lane_rate_khz = mykDevice.obsRx->orxProfile->iqRate_kHz *
    				       mykDevice.obsRx->framer->M * (20 /
    						       no_os_hweight8(mykDevice.obsRx->framer->serializerLanesEnabled));
    	uint32_t rx_os_div40_rate_hz = rx_os_lane_rate_khz * (1000 / 40);
    	struct jesd204_rx_init rx_jesd_init = {
    		"rx_jesd",
    		RX_JESD_BASEADDR,
    		4,
    		32,
    		1,
    		rx_div40_rate_hz / 1000,
    		rx_lane_rate_khz
    	};
    	struct jesd204_tx_init tx_jesd_init = {
    		"tx_jesd",
    		TX_JESD_BASEADDR,
    		2,
    		32,
    		4,
    		14,
    		16,
    		false,
    		2,
    		1,
    		tx_div40_rate_hz / 1000,
    		tx_lane_rate_khz
    	};
    
    	struct jesd204_rx_init rx_os_jesd_init = {
    		"rx_os_jesd",
    		RX_OS_JESD_BASEADDR,
    		2,
    		32,
    		1,
    		rx_os_div40_rate_hz / 1000,
    		rx_os_lane_rate_khz
    	};
    	struct axi_jesd204_rx *rx_jesd;
    	struct axi_jesd204_tx *tx_jesd;
    	struct axi_jesd204_rx *rx_os_jesd;
    #ifdef ALTERA_PLATFORM
    	struct adxcvr_init rx_adxcvr_init = {
    		"rx_adxcvr",
    		RX_XCVR_BASEADDR,
    		{RX_ADXCFG_0_BASEADDR, RX_ADXCFG_1_BASEADDR, 0, 0},
    		0,
    		rx_lane_rate_khz,
    		mykDevice.clocks->deviceClock_kHz,
    	};
    	struct adxcvr_init tx_adxcvr_init = {
    		"tx_adxcvr",
    		TX_XCVR_BASEADDR,
    		{TX_ADXCFG_0_BASEADDR, TX_ADXCFG_1_BASEADDR, TX_ADXCFG_2_BASEADDR, TX_ADXCFG_3_BASEADDR},
    		TX_PLL_BASEADDR,
    		tx_lane_rate_khz,
    		mykDevice.clocks->deviceClock_kHz,
    	};
    	struct adxcvr_init rx_os_adxcvr_init = {
    		"rx_os_adxcvr",
    		RX_OS_XCVR_BASEADDR,
    		{RX_OS_ADXCFG_0_BASEADDR, RX_OS_ADXCFG_1_BASEADDR, 0, 0},
    		0,
    		rx_os_lane_rate_khz,
    		mykDevice.clocks->deviceClock_kHz,
    	};
    #else
    	struct adxcvr_init rx_adxcvr_init = {
    		.name = "rx_adxcvr",
    		.base = RX_XCVR_BASEADDR,
    		.sys_clk_sel = ADXCVR_SYS_CLK_CPLL,
    		.out_clk_sel = ADXCVR_REFCLK,
    		.lpm_enable = 1,
    		.lane_rate_khz = rx_lane_rate_khz,
    		.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
    	};
    	struct adxcvr_init tx_adxcvr_init = {
    		.name = "tx_adxcvr",
    		.base = TX_XCVR_BASEADDR,
    		.sys_clk_sel = ADXCVR_SYS_CLK_QPLL0,
    		.out_clk_sel = ADXCVR_REFCLK,
    		.lpm_enable = 0,
    		.lane_rate_khz = tx_lane_rate_khz,
    		.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
    	};
    	struct adxcvr_init rx_os_adxcvr_init = {
    		.name = "rx_os_adxcvr",
    		.base = RX_OS_XCVR_BASEADDR,
    		.sys_clk_sel = ADXCVR_SYS_CLK_CPLL,
    		.out_clk_sel = ADXCVR_REFCLK,
    		.lpm_enable = 1,
    		.lane_rate_khz = rx_os_lane_rate_khz,
    		.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
    	};
    #endif
    	struct adxcvr *rx_adxcvr;
    	struct adxcvr *tx_adxcvr;
    	struct adxcvr *rx_os_adxcvr;
    #ifdef 	M2_L2_Config
    	struct axi_dac_channel ad9371_tx_channels[1] = {
    		{
    			10*1000*1000,	// dds_frequency_tone0
    			0,			// dds_phase_tone0
    			50*1000,		// dds_scale_tone0	1.0*1000*1000
    			0,				// dds_frequency_tone1
    			0,				// dds_phase_tone1
    			0,				// dds_scale_tone1
    			0,				// dds_dual_tone
    			0,				// pat_data
    			AXI_DAC_DATA_SEL_DMA		// sel
    		},
    	};
    
    
    	struct axi_dac_init tx_dac_init = {
    		"tx_dac",
    		TX_CORE_BASEADDR,
    		1,
    		&ad9371_tx_channels, //NULL,
    		3
    	};
    #endif
    #ifdef 	default_config
    	struct axi_dac_channel ad9371_tx_channels[4] = {
    				{
    					10*1000*1000,	// dds_frequency_tone0
    					0,			// dds_phase_tone0
    					50*1000,		// dds_scale_tone0	1.0*1000*1000
    					0,				// dds_frequency_tone1
    					0,				// dds_phase_tone1
    					0,				// dds_scale_tone1
    					0,				// dds_dual_tone
    					0,				// pat_data
    					AXI_DAC_DATA_SEL_DMA		// sel
    				}, {
    					20*1000*1000,	// dds_frequency_tone0
    					0,			// dds_phase_tone0
    					50*1000,		// dds_scale_tone0	1.0*1000*1000
    					0,				// dds_frequency_tone1
    					0,				// dds_phase_tone1
    					0,				// dds_scale_tone1
    					0,				// dds_dual_tone
    					0,				// pat_data
    					AXI_DAC_DATA_SEL_DMA		// sel
    				}, {
    					30*1000*1000,	// dds_frequency_tone0
    					90000,			// dds_phase_tone0
    					50*1000,		// dds_scale_tone0	1.0*1000*1000
    					0,				// dds_frequency_tone1
    					0,				// dds_phase_tone1
    					0,				// dds_scale_tone1
    					1,				// dds_dual_tone
    					0,				// pat_data
    					AXI_DAC_DATA_SEL_DMA		// sel
    				}, {
    					40*1000*1000,	// dds_frequency_tone0
    					0,				// dds_phase_tone0
    					50*1000,		// dds_scale_tone0	1.0*1000*1000
    					0,				// dds_frequency_tone1
    					0,				// dds_phase_tone1
    					0,				// dds_scale_tone1
    					1,				// dds_dual_tone
    					0,				// pat_data
    					AXI_DAC_DATA_SEL_DMA		// sel
    				}
    		};
    	struct axi_dac_init tx_dac_init = {
    		"tx_dac",
    		TX_CORE_BASEADDR,
    		4,
    		ad9371_tx_channels,
    		3
    	};
    #endif
    	struct axi_dac *tx_dac;
    #ifdef 	default_config
    	struct axi_adc_init rx_adc_init = {
    		"rx_adc",
    		RX_CORE_BASEADDR,
    		2
    	};
    #endif
    #ifdef 	M2_L2_Config
    	struct axi_adc_init rx_adc_init = {
    	"rx_adc",
    	RX_CORE_BASEADDR,
    	2
    	};
    #endif
    	struct axi_adc *rx_adc;
    
    	struct axi_adc_init rx_obs_adc_init = {
    		"rx_obs_adc",
    		RX_OS_CORE_BASEADDR,
    		2
    	};
    
    	struct axi_adc *rx_obs_adc;
    
    	struct axi_dmac_init rx_dmac_init = {
    		"rx_dmac",
    		RX_DMA_BASEADDR,
    		IRQ_DISABLED
    	};
    	struct axi_dmac *rx_dmac;
    
    	struct axi_dmac_init rx_obs_dmac_init = {
    		"rx_obs_dmac",
    		RX_OBS_DMA_BASEADDR,
    		IRQ_DISABLED
    	};
    	struct axi_dmac *rx_obs_dmac;
    
    #ifdef DMA_EXAMPLE
    	struct axi_dmac_init tx_dmac_init = {
    		"tx_dmac",
    		TX_DMA_BASEADDR,
    		IRQ_DISABLED
    	};
    	struct axi_dmac *tx_dmac;
    	extern const uint32_t sine_lut_iq[1024];
    #endif
    	uint32_t i;
    
    	/* Allocating memory for the errorString */
    	errorString = NULL;
    
    	printf("Please wait...\n");
    
    #ifdef XILINX_PLATFORM
    	/* Enable the instruction cache. */
    	Xil_ICacheEnable();
    	/* Enable the instruction cache. */
    	Xil_DCacheEnable();
    #endif //XILINX_PLATFORM
    
    	ret = platform_init();
    	if (ret != 0) {
    		printf("error: platform_init() failed\n");
    		goto error_0;
    	}
    
    	/**************************************************************************/
    	/*****      System Clocks Initialization Initialization Sequence      *****/
    	/**************************************************************************/
    
    	/* Perform a hard reset on the AD9528 DUT */
    	error = AD9528_resetDevice(clockAD9528_device);
    	if (error != ADIERR_OK) {
    		printf("AD9528_resetDevice() failed\n");
    		error = ADIERR_FAILED;
    		goto error_1;
    	}
    
    	error = AD9528_initDeviceDataStruct(clockAD9528_device,
    					    clockAD9528_device->pll1Settings->vcxo_Frequency_Hz,
    					    clockAD9528_device->pll1Settings->refA_Frequency_Hz,
    					    clockAD9528_device->outputSettings->outFrequency_Hz[1]);
    	if (error != ADIERR_OK) {
    		printf("AD9528_initDeviceDataStruct() failed\n");
    		error = ADIERR_FAILED;
    		goto error_1;
    	}
    
    	/* Initialize the AD9528 by writing all SPI registers */
    	error = AD9528_initialize(clockAD9528_device);
    	if (error != ADIERR_OK)
    		printf("WARNING: AD9528_initialize() issues. Possible cause: REF_CLK not connected.\n");
    
    #ifdef ALTERA_PLATFORM
    	/* Initialize A10 FPLLs */
    	status = altera_a10_fpll_init(&rx_device_clk_pll,
    				      &rx_device_clk_pll_init);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_init() failed\n",
    		       rx_device_clk_pll_init.name);
    		goto error_1;
    	}
    	status = altera_a10_fpll_init(&tx_device_clk_pll,
    				      &tx_device_clk_pll_init);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_init() failed\n",
    		       tx_device_clk_pll_init.name);
    		goto error_2;
    	}
    	status = altera_a10_fpll_init(&rx_os_device_clk_pll,
    				      &rx_os_device_clk_pll_init);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_init() failed\n",
    		       rx_os_device_clk_pll_init.name);
    		goto error_3;
    	}
    
    	altera_a10_fpll_disable(rx_device_clk_pll);
    	status = altera_a10_fpll_set_rate(rx_device_clk_pll,
    					  rx_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_set_rate() failed\n",
    		       rx_device_clk_pll->name);
    		goto error_4;
    	}
    	altera_a10_fpll_enable(rx_device_clk_pll);
    	altera_a10_fpll_disable(tx_device_clk_pll);
    	status = altera_a10_fpll_set_rate(tx_device_clk_pll,
    					  tx_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_set_rate() failed\n",
    		       tx_device_clk_pll->name);
    		goto error_4;
    	}
    	altera_a10_fpll_enable(tx_device_clk_pll);
    	altera_a10_fpll_disable(rx_os_device_clk_pll);
    	status = altera_a10_fpll_set_rate(rx_os_device_clk_pll,
    					  rx_os_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: altera_a10_fpll_set_rate() failed\n",
    		       rx_os_device_clk_pll->name);
    		goto error_4;
    	}
    	altera_a10_fpll_enable(rx_os_device_clk_pll);
    #else
    	/* Initialize CLKGEN */
    	status = axi_clkgen_init(&rx_clkgen, &rx_clkgen_init);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_init() failed\n", rx_clkgen_init.name);
    		goto error_1;
    	}
    	status = axi_clkgen_init(&tx_clkgen, &tx_clkgen_init);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_init() failed\n", tx_clkgen_init.name);
    		goto error_2;
    	}
    	status = axi_clkgen_init(&rx_os_clkgen, &rx_os_clkgen_init);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_set_rate() failed\n", rx_os_clkgen_init.name);
    		goto error_3;
    	}
    
    	status = axi_clkgen_set_rate(rx_clkgen, rx_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_set_rate() failed\n", rx_clkgen->name);
    		goto error_4;
    	}
    	status = axi_clkgen_set_rate(tx_clkgen, tx_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_set_rate() failed\n", tx_clkgen->name);
    		goto error_4;
    	}
    	status = axi_clkgen_set_rate(rx_os_clkgen, rx_os_div40_rate_hz);
    	if (status != 0) {
    		printf("error: %s: axi_clkgen_set_rate() failed\n", rx_os_clkgen->name);
    		goto error_4;
    	}
    #endif
    
    	/* Initialize JESDs */
    	status = axi_jesd204_rx_init(&rx_jesd, &rx_jesd_init);
    	if (status != 0) {
    		printf("error: %s: axi_jesd204_rx_init() failed\n", rx_jesd_init.name);
    		goto error_4;
    	}
    	status = axi_jesd204_tx_init(&tx_jesd, &tx_jesd_init);
    	if (status != 0) {
    		printf("error: %s: axi_jesd204_tx_init() failed\n", tx_jesd_init.name);
    		goto error_5;
    	}
    	status = axi_jesd204_rx_init(&rx_os_jesd, &rx_os_jesd_init);
    	if (status != 0) {
    		printf("error: %s: axi_jesd204_rx_init() failed\n", rx_jesd_init.name);
    		goto error_6;
    	}
    
    	/* Initialize ADXCVRs */
    	status = adxcvr_init(&rx_adxcvr, &rx_adxcvr_init);
    	if (status != 0) {
    		printf("error: %s: adxcvr_init() failed\n", rx_adxcvr_init.name);
    		goto error_7;
    	}
    	status = adxcvr_init(&tx_adxcvr, &tx_adxcvr_init);
    	if (status != 0) {
    		printf("error: %s: adxcvr_init() failed\n", tx_adxcvr_init.name);
    		goto error_8;
    	}
    	status = adxcvr_init(&rx_os_adxcvr, &rx_os_adxcvr_init);
    	if (status != 0) {
    		printf("error: %s: adxcvr_init() failed\n", rx_os_adxcvr_init.name);
    		goto error_9;
    	}
    
    	/*************************************************************************/
    	/*****                Mykonos Initialization Sequence                *****/
    	/*************************************************************************/
    
    	/* Perform a hard reset on the MYKONOS DUT (Toggle RESETB pin on device) */
    	if ((mykError = MYKONOS_resetDevice(&mykDevice)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_initialize(&mykDevice)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****                Mykonos CLKPLL Status Check                    *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice,
    			&pllLockStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****                Mykonos Perform MultiChip Sync                 *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_enableMultichipSync(&mykDevice, 1,
    			&mcsStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/* Minimum 3 SYSREF pulses from Clock Device has to be produced for MulticChip Sync */
    
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    
    	/*************************************************************************/
    	/*****                Mykonos Verify MultiChip Sync                 *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_enableMultichipSync(&mykDevice, 0,
    			&mcsStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mcsStatus & 0x0B) == 0x0B)
    		printf("MCS successful\n");
    	else
    		printf("MCS failed\n");
    
    	/*************************************************************************/
    	/*****                Mykonos Load ARM file                          *****/
    	/*************************************************************************/
    
    	if (pllLockStatus & 0x01) {
    		printf("CLKPLL locked\n");
    		if ((mykError = MYKONOS_initArm(&mykDevice)) != MYKONOS_ERR_OK) {
    			errorString = getMykonosErrorMessage(mykError);
    			goto error_11;
    		}
    
    		if ((mykError = MYKONOS_loadArmFromBinary(&mykDevice,
    				&firmware_Mykonos_M3_bin[0], firmware_Mykonos_M3_bin_len)) != MYKONOS_ERR_OK) {
    			errorString = getMykonosErrorMessage(mykError);
    			goto error_11;
    		}
    	} else {
    		printf("CLKPLL not locked (0x%x)\n", pllLockStatus);
    		error = ADIERR_FAILED;
    		goto error_2;
    	}
    
    	/* Read back the version of the ARM binary loaded into the Mykonos ARM memory */
    	if ((mykError = MYKONOS_getArmVersion(&mykDevice, &arm_major, &arm_minor,
    					      &arm_release, NULL)) == MYKONOS_ERR_OK)
    		printf("AD9371 ARM version %d.%d.%d\n", arm_major, arm_minor, arm_release);
    
    	/*************************************************************************/
    	/*****                Mykonos Set RF PLL Frequencies                 *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, RX_PLL,
    			mykDevice.rx->rxPllLoFrequency_Hz)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, TX_PLL,
    			mykDevice.tx->txPllLoFrequency_Hz)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, SNIFFER_PLL,
    			mykDevice.obsRx->snifferPllLoFrequency_Hz)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/* Wait 200ms for PLLs to lock */
    	no_os_mdelay(200);
    
    	if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice,
    			&pllLockStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((pllLockStatus & 0x0F) == 0x0F)
    		printf("PLLs locked\n");
    	else {
    		printf("PLLs not locked (0x%x)\n", pllLockStatus);
    		error = ADIERR_FAILED;
    		goto error_2;
    	}
    
    	sleep(10);
    	/*************************************************************************/
    	/*****                Mykonos Set GPIOs                              *****/
    	/*************************************************************************/
    
    	if ((mykGpioErr = MYKONOS_setRx1GainCtrlPin(&mykDevice, 0, 0, 0, 0,
    			  0)) != MYKONOS_ERR_GPIO_OK) {
    		errorString = getGpioMykonosErrorMessage(mykGpioErr);
    		goto error_11;
    	}
    
    	if ((mykGpioErr = MYKONOS_setRx2GainCtrlPin(&mykDevice, 0, 0, 0, 0,
    			  0)) != MYKONOS_ERR_GPIO_OK) {
    		errorString = getGpioMykonosErrorMessage(mykGpioErr);
    		goto error_11;
    	}
    
    	if ((mykGpioErr = MYKONOS_setTx1AttenCtrlPin(&mykDevice, 0, 0, 0, 0,
    			  0)) != MYKONOS_ERR_GPIO_OK) {
    		errorString = getGpioMykonosErrorMessage(mykGpioErr);
    		goto error_11;
    	}
    
    	if ((mykGpioErr = MYKONOS_setTx2AttenCtrlPin(&mykDevice, 0, 0, 0,
    			  0)) != MYKONOS_ERR_GPIO_OK) {
    		errorString = getGpioMykonosErrorMessage(mykGpioErr);
    		goto error_11;
    	}
    
    	if ((mykGpioErr = MYKONOS_setupGpio(&mykDevice)) != MYKONOS_ERR_GPIO_OK) {
    		errorString = getGpioMykonosErrorMessage(mykGpioErr);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****                Mykonos Set manual gains values                *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_setRx1ManualGain(&mykDevice, 255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setRx2ManualGain(&mykDevice, 255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_RX1_TXLO,
    			255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_RX2_TXLO,
    			255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_A,
    			255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_B,
    			255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_C,
    			255)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****                Mykonos Initialize attenuations                *****/
    	/*************************************************************************/
    
    	mykError = MYKONOS_setTx1Attenuation(&mykDevice, 10000);
    	if (mykError != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	mykError = MYKONOS_setTx2Attenuation(&mykDevice, 10000);
    	if (mykError != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****           Mykonos ARM Initialization Calibrations             *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_runInitCals(&mykDevice,
    					    (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag,
    					     &errorCode)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((errorFlag != 0) || (errorCode != 0)) {
    		/*** < Info: abort init cals > ***/
    		if ((mykError = MYKONOS_abortInitCals(&mykDevice,
    						      &initCalsCompleted)) != MYKONOS_ERR_OK) {
    			errorString = getMykonosErrorMessage(mykError);
    			goto error_11;
    		}
    		if (initCalsCompleted)
    			printf("Completed calibrations: %x\n", (unsigned int)initCalsCompleted);
    	} else
    		printf("Calibrations completed successfully\n");
    
    	/*************************************************************************/
    	/*****  Mykonos ARM Initialization External LOL Calibrations with PA *****/
    	/*************************************************************************/
    
    	/* Please ensure PA is enabled operational at this time */
    	if (initCalMask & TX_LO_LEAKAGE_EXTERNAL) {
    		if ((mykError = MYKONOS_runInitCals(&mykDevice,
    						    TX_LO_LEAKAGE_EXTERNAL)) != MYKONOS_ERR_OK) {
    			errorString = getMykonosErrorMessage(mykError);
    			goto error_11;
    		}
    
    		if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag,
    						     &errorCode)) != MYKONOS_ERR_OK) {
    			errorString = getMykonosErrorMessage(mykError);
    			goto error_11;
    		}
    
    		if ((errorFlag != 0) || (errorCode != 0)) {
    			/*** < Info: abort init cals > ***/
    			if ((mykError = MYKONOS_abortInitCals(&mykDevice,
    							      &initCalsCompleted)) != MYKONOS_ERR_OK) {
    				errorString = getMykonosErrorMessage(mykError);
    				goto error_11;
    			}
    		} else
    			printf("External LOL Calibrations completed successfully\n");
    	}
    
    	/*************************************************************************/
    	/*****             SYSTEM JESD bring up procedure                    *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_enableSysrefToRxFramer(&mykDevice,
    			1)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    	/*** < Info: Mykonos is waiting for sysref in order to start
    	 * transmitting CGS from the RxFramer> ***/
    
    	if ((mykError = MYKONOS_enableSysrefToObsRxFramer(&mykDevice,
    			1)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    	/*** < Info: Mykonos is waiting for sysref in order to start
    	 * transmitting CGS from the ObsRxFramer> ***/
    
    	if ((mykError = MYKONOS_enableSysrefToDeframer(&mykDevice,
    			0)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	if ((mykError = MYKONOS_resetDeframer(&mykDevice)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    #ifndef ALTERA_PLATFORM
    	status = adxcvr_clk_enable(tx_adxcvr);
    	if (status != 0) {
    		printf("error: %s: adxcvr_clk_enable() failed\n", tx_adxcvr->name);
    		goto error_10;
    	}
    #endif
    	axi_jesd204_tx_lane_clk_enable(tx_jesd);
    
    	if ((mykError = MYKONOS_enableSysrefToDeframer(&mykDevice,
    			1)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*************************************************************************/
    	/*****            Enable SYSREF to Mykonos and BBIC                  *****/
    	/*************************************************************************/
    
    	/* Request a SYSREF from the AD9528 */
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    
    	/*** < Info: Mykonos is actively transmitting CGS from the RxFramer> ***/
    
    	/*** < Info: Mykonos is actively transmitting CGS from the ObsRxFramer> ***/
    
    #ifndef ALTERA_PLATFORM
    	status = adxcvr_clk_enable(rx_adxcvr);
    	if (status != 0) {
    		printf("error: %s: adxcvr_clk_enable() failed\n", rx_adxcvr->name);
    		goto error_10;
    	}
    #endif
    	axi_jesd204_rx_lane_clk_enable(rx_jesd);
    #ifndef ALTERA_PLATFORM
    	status = adxcvr_clk_enable(rx_os_adxcvr);
    	if (status != 0) {
    		printf("error: %s: adxcvr_clk_enable() failed\n", rx_os_adxcvr->name);
    		goto error_10;
    	}
    #endif
    	axi_jesd204_rx_lane_clk_enable(rx_os_jesd);
    
    	/* Request two SYSREFs from the AD9528 */
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(1);
    	AD9528_requestSysref(clockAD9528_device, 1);
    	no_os_mdelay(5);
    
    	/*************************************************************************/
    	/*****               Check Mykonos Framer Status                     *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_readRxFramerStatus(&mykDevice,
    			&framerStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	} else if (framerStatus != 0x3E)
    		printf("RxFramerStatus = 0x%x\n", framerStatus);
    
    	if ((mykError = MYKONOS_readOrxFramerStatus(&mykDevice,
    			&obsFramerStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	} else if (obsFramerStatus != 0x3E)
    		printf("OrxFramerStatus = 0x%x\n", obsFramerStatus);
    
    	/*************************************************************************/
    	/*****               Check Mykonos Deframer Status                   *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_readDeframerStatus(&mykDevice,
    			&deframerStatus)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	} else if (deframerStatus != 0x28)
    		printf("DeframerStatus = 0x%x\n", deframerStatus);
    
    	/*************************************************************************/
    	/*****           Mykonos enable tracking calibrations                *****/
    	/*************************************************************************/
    
    	if ((mykError = MYKONOS_enableTrackingCals(&mykDevice,
    			trackingCalMask)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*** < Info: Allow Rx1/2 QEC tracking and Tx1/2 QEC tracking to run when in the radioOn state
    	     *  Tx calibrations will only run if radioOn and the obsRx path is set to OBS_INTERNAL_CALS > ***/
    
    	/*** < Info: Function to turn radio on, Enables transmitters and receivers
    	 * that were setup during MYKONOS_initialize() > ***/
    	if ((mykError = MYKONOS_radioOn(&mykDevice)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	/*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice,
    			OBS_RXOFF)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice,
    			OBS_INTERNALCALS)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	axi_jesd204_rx_watchdog(rx_jesd);
    	axi_jesd204_rx_watchdog(rx_os_jesd);
    
    	no_os_mdelay(1000);
    
    	/* Print JESD status */
    	axi_jesd204_rx_status_read(rx_jesd);
    	for (i = 0; i < rx_jesd->num_lanes; i++)
    		axi_jesd204_rx_laneinfo_read(rx_jesd, i);
    	axi_jesd204_tx_status_read(tx_jesd);
    	axi_jesd204_rx_status_read(rx_os_jesd);
    	for (i = 0; i < rx_os_jesd->num_lanes; i++)
    		axi_jesd204_rx_laneinfo_read(rx_os_jesd, i);
    
    	/* Initialize the DAC DDS */
    	axi_dac_init(&tx_dac, &tx_dac_init);
    
    	/* Initialize the ADC core */
    	axi_adc_init(&rx_adc, &rx_adc_init);
    
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice,
    			OBS_RX1_SNIFFERLO)) != MYKONOS_ERR_OK) {
    		errorString = getMykonosErrorMessage(mykError);
    		goto error_11;
    	}
    
    	axi_adc_init(&rx_obs_adc, &rx_obs_adc_init);
    #ifdef SDR_LOGICS
    		*global_en = 0xFFFFFFFF;
    		*global_rst = 0xFFFFFFFF;
    
    		sleep(3);
    
    		*global_rst = 0x00000000;
    #endif
    #ifdef DMA_EXAMPLE
    	axi_dac_load_custom_data(tx_dac, sine_lut_iq,
    				 NO_OS_ARRAY_SIZE(sine_lut_iq),
    				 (uintptr_t)dac_buffer);
    #ifndef ALTERA_PLATFORM
    	Xil_DCacheFlush();
    #endif
    	axi_dmac_init(&tx_dmac, &tx_dmac_init);
    	struct axi_dma_transfer transfer = {
    		// Number of bytes to write/read
    		.size = sizeof(sine_lut_iq),
    		// Transfer done flag
    		.transfer_done = 0,
    		// Signal transfer mode
    		.cyclic = NO,
    		// Address of data source
    		.src_addr = (uintptr_t)dac_buffer,
    		// Address of data destination
    		.dest_addr = 0
    	};
    	axi_dmac_transfer_start(tx_dmac, &transfer);
    	/* Flush cache data. */
    	Xil_DCacheInvalidateRange((uintptr_t)dac_buffer, sizeof(sine_lut_iq));
    
    	no_os_mdelay(1000);
    
    	/* Initialize the DMAC and transfer 16384 samples from ADC to MEM */
    	axi_dmac_init(&rx_dmac, &rx_dmac_init);
    	axi_dmac_init(&rx_obs_dmac, &rx_obs_dmac_init);
    
    	struct axi_dma_transfer read_transfer = {
    		// Number of bytes to write/read
    		.size = sizeof(adc_buffer),
    		// Transfer done flag
    		.transfer_done = 0,
    		// Signal transfer mode
    		.cyclic = NO,
    		// Address of data source
    		.src_addr = 0,
    		// Address of data destination
    		.dest_addr = (uintptr_t)adc_buffer
    	};
    	axi_dmac_transfer_start(rx_dmac, &read_transfer);
    	/* Wait until transfer finishes */
    	status = axi_dmac_transfer_wait_completion(rx_dmac, 500);
    	if(status)
    		return status;
    #ifndef ALTERA_PLATFORM
    	Xil_DCacheInvalidateRange((uintptr_t)adc_buffer, sizeof(adc_buffer));
    #endif
    
    //	printf("DMA_EXAMPLE: address=%#lx samples=%lu channels=%u bits=%lu\n",
    //	       (uintptr_t)adc_buffer, NO_OS_ARRAY_SIZE(adc_buffer), rx_adc_init.num_channels,
    //	       8 * sizeof(adc_buffer[0]));
    	printf("DMA_EXAMPLE: address=%#x samples=%u channels=%u bits=%u\n",
    	       (unsigned int)(uintptr_t)adc_buffer,
    	       (unsigned int)NO_OS_ARRAY_SIZE(adc_buffer),
    	       (unsigned int)rx_adc_init.num_channels,
    	       (unsigned int)(8 * sizeof(adc_buffer[0])));
    
    #endif
    
    #ifdef IIO_SUPPORT
    
    	/**
    	 * Transmit DMA initial configuration.
    	 */
    	struct axi_dmac_init tx_dmac_init = {
    		"tx_dmac",
    		TX_DMA_BASEADDR,
    		IRQ_DISABLED
    	};
    
    	/**
    	 * Pointer to transmit DMA instance.
    	 */
    	struct axi_dmac *tx_dmac;
    
    	/**
    	 * iio application configurations.
    	 */
    	struct iio_init_param iio_init_par;
    
    	/**
    	 * UART init params
    	 */
    	struct xil_uart_init_param platform_uart_init_par = {
    #ifdef XPAR_XUARTLITE_NUM_INSTANCES
    		.type = UART_PL,
    #else
    		.type = UART_PS,
    		.irq_id = UART_IRQ_ID
    #endif
    	};
    
    	struct no_os_uart_init_param iio_uart_ip = {
    		.device_id = UART_DEVICE_ID,
    		.irq_id = UART_IRQ_ID,
    		.baud_rate = UART_BAUDRATE,
    		.size = NO_OS_UART_CS_8,
    		.parity = NO_OS_UART_PAR_NO,
    		.stop = NO_OS_UART_STOP_1_BIT,
    		.extra = &platform_uart_init_par,
    		.platform_ops = &xil_uart_ops
    	};
    
    	/**
    	 * IIO application descriptor
    	 */
    	struct iio_app_desc *app;
    
    	/**
    	 * IIO application initialization parameters
    	 */
    	struct iio_app_init_param app_init_param = { 0 };
    
    	/**
    	 * iio axi adc configurations.
    	 */
    	struct iio_axi_adc_init_param iio_axi_adc_init_par;
    
    	/**
    	 * iio axi adc configurations, for observation chain
    	 */
    	struct iio_axi_adc_init_param iio_axi_adc_obs_init_par;
    
    	/**
    	 * iio axi dac configurations.
    	 */
    	struct iio_axi_dac_init_param iio_axi_dac_init_par;
    
    	/**
    	 * iio application instance descriptor.
    	 */
    	struct iio_desc *iio_app_desc;
    
    	/**
    	 * iio instance descriptor.
    	 */
    	struct iio_axi_adc_desc *iio_axi_adc_desc;
    
    	/**
    	 * iio instance descriptor, for observation chain
    	 */
    	struct iio_axi_adc_desc *iio_axi_adc_obs_desc;
    
    	/**
    	 * iio instance descriptor.
    	 */
    	struct iio_axi_dac_desc *iio_axi_dac_desc;
    
    	/**
    	 * iio device instance descriptor.
    	 */
    	struct iio_device *adc_dev_desc, *dac_dev_desc;
    
    	status = axi_dmac_init(&tx_dmac, &tx_dmac_init);
    	if(status < 0)
    		return status;
    
    	iio_axi_adc_init_par = (struct iio_axi_adc_init_param) {
    		.rx_adc = rx_adc,
    		.rx_dmac = rx_dmac,
    #ifndef PLATFORM_MB
    		.dcache_invalidate_range = (void (*)(uint32_t,
    						     uint32_t))Xil_DCacheInvalidateRange,
    #endif
    	};
    
    	status = iio_axi_adc_init(&iio_axi_adc_desc, &iio_axi_adc_init_par);
    	if(status < 0)
    		return status;
    
    	iio_axi_adc_obs_init_par = (struct iio_axi_adc_init_param) {
    		.rx_adc = rx_obs_adc,
    		.rx_dmac = rx_obs_dmac,
    #ifndef PLATFORM_MB
    		.dcache_invalidate_range = (void (*)(uint32_t,
    						     uint32_t))Xil_DCacheInvalidateRange,
    #endif
    	};
    
    	status = iio_axi_adc_init(&iio_axi_adc_obs_desc,
    				  &iio_axi_adc_obs_init_par);
    	if(status < 0)
    		return status;
    
    	struct iio_data_buffer read_buff = {
    		.buff = (void *)adc_buffer,
    		.size = sizeof(adc_buffer),
    	};
    	iio_axi_adc_get_dev_descriptor(iio_axi_adc_desc, &adc_dev_desc);
    	if (status < 0)
    		return status;
    
    	iio_axi_dac_init_par = (struct iio_axi_dac_init_param) {
    		.tx_dac = tx_dac,
    		.tx_dmac = tx_dmac,
    #ifndef PLATFORM_MB
    		.dcache_flush_range = (void (*)(uint32_t, uint32_t))Xil_DCacheFlushRange,
    #endif
    	};
    
    	status = iio_axi_dac_init(&iio_axi_dac_desc, &iio_axi_dac_init_par);
    	if(status < 0)
    		return status;
    	struct iio_data_buffer write_buff = {
    		.buff = (void *)dac_buffer,
    		.size = sizeof(dac_buffer),
    	};
    	iio_axi_dac_get_dev_descriptor(iio_axi_dac_desc, &dac_dev_desc);
    	struct iio_app_device devices[] = {
    		IIO_APP_DEVICE("cf-ad9371-lpc", iio_axi_adc_desc, adc_dev_desc, &read_buff, NULL, NULL),
    		IIO_APP_DEVICE("cf-ad9371-dds-core-lpc", iio_axi_dac_desc, dac_dev_desc, NULL, &write_buff, NULL)
    	};
    
    	app_init_param.devices = devices;
    	app_init_param.nb_devices = NO_OS_ARRAY_SIZE(devices);
    	app_init_param.uart_init_params = iio_uart_ip;
    
    	status = iio_app_init(&app, app_init_param);
    	if (status)
    		return status;
    
    	return iio_app_run(app);
    
    #endif // IIO_SUPPORT
    
    	printf("Done\n");
    #ifdef Debug
    
    	CheckDacData(tx_dac, 100, 100);
    
    	CheckAdcData(rx_adc, 100, 100);
    
    #endif
    
    #ifdef XILINX_PLATFORM
    	/* Disable the instruction cache. */
    	Xil_ICacheDisable();
    	/* Disable the data cache. */
    	Xil_DCacheDisable();
    #endif //XILINX_PLATFORM
    
    	return 0;
    
    error_11:
    	printf("%s", errorString);
    #ifndef ALTERA_PLATFORM
    error_10:
    #endif
    	adxcvr_remove(rx_os_adxcvr);
    error_9:
    	adxcvr_remove(tx_adxcvr);
    error_8:
    	adxcvr_remove(rx_adxcvr);
    error_7:
    	axi_jesd204_rx_remove(rx_os_jesd);
    error_6:
    	axi_jesd204_tx_remove(tx_jesd);
    error_5:
    	axi_jesd204_rx_remove(rx_jesd);
    error_4:
    #ifdef ALTERA_PLATFORM
    	altera_a10_fpll_remove(rx_os_device_clk_pll);
    #else
    	axi_clkgen_remove(rx_os_clkgen);
    #endif
    error_3:
    #ifdef ALTERA_PLATFORM
    	altera_a10_fpll_remove(tx_device_clk_pll);
    #else
    	axi_clkgen_remove(tx_clkgen);
    #endif
    error_2:
    #ifdef ALTERA_PLATFORM
    	altera_a10_fpll_remove(rx_device_clk_pll);
    #else
    	axi_clkgen_remove(rx_clkgen);
    #endif
    error_1:
    	platform_remove();
    error_0:
    
    #ifdef XILINX_PLATFORM
    	/* Disable the instruction cache. */
    	Xil_ICacheDisable();
    	/* Disable the data cache. */
    	Xil_DCacheDisable();
    #endif //XILINX_PLATFORM
    
    	return -1;
    }
    #ifdef Debug
    
    u32 CheckDacData(struct axi_dac *dac, u32 time_ms, u32 time_err_ms)
    {
    	printf("CheckDacData \r\n");
    	volatile u8 i=0;
    
    	for (i = 0; i < dac->num_channels ; i++)
    	{
    		axi_dac_set_datasel(dac, i, AXI_DAC_DATA_SEL_PN7);
    	}
    
    	MYKONOS_enableDeframerPrbsChecker(&mykDevice, 0xf, MYK_PRBS7, 1);
    
    
    	MYKONOS_clearDeframerPrbsCounters(&mykDevice);
    
    	no_os_mdelay(time_ms);
    	uint32_t prbsErrorCount;
    
    
    	for (i = 0; i < 4; i++)
    	{
    		xil_printf("i = %d\r\n",i);
    
    		MYKONOS_readDeframerPrbsCounters(&mykDevice, (1<<i), &prbsErrorCount);
    
    		printf("prbsErrorCount : %d\n", prbsErrorCount);
    
    	}
    	return 0;
    }
    u32 CheckAdcData(struct axi_adc *adc_core, u32 time_ms, u32 time_err_ms)
    {
    	xil_printf("CheckAdcData \r\n");
    	MYKONOS_enableRxFramerPrbs(&mykDevice, MYK_PRBS7, 1);
    	int status;
    
    
    	uint32_t del_ms = time_ms;
    
    
    	status = axi_adc_pn_mon(adc_core, AXI_ADC_PN7, del_ms);
    	if(status != 0)
    	{
    		xil_printf("FAIL find errors! status: %d \r\n", status);
    
    	}
    	xil_printf("axi_adc_pn_mon = status: %d \r\n", status);
    
    
    	MYKONOS_rxInjectPrbsError(&mykDevice);
    	xil_printf("injectFramerTestDataError \r\n");
    
    
    	del_ms = time_err_ms;
    	status = axi_adc_pn_mon(adc_core, AXI_ADC_PN7, del_ms);
    	if(status != 1)
    	{
    		xil_printf("FAIL NO errors! status: %d \r\n", status);
    	}
    	xil_printf("axi_adc_pn_mon = status: %d \r\n", status);
    
    
    	MYKONOS_enableRxFramerPrbs(&mykDevice, MYK_PRBS7, 0);
    	return 0;
    }
    #endif

  • Is this a custom or eval board?

    Can you please share full log in .txt format instead of copy pasting the error log  ?

    Is the firmware binary file loaded properly ,does the MYKONOS_loadArmFromBinary() API execute without any issues?

    We would get into these ARM issues due to SPI or power supply .

    • Can you please write and readback from the scratch pad register (0xA) and ensure that the SPI interface is working fine or not?
    • During initialization , can you monitor the power supply rails and see if there is any voltage drop and check if all of them are within the tolerances as expected?
  • Q: Is this a custom or eval board?
    A: It is an evaluation setup but ZCU102-based. Both boards use Ultrascale+ FPGA architecture. I created the HDL and block design from scratch by taking ZCU102 as a reference. The SOM used is TE0808-9BE81-A-05, and the carrier board is TEBF0808-05.

    Q: Can you please share the full log in .txt format instead of copy-pasting the error log?
    A: Yes, I have attached the full log file in .txt format.

    Please wait...
    rx_clkgen: MMCM-PLL locked (76800000 Hz)
    tx_clkgen: MMCM-PLL locked (153600000 Hz)
    rx_os_clkgen: MMCM-PLL locked (153600000 Hz)
    MCS successful
    CLKPLL locked
    ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()

    Q: Is the firmware binary file loaded properly? Does the MYKONOS_loadArmFromBinary() API execute without issues?
    A: The error occurs within the MYKONOS_loadArmFromBinary() API, specifically near MYKONOS_setArmGpioPins(), where the ARM command is triggered. The flow is:

    MYKONOS_loadArmFromBinary()
    MYKONOS_setArmGpioPins()
    MYKONOS_sendArmCommand()
    (ARM Mailbox Busy)

    Q: ARM issues can occur due to SPI or power supply. Can you write/read the scratch pad register (0x0A) to verify SPI?
    A: Yes, I verified this already. Writing to and reading back from the scratch pad register (0x0A) works correctly, confirming that the SPI interface is functioning properly.

    Q.During initialization, can you monitor the power supply rails and check if there is any voltage drop and whether all rails are within tolerance?
    A: Yes, I have monitored the power supply rails during initialization. All voltages are within the expected tolerance range, and no voltage drop was observed.

  • We would get the ARM mailbox busy issues due to SPI ,clock  and Power supply.

    Can you disable the SPI streaming mode and then verify the SPI timings are met as per mentioned in the UG -992 (Page 20)

      

  • In the SPI clock time period, the SPI Bus Timing Constraint Values mentioned in UG-992 specify 20 ns, which corresponds to 50 MHz. However, in the Mykonos no-OS drivers the SPI clock is set to 2 MHz

    (    spi_param.mode = NO_OS_SPI_MODE_0;
        spi_param.chip_select = AD9371_CS;
        spi_param.max_speed_hz = 2000000u;

    When I try to match the parameters according to UG-992 SPI Bus Timing Constraint Values, I am not able to get the correct CLK, MISO, MOSI, and CS signals.

    With the default SPI settings in the Mykonos configuration, I am getting proper CLK, CS, MOSI, and MISO signals, and the SPI communication is working fine. I have attached the default settings below.

    static spiSettings_t mykSpiSettings =
    {
        2, /* chip select index - valid 1~8 */
        0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */
        1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */
        1, /* 1 = MSBFirst, 0 = LSBFirst */
        0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */
        0, /* clock polarity 0 = clock starts low, 1 = clock starts high */
        0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */
        1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */
        1  /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */
    };
    
    typedef struct {
        uint8_t chipSelectIndex;        ///< valid 1~8
        uint8_t writeBitPolarity;        ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation
        uint8_t longInstructionWord;    ///< 1 = 16bit instruction word, 0 = 8bit instruction word
        uint8_t MSBFirst;                ///< 1 = MSBFirst, 0 = LSBFirst
        uint8_t CPHA;                    ///< clock phase, sets which clock edge the data updates (valid 0 or 1)
        uint8_t CPOL;                    ///< clock polarity 0 = clock starts low, 1 = clock starts high
        uint8_t enSpiStreaming;            ///< Not implemented. SW feature to improve SPI throughput.
        uint8_t autoIncAddrUp;            ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1
        uint8_t fourWireMode;            ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode.
        uint32_t spiClkFreq_Hz;            ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */
    } spiSettings_t
    
    
    From common.c file :
    	spi_param.mode = NO_OS_SPI_MODE_0;
    	spi_param.chip_select = AD9371_CS;
    	spi_param.max_speed_hz = 2000000u;

  • We would get the ARM mailbox busy issues due to SPI ,clock  and Power supply, 

    Have you verified the SPI timings are met or not as per mentioned in the UG -992 (Page 20)?


  • I  have verified the SPI timings as per UG-992 (Page 20), and the SPI communication signals  are clean and within the required limits. The reference clocks and power supplies are also stable and within specification.

    Can you please explain what might be causing the ARM mailbox busy issue in my case?

    Thank you.

  • The "ARM Mailbox Busy" error is strange and this indicates its an  ARM firmware internal error which can be caused by some erroneous or incomplete profile. Please double check all the settings in the device tree. 

     ARM Mailbox Busy error 

    https://wiki.analog.com/resources/eval/user-guides/rf-trx-vcxo-and-profiles#arm_mailbox_busy_command_not_executed_in_mykonos_sendarmcommand

    Sorry, I couldn’t think of any other possible causes for the ARM mailbox busy issue besides the SPI, clock, and power‑supply problems reported by customers.

  • The ARM Mailbox Busy issue earlier was due to an SPI communication problem. I have now resolved the SPI issue, and SPI read/write operations are working correctly. I verified this using the scratchpad register(0x0A)with the AD9371, and the read/write transactions are successful.

    However, I am now encountering a different issue during the MYKONOS_initialize() function. The initialization fails with the following error:

    Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()

    Regarding the clock configuration, the AD9528 appears to be locking correctly. When I read register 0x508, it returns 0xE7, which indicates the PLL is locked.

    I also checked the reference clock and device clock using an oscilloscope, and both clocks appear to be present and correct.

    Could you please help identify what might be causing the Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent() during the Mykonos initialization?

    I have attached the error log and the Mykonos profile files for reference.

    Could you please help identify the possible cause of this issue

    Thanks 

    Reg508 = 0xE7
    rx_clkgen: MMCM-PLL locked (76800000 Hz)
    tx_clkgen: MMCM-PLL locked (153600000 Hz)
    rx_os_clkgen: MMCM-PLL locked (153600000 Hz)
    Reg 0x000 from AD9371  = 0x3C
    Reg 0x001 from AD9371 = 0x80
    Reg 0x0A from AD9371  = 0x55
    Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()

    /**
     * \brief Contains init setting structure declarations for the _instance API
     *
     * The top level structure mykonosDevice_t mykDevice uses keyword
     * extern to allow the application layer main() to have visibility
     * to these settings.
     * 
     * All data structures required for operation have been initialized with values which reflect these settings:
     * 
     * Device Clock:
     * 122.88MHz
     * 
     * Profiles:
     * Rx 100MHz, IQrate 153.6MSPS, Dec5
     * Tx 100/250MHz, IQrate 307.2MSPS, Dec5
     * ORX 240MHz, IQrate 307.2MSPS, Dec5
     * SRx 20MHz, IQrate 38.4MSPS, Dec5
     * 
     */
    
    /**
      \page Disclaimer Legal Disclaimer
      Copyright 2015-2017 Analog Devices Inc.
      Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
     */
    
    #include <stddef.h>
    #include "t_mykonos.h"
    #include "t_mykonos_gpio.h"
    #include "myk.h"
    
    
    static int16_t txFirCoefs[] = {-116,-120,238,235,-422,-489,718,882,-1137,-1583,1719,2900,-2300,-5246,3919,17095,17095,3919,-5246,-2300,2900,1719,-1583,-1137,882,718,-489,-422,235,238,-120,-116};
    
    static mykonosFir_t txFir =
    {
        0,              /* Filter gain in dB*/
        32,             /* Number of coefficients in the FIR filter*/
        &txFirCoefs[0]  /* A pointer to an array of filter coefficients*/
    };
    
    static int16_t rxFirCoefs[] = {0,-1,2,3,-5,-7,11,15,-23,-29,43,54,-75,-92,125,150,-198,-235,302,355,-447,-524,646,759,-920,-1089,1302,1568,-1864,-2324,2763,3696,-4513,-7179,9583,31418,31418,9583,-7179,-4513,3696,2763,-2324,-1864,1568,1302,-1089,-920,759,646,-524,-447,355,302,-235,-198,150,125,-92,-75,54,43,-29,-23,15,11,-7,-5,3,2,-1,0};
    
    static mykonosFir_t rxFir =
    {
        -6,             /* Filter gain in dB*/
        72,             /* Number of coefficients in the FIR filter*/
        &rxFirCoefs[0]  /* A pointer to an array of filter coefficients*/
    };
    
    static int16_t obsrxFirCoefs[] = {0,-1,1,2,-2,-6,6,12,-13,-24,25,43,-45,-73,77,118,-124,-183,193,274,-289,-402,423,579,-607,-826,866,1187,-1244,-1759,1842,2818,-2970,-5815,4337,18436,18436,4337,-5815,-2970,2818,1842,-1759,-1244,1187,866,-826,-607,579,423,-402,-289,274,193,-183,-124,118,77,-73,-45,43,25,-24,-13,12,6,-6,-2,2,1,-1,0};
    static mykonosFir_t obsrxFir =
    {
        0,              /* Filter gain in dB*/
        72,             /* Number of coefficients in the FIR filter*/
        &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/
    };
    
    static int16_t snifferFirCoefs[] = {-24,107,36,42,-60,-108,-142,-48,90,239,252,109,-173,-412,-452,-186,277,690,747,323,-438,-1108,-1224,-551,677,1806,2058,1002,-1095,-3214,-3985,-2319,1957,7863,13548,17027,17027,13548,7863,1957,-2319,-3985,-3214,-1095,1002,2058,1806,677,-551,-1224,-1108,-438,323,747,690,277,-186,-452,-412,-173,109,252,239,90,-48,-142,-108,-60,42,36,107,-24};
    static mykonosFir_t snifferRxFir=
    {
        -6,             /* Filter gain in dB*/
        72,             /* Number of coefficients in the FIR filter*/
        &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/
    };
    
    static mykonosJesd204bFramerConfig_t rxFramer =
    {
        0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
        0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
        0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
        4,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
        32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
        1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
        0x03,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
        0x08,           /* serializerLaneCrossbar*/
        22,             /* serializerAmplitude - default 22 (valid (0-31)*/
        4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
        0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
        0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
        0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        0,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
        0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
    };
    
    static mykonosJesd204bFramerConfig_t obsRxFramer =
    {
        0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
        0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
        0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
        2,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
        32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
        1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
        0x0C,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
        0x40,           /* Lane crossbar to map framer lane outputs to physical lanes*/
        22,             /* serializerAmplitude - default 22 (valid (0-31)*/
        4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
        0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
        0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        1,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
        0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        0,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
        0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
    };
    
    static mykonosJesd204bDeframerConfig_t deframer =
    {
        0,              /* bankId extension to Device ID (Valid 0..15)*/
        0,              /* deviceId  link identification number. (Valid 0..255)*/
        0,              /* lane0Id Lane0 ID. (Valid 0..31)*/
        2,              /* M  number of DACss (0, 2, or 4) - 2 DACs per transmit chain */
        32,             /* K  #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scramble  scrambling off if scramble= 0.*/
        1,              /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/
        0x03,           /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */
        0x04,           /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */
        1,              /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/
        0,              /* PN inversion per each lane.  bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/
        0,              /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        0               /* Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used*/
    };
    
    static mykonosRxGainControl_t rxGainControl =
    {
        MGC,            /* Current Rx gain control mode setting*/
        255,            /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Max gain index for the currently loaded Rx1 Gain table*/
        195,            /* Min gain index for the currently loaded Rx1 Gain table*/
        255,            /* Max gain index for the currently loaded Rx2 Gain table*/
        195,            /* Min gain index for the currently loaded Rx2 Gain table*/
        0,              /* Stores Rx1 RSSI value read back from the Mykonos*/
        0               /* Stores Rx2 RSSI value read back from the Mykonos*/
    };
    
    static mykonosORxGainControl_t orxGainControl =
    {
        MGC,            /* Current ORx gain control mode setting*/
        255,            /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Max gain index for the currently loaded ORx Gain table*/
        237             /* Min gain index for the currently loaded ORx Gain table*/
    };
    
    static mykonosSnifferGainControl_t snifferGainControl =
    {
        MGC,            /* Current Sniffer gain control mode setting*/
        255,            /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/
        255,            /* Max gain index for the currently loaded Sniffer Gain table*/
        203             /* Min gain index for the currently loaded Sniffer Gain table*/
    };
    
    static mykonosPeakDetAgcCfg_t rxPeakAgc =
    {
        0x26,	/* apdHighThresh: */
        0x16,	/* apdLowThresh */
        0xB5,	/* hb2HighThresh */
        0x72,	/* hb2LowThresh */
        0x40,	/* hb2VeryLowThresh */
        0x06,	/* apdHighThreshExceededCnt */
        0x04,	/* apdLowThreshExceededCnt */
        0x06,	/* hb2HighThreshExceededCnt */
        0x04,	/* hb2LowThreshExceededCnt */
        0x04,	/* hb2VeryLowThreshExceededCnt */
        0x4,	/* apdHighGainStepAttack */
        0x2,	/* apdLowGainStepRecovery */
        0x4,	/* hb2HighGainStepAttack */
        0x2,	/* hb2LowGainStepRecovery */
        0x4,	/* hb2VeryLowGainStepRecovery */
        0x1,	/* apdFastAttack */
        0x1,	/* hb2FastAttack */
        0x1,	/* hb2OverloadDetectEnable */
        0x1,	/* hb2OverloadDurationCnt */
        0x1	/* hb2OverloadThreshCnt */
    };
    
    static mykonosPowerMeasAgcCfg_t rxPwrAgc =
    {
        0x01,	/* pmdUpperHighThresh */
        0x03,	/* pmdUpperLowThresh */
        0x0C,	/* pmdLowerHighThresh */
        0x04,	/* pmdLowerLowThresh */
        0x4,	/* pmdUpperHighGainStepAttack */
        0x2,	/* pmdUpperLowGainStepAttack */
        0x2,	/* pmdLowerHighGainStepRecovery */
        0x4,	/* pmdLowerLowGainStepRecovery */
        0x08,	/* pmdMeasDuration */
        0x02	/* pmdMeasConfig */
    };
    
    static mykonosAgcCfg_t rxAgcConfig =
    {
        255,	/* agcRx1MaxGainIndex */
        195,	/* agcRx1MinGainIndex */
        255,	/* agcRx2MaxGainIndex */
        195,	/* agcRx2MinGainIndex: */
        255,	/* agcObsRxMaxGainIndex */
        203,	/* agcObsRxMinGainIndex */
        1,		/* agcObsRxSelect */
        1,		/* agcPeakThresholdMode */
        1,		/* agcLowThsPreventGainIncrease */
        30720,	/* agcGainUpdateCounter */
        3,	/* agcSlowLoopSettlingDelay */
        4,	/* agcPeakWaitTime */
        0,	/* agcResetOnRxEnable */
        0,	/* agcEnableSyncPulseForGainCounter */
        &rxPeakAgc,
        &rxPwrAgc
    };
    
    static mykonosPeakDetAgcCfg_t obsRxPeakAgc =
    {
        0x2A,	/* apdHighThresh: */
        0x16,	/* apdLowThresh */
        0xB5,	/* hb2HighThresh */
        0x72,	/* hb2LowThresh */
        0x40,	/* hb2VeryLowThresh */
        0x03,	/* apdHighThreshExceededCnt */
        0x03,	/* apdLowThreshExceededCnt */
        0x03,	/* hb2HighThreshExceededCnt */
        0x03,	/* hb2LowThreshExceededCnt */
        0x03,	/* hb2VeryLowThreshExceededCnt */
        0x4,	/* apdHighGainStepAttack */
        0x2,	/* apdLowGainStepRecovery */
        0x4,	/* hb2HighGainStepAttack */
        0x2,	/* hb2LowGainStepRecovery */
        0x4,	/* hb2VeryLowGainStepRecovery */
        0x0,	/* apdFastAttack */
        0x0,	/* hb2FastAttack */
        0x1,	/* hb2OverloadDetectEnable */
        0x1,	/* hb2OverloadDurationCnt */
        0x1		/* hb2OverloadThreshCnt */
    };
    
    static mykonosPowerMeasAgcCfg_t obsRxPwrAgc =
    {
        0x01,	/* pmdUpperHighThresh */
        0x03,	/* pmdUpperLowThresh */
        0x0C,	/* pmdLowerHighThresh */
        0x04,	/* pmdLowerLowThresh */
        0x0,	/* pmdUpperHighGainStepAttack */
        0x0,	/* pmdUpperLowGainStepAttack */
        0x0,	/* pmdLowerHighGainStepRecovery */
        0x0,	/* pmdLowerLowGainStepRecovery */
        0x08,	/* pmdMeasDuration */
        0x02	/* pmdMeasConfig */
    };
    
    static mykonosAgcCfg_t obsRxAgcConfig =
    {
        255,	/* agcRx1MaxGainIndex */
        195,	/* agcRx1MinGainIndex */
        255,	/* agcRx2MaxGainIndex */
        195,	/* agcRx2MinGainIndex: */
        255,	/* agcObsRxMaxGainIndex */
        203,	/* agcObsRxMinGainIndex */
        1,		/* agcObsRxSelect */
        1,		/* agcPeakThresholdMode */
        1,		/* agcLowThsPreventGainIncrease */
        30720,	/* agcGainUpdateCounter */
        3,		/* agcSlowLoopSettlingDelay */
        4,		/* agcPeakWaitTime */
        0,		/* agcResetOnRxEnable */
        0,		/* agcEnableSyncPulseForGainCounter */
        &obsRxPeakAgc,
        &obsRxPwrAgc
    };
    
    static uint16_t rxAdcCustom[]={745,449,201,98,1280,134,1509,64,1062,20,654,39,48,32,19,193};
    
    static mykonosRxProfile_t rxProfile =
    {/* RX 40MHz, Iqrate 49.152MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &rxFir,         /* Pointer to Rx FIR filter structure*/
        2,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        1,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        2,              /* RX Half band 1 decimation (1 or 2)*/
        49152,          /* Rx IQ data rate in kHz*/
        40000000,       /* The Rx RF passband bandwidth for the profile*/
        40000,          /* Rx BBF 3dB corner in kHz*/
        &rxAdcCustom[0] /* pointer to custom ADC profile*/
    };
    static uint16_t orxAdcCustom[]={745,449,201,98,1280,134,1509,64,1062,20,654,39,48,32,19,193};
    
    static mykonosRxProfile_t orxProfile =
    {/* ORX 40MHz, Iqrate 49.152MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &obsrxFir,      /* Pointer to Rx FIR filter structure or NULL*/
        2,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        2,              /* RX Half band 1 decimation (1 or 2)*/
        49152,          /* Rx IQ data rate in kHz*/
        40000000,       /* The Rx RF passband bandwidth for the profile*/
        20000,          /* Rx BBF 3dB corner in kHz*/
        &orxAdcCustom[0] /* pointer to custom ADC profile*/
    };
    
    static uint16_t snifferAdcCustom[]={750,447,201,98,1280,112,1505,53,1063,17,655,40,48,32,19,194};
    
    static mykonosRxProfile_t snifferProfile =
    { /* SNIFFER 20MHz, Iqrate 24.576MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &snifferRxFir,  /* Pointer to Rx FIR filter structure or NULL*/
        4,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        2,              /* RX Half band 1 decimation (1 or 2)*/
        24576,          /* Rx IQ data rate in kHz*/
        20000000,       /* The Rx RF passband bandwidth for the profile*/
        20000,          /* Rx BBF 3dB corner in kHz*/
        &snifferAdcCustom[0] /* pointer to custom ADC profile*/
    };
    
    
    
    static mykonosTxProfile_t txProfile =
    { /* TX 8/40MHz, Iqrate 49.152MSPS, DEC5 */
        DACDIV_2p5,     /* The divider used to generate the DAC clock*/
        &txFir,         /* Pointer to Tx FIR filter structure*/
        2,              /* The Tx digital FIR filter interpolation (1,2,4)*/
        2,              /* Tx Halfband1 filter interpolation (1,2)*/
        2,              /* Tx Halfband2 filter interpolation (1,2)*/
        1,              /* TxInputHbInterpolation (1,2)*/
        49152,          /* Tx IQ data rate in kHz*/
        8000000,        /* Primary Signal BW*/
        40000000,       /* The Tx RF passband bandwidth for the profile*/
        92000,          /* The DAC filter 3dB corner in kHz*/
        20000,          /* Tx BBF 3dB corner in kHz*/
        0               /* Enable DPD, only valid for AD9373*/
    };
    
    static mykonosDigClocks_t mykonosClocks =
    {
        122880,         /* CLKPLL and device reference clock frequency in kHz*/
        11796480,       /* CLKPLL VCO frequency in kHz*/
        VCODIV_3,       /* CLKPLL VCO divider*/
        4               /* CLKPLL high speed clock divider*/
    };
    
    static mykonosRxSettings_t  rxSettings =
    {
        &rxProfile,     /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &rxFramer,      /* Rx JESD204b framer configuration structure*/
        &rxGainControl, /* Rx Gain control settings structure*/
        &rxAgcConfig,   /* Rx AGC control settings structure*/
        3,              /* The desired Rx Channels to enable during initialization*/
        0,              /* Internal LO = 0, external LO*2 = 1*/
        2000000000U,     /* Rx PLL LO Frequency (internal or external LO)*/
        0               /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/
    };
    
    static mykonosDpdConfig_t dpdConfig =
    {
        5,              /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/
        1,              /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/
        2,              /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/
        1,              /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/
        20,             /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/
        0,              /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */
        512,            /* Number of samples to capture (default: 512, valid 64-32768)*/
        4096,           /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/
    };
    
    static mykonosClgcConfig_t clgcConfig =
    {
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/
        75,             /* valid range 1-100, default 75*/
        75,             /* valid range 1-100, default 45*/
        0,              /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx1Atten automatically updated*/
        0,              /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx2Atten automatically updated*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        600,            /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        600,            /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        0,              /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
        0               /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
    };
    
    static mykonosVswrConfig_t vswrConfig =
    {
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        0,              /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/
        1,              /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/
        0,              /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/
        0,              /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/
        50,             /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution*/
        50              /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution*/
    };
    
    static mykonosTxSettings_t txSettings =
    {
        &txProfile,     /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &deframer,      /* Mykonos JESD204b deframer config for the Tx data path*/
        TX1,        /* The desired Tx channels to enable during initialization*/
        0,              /* Internal LO=0, external LO*2 if =1*/
        4800000000U,     /* Tx PLL LO frequency (internal or external LO)*/
        TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/
        10000,          /* Initial and current Tx1 Attenuation mdB*/
        10000,          /* Initial and current Tx2 Attenuation mdB*/
        NULL,           /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/
        NULL,           /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
        NULL            /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
    };
    
    static uint16_t lpbkAdcCustom[]={750,447,201,98,1280,112,1505,53,1063,17,655,40,48,32,19,194};
    
    static mykonosObsRxSettings_t obsRxSettings =
    {
        &orxProfile,    /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &orxGainControl,/* ObsRx gain control settings structure*/
        &obsRxAgcConfig,/* ORx AGC control settings structure*/
        &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/
        &snifferGainControl,/* SnRx gain control settings structure*/
        &obsRxFramer,   /* ObsRx JESD204b framer configuration structure */
        (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */
        OBSLO_TX_PLL,   /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */
    	2000000000U,     /* SnRx PLL LO frequency in Hz */
        0,              /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/
        &lpbkAdcCustom[0],/* Custom Loopback ADC profile to set the bandwidth of the ADC response*/
        OBS_RXOFF       /* Default ObsRx channel to enter when radioOn called */
    };
    
    static mykonosArmGpioConfig_t armGpio =
    {
        0,	// useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */
        0,	// useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */
        0,	// txRxPinMode;     /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */
        0,	// orxPinMode;      /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/
    
        /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */
        0,	// orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */
        0,	// orxMode2Pin;   /*!< Select desired GPIO pin (valid 0-18) */
        0,	// orxMode1Pin;   /*!< Select desired GPIO pin (valid 0-18) */
        0,	// orxMode0Pin;   /*!< Select desired GPIO pin (valid 0-18) */
    
        /* Mykonos ARM output GPIO pins  --  always available, even when pin mode not enabled*/
        0,	// rx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// rx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// tx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// tx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// orx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// orx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// srxEnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0 	// txObsSelect;   /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is   */
        /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/
    };
    
    static mykonosGpio3v3_t gpio3v3 =
    {
        0,				/*!< Oe per pin, 1=output, 0 = input */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[3:0] */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[7:4] */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[11:8] */
    };
    
    static mykonosGpioLowVoltage_t gpio =
    {
        0,/* Oe per pin, 1=output, 0 = input */
        GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */
    };
    
    static mykonosAuxIo_t mykonosAuxIo =
    {
        0,	//auxDacEnableMask uint16_t
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacValue uint16[10]
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacSlope uint8[10]
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacVref uint8[10]
        &gpio3v3,	//pointer to gpio3v3 struct
        &gpio,	//pointer to gpio1v8 struct
        &armGpio
    };
    
    static spiSettings_t mykSpiSettings =
    {
        2, /* chip select index - valid 1~8 */
        0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */
        1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */
        1, /* 1 = MSBFirst, 0 = LSBFirst */
        0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */
        0, /* clock polarity 0 = clock starts low, 1 = clock starts high */
        0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */
        1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */
        1  /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */
    };
    
    static mykonosTempSensorConfig_t tempSensor =
    {
        7,              /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/
        67,             /* 8-bit offset that gets added to temp sensor code internally*/
        1,              /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/
        15,             /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/
    };
    
    static mykonosTempSensorStatus_t tempStatus =
    {
        0,              /* 16-bit signed temperature value (in deg C) that is read back*/
        0,              /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/
        0,              /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/
        0,              /* when the reading is complete and a valid temperature value stored in tempCode.*/
    };
    
    mykonosDevice_t mykDevice =
    {
        &mykSpiSettings,    /* SPI settings data structure pointer */
        &rxSettings,        /* Rx settings data structure pointer */
        &txSettings,        /* Tx settings data structure pointer */
        &obsRxSettings,     /* ObsRx settings data structure pointer */
        &mykonosAuxIo,          /* Auxiliary IO settings data structure pointer */
        &mykonosClocks,     /* Holds settings for CLKPLL and reference clock */
        0                   /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */
    };
    

    /* AD9528 data structure initialization file */
    
    /**
    * \page Disclaimer Legal Disclaimer
    * Copyright 2015-2017 Analog Devices Inc.
    * Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
    *
    */
    
    
    #include <stdint.h>
    #include "common.h"
    #include "t_ad9528.h"
    
    static spiSettings_t clockSpiSettings =
    {
         1,
         0,
         1,
         1,
         0,
         0,
         0,
         1,
         1,
         25000000
    };
    
    ad9528pll1Settings_t clockPll1Settings =
    {
        30720000,
        1,
        3,
        0,
        1,
        0,
        122880000,
        3,
        4
    };
    
    ad9528pll2Settings_t clockPll2Settings =
    {
        3,
        10,
        30
    };
    
    ad9528outputSettings_t clockOutputSettings =
    {
        53237,
        {0,0,0,2,0,0,0,0,0,0,0,0,2,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {10,10,10,10,10,10,10,10,10,10,10,10,10,10},
        {0,122880000,0,120000,0,0,0,0,0,0,0,0,120000,122880000}
    };
    
    ad9528sysrefSettings_t clockSysrefSettings =
    {
       0,
       2,
       0,
       0,
       0,
       0,
       512
    };
    
    ad9528Device_t clockAD9528_ =
    {
        &clockSpiSettings,
        &clockPll1Settings,
        &clockPll2Settings,
        &clockOutputSettings,
        &clockSysrefSettings
    };