Post Go back to editing

Bringing Up Clocks with adi_hmc7044.c

Category: Software
Product Number: HMC7044
Software Version: AD9082_API-Rel1.7.0

Hardware

Software

  • Yocto Linux
  • adi_hmc7044.c
  • adi_ad9082.c

Description

I'm trying to work with this ad9082-fmca-ebz board and am struggling to bring up the clocking chip. PLL lock for the hmc7044 seems intermittent/unreliable. I'm confident my hardware design is solid but if symptoms point to hardware issues, I can re-evaluate. troubleshooting ad9082 is another matter and probably a separate post. 

Function in Question

int hmc7044_testing(void)
{
    AD9082_UserData ud9082 = {
        .gpiochipName = "gpiochip1"
    };
    initUserData(&ud9082);
    
    adi_ad9082_hal_t hal9082 = {
        .user_data       = (void*)&ud9082,
        .sdo             = SPI_SDO,
        .msb             = 1,
        .addr_inc        = SPI_ADDR_INC_AUTO,
        .spi_xfer        = ad9082_mySpiTransfer,
        .delay_us        = ad9082_myDelayUs,
        .hw_open         = ad9082_myHwOpen,
        .hw_close        = ad9082_myHwClose,
        .log_write       = ad9082_myLogWrite,
        .tx_en_pin_ctrl  = ad9082_myTxEnPinCtrl,
        .reset_pin_ctrl  = ad9082_myResetPinCtrl
    };

    adi_ad9082_info_t info9082 = {
        .dev_freq_hz        = 3000000000ULL,   
        .dac_freq_hz        = 12000000000ULL,  
        .adc_freq_hz        = 4000000000ULL,   
        .dev_rev            = 0,
        .jesd_rx_lane_rate  = 10000000000ULL   
    };

    adi_ad9082_ser_lane_settings_t lane_cfg[8];
    for(int i = 0; i < 8; i++) {
        lane_cfg[i].swing_setting    = AD9082_SER_SWING_1000;
        lane_cfg[i].pre_emp_setting  = AD9082_SER_PRE_EMP_0DB;
        lane_cfg[i].post_emp_setting = AD9082_SER_POST_EMP_0DB;
    }

    uint8_t lane_map_tx[2][8] = {
        {0,1,2,3,4,5,6,7},  
        {0}                 
    };

    adi_ad9082_ser_settings_t ser_cfg = {
        .invert_mask   = 0,
        .lane_settings = {0},
        .lane_mapping  = {{0}}
    };

    memcpy(ser_cfg.lane_settings, lane_cfg, sizeof(lane_cfg));
    memcpy(ser_cfg.lane_mapping, lane_map_tx, sizeof(lane_map_tx));

    adi_ad9082_des_settings_t des_cfg = {0};

    adi_ad9082_serdes_settings_t serdes_cfg = {
        .ser_settings = ser_cfg,
        .des_settings = des_cfg
    };

    adi_ad9082_clk_t clk_cfg = {
        .sysref_mode = SYSREF_CONT   
    };

    adi_ad9082_device_t ad9082 = {
        .hal_info    = hal9082,
        .dev_info    = info9082,
        .serdes_info = serdes_cfg,
        .clk_info    = clk_cfg
    };

    adi_ad9082_device_hw_open(&ad9082);

    HMC7044_UserData ud7044 = {
        .gpiochipName = "gpiochip1",
        .readEnPin    = 79,
        .writeEnPin   = 80,
        .syncPin      = 81
    };

    adi_hmc7044_hal_t hal7044 = {
        .user_data     = &ud7044,
        .spi_xfer      = hmc7044_mySpiTransfer,
        .delay_us      = hmc7044_myDelayUs,
        .reset_pin_ctrl= hmc7044_myResetPinCtrl,
        .hw_open       = hmc7044_myHwOpen,
        .hw_close      = hmc7044_myHwClose
    };

    adi_hmc7044_device_t hmc = {
        .hal_info = hal7044
    };

    printf("DEBUG: Opening HMC7044\n");
    adi_hmc7044_device_hw_open(&hmc);

    int32_t err = 0;

    const uint64_t fpga_clk   = 250000000ULL;   
    const uint64_t dev_clk    = 125000000ULL;   
    const uint64_t sysref_clk = 1000000ULL;     
    const uint64_t ref_in     = 100000000ULL;   
    const uint64_t clk_3g      = 3000000000ULL;

    uint8_t  prio[] = {0,1,2,3};

    uint16_t out_ch =
        HMC7044_OP_CH_0  |
        HMC7044_OP_CH_2  |   
        HMC7044_OP_CH_3  |  
        HMC7044_OP_CH_6  |   
        HMC7044_OP_CH_8  |   
        HMC7044_OP_CH_10 |   
        HMC7044_OP_CH_12;    

    uint64_t out_freqs[14] = {
        fpga_clk/2,       
        0,                
        clk_3g,          
        sysref_clk,       
        0,0,
        fpga_clk/2,       
        0,
        fpga_clk,         
        0,
        fpga_clk/2,       
        0,
        fpga_clk,         
        0
    };

    err = adi_hmc7044_device_init(&hmc);          print_err(err);
    err = adi_hmc7044_device_reset(&hmc, 0);      print_err(err);

    for(int i=0;i<14;i++) {
        err = adi_hmc7044_output_config_set(&hmc, i, HMC7044_OP_SIG_CH_DIV, 0,0,0);
        print_err(err);
    }

    err = adi_hmc7044_input_reference_set(&hmc, 0, IPBUFFER_INTERNAL_100_OHM_EN | IPBUFFER_AC_COUPLED_MODE_EN, 1);
    print_err(err);

    err = adi_hmc7044_vco_sel_set(&hmc, HMC7044_VCO_INTERNAL_3GHZ, 0);
    print_err(err);

    err = adi_hmc7044_output_sync_config_set(&hmc, 3, (clk_cfg.sysref_mode == SYSREF_ONESHOT), 1, 1);
    print_err(err);

    err = adi_hmc7044_sysref_config_set(&hmc,
            (clk_cfg.sysref_mode == SYSREF_ONESHOT)    ? HMC7044_SYSREF_1_PULSE : HMC7044_SYSREF_CONTINUOUS_MODE);
    print_err(err);

    err = adi_hmc7044_clk_config(
            &hmc, HMC7044_CLK_IN_0,
            prio,
            ref_in,   /* primary reference */
            ref_in,   /* secondary unused */
            out_ch,
            out_freqs);
    print_err(err);

    //    err = adi_hmc7044_output_config_set(&hmc, 2, HMC7044_OP_SIG_CH_DIV, 1, 1, 1);    print_err(err);
    //    err = adi_hmc7044_output_config_set(&hmc, 3, HMC7044_OP_SIG_CH_DIV, 192, 1, 1);    print_err(err);
    //    err = adi_hmc7044_output_config_set(&hmc, 6, HMC7044_OP_SIG_CH_DIV, 12, 0, 1);    print_err(err);
    //    err = adi_hmc7044_output_config_set(&hmc, 10, HMC7044_OP_SIG_CH_DIV, 12, 0, 1);    print_err(err);
    //    err = adi_hmc7044_output_config_set(&hmc, 12, HMC7044_OP_SIG_CH_DIV, 12, 0, 1);    print_err(err);
    //    err = adi_hmc7044_output_config_set(&hmc, 13, HMC7044_OP_SIG_CH_DIV, 192, 0, 1);print_err(err);


    err = adi_hmc7044_device_sysref_enable_control_set(&hmc, 1, 1);
    print_err(err);
    err = adi_hmc7044_high_performance_set(&hmc); print_err(err);
    err = adi_hmc7044_reg_update(&hmc);           print_err(err);
    err = adi_hmc7044_reseed_request_set(&hmc);   print_err(err);

    uint8_t pll_status = 0;
    printf("Waiting for HMC7044 PLL lock...\n");
    for(int i=0; i<50; i++) {
        adi_hmc7044_device_pll_lock_status_get(&hmc, &pll_status);
        printf("PLL: %s\r",
                (pll_status == HMC7044_PLL1_AND_PLL2_LOCK_ST) ? "Both LOCKED" :
                (pll_status == HMC7044_PLL1_LOCK_ST)          ? "PLL1 only" :
                (pll_status == HMC7044_PLL2_LOCK_ST)          ? "PLL2 only" :
                "UNLOCKED");
        fflush(stdout);
        usleep(20000);
    }

    adi_ad9082_device_hw_close(&ad9082);
    if(pll_status != HMC7044_PLL1_AND_PLL2_LOCK_ST) {
        printf("\r\nPLLs were not locked\r\n");
        return 0;
    } else {
        printf("\r\nHMC7044 LOCKED. Clocking OK.\n");
        return 1;
    }

}

Before You Switch


Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.