整体架构—区分9528版本代码和7044版本
默认的硬件板子是zc706 + adrv9009-w/pcbz,该9009板搭载时钟为9528。
- 本篇主要关注9528时钟部分
硬件连接图如下:
-复位(clocking_init),输入所有用到的时钟
adiHalErr_t clocking_init(uint32_t rx_div40_rate_hz,
uint32_t tx_div40_rate_hz,
uint32_t rx_os_div40_rate_hz,
uint32_t device_clock_khz,
uint32_t lmfc_rate_hz)
rate_dev = device_clock_khz * 1000;
rate_fmc = device_clock_khz * 1000;
初始化9528
关闭所有时钟输出,再根据代码,只输出1、3、12、13渠道。分别对应以下信道(fr.app_clocking.h)
DEV_CLK是指给9009的时钟信号
FMC_CLK是指给fpga的时钟信号
再设置9528参数,具体什么意思可以在代码中用鼠标放在上面看到
// ad9528 settings
ad9528_param.pdata->spi3wire = 0;
ad9528_param.pdata->vcxo_freq = 122880000;
ad9528_param.pdata->refa_en = 1;
ad9528_param.pdata->refa_diff_rcv_en = 1;
ad9528_param.pdata->refa_r_div = 1;
ad9528_param.pdata->osc_in_cmos_neg_inp_en = 1;
ad9528_param.pdata->pll1_feedback_div = 4;
ad9528_param.pdata->pll1_feedback_src_vcxo = 0; /* VCO */
ad9528_param.pdata->pll1_charge_pump_current_nA = 5000;
ad9528_param.pdata->pll1_bypass_en = 0;
ad9528_param.pdata->pll2_vco_div_m1 = 3;
ad9528_param.pdata->pll2_n2_div = 10;
ad9528_param.pdata->pll2_r1_div = 1;
ad9528_param.pdata->pll2_charge_pump_current_nA = 805000;
ad9528_param.pdata->pll2_bypass_en = false;
ad9528_param.pdata->sysref_src = SYSREF_SRC_INTERNAL;
ad9528_param.pdata->sysref_pattern_mode = SYSREF_PATTERN_CONTINUOUS;
ad9528_param.pdata->sysref_req_en = true;
ad9528_param.pdata->sysref_nshot_mode = SYSREF_NSHOT_4_PULSES;
ad9528_param.pdata->sysref_req_trigger_mode = SYSREF_LEVEL_HIGH;
ad9528_param.pdata->rpole2 = RPOLE2_900_OHM;
ad9528_param.pdata->rzero = RZERO_1850_OHM;
ad9528_param.pdata->cpole1 = CPOLE1_16_PF;
ad9528_param.pdata->stat0_pin_func_sel = 0x1; /* PLL1 & PLL2 Locked */
ad9528_param.pdata->stat1_pin_func_sel = 0x7; /* REFA Correct */
定义xil_gpio_param、xil_spi_param
type为._PS和device_id。
struct xil_spi_init_param xil_spi_param = {
#ifdef PLATFORM_MB
.type = SPI_PL,
#else
.type = SPI_PS,
#endif
#if defined(ZU11EG) || defined(FMCOMMS8_ZCU102)
.flags = SPI_CS_DECODE
#endif
};
#if !defined(ZU11EG) && !defined(FMCOMMS8_ZCU102)
struct xil_gpio_init_param xil_gpio_param = {
#ifdef PLATFORM_MB
.type = GPIO_PL,
#else
.type = GPIO_PS,
#endif
.device_id = GPIO_DEVICE_ID,
};
对axi_clkgen初始化
包括三个rx tx rx_os的初始化。给定基地址和频率。
设置时钟芯片的spi控制-clkchip_spi_init_param
这里的extra表示SPI extra parameters (device specific)。并且如果板卡型号不是706时,给出了另外的clock chip spi setting。
设置时钟芯片的gpio口初始化
定义结构体no_os_gpio_init_param,对gpio_resetb赋值clkchip_gpio_init_param的地址。
**并指明hmc7044通常通过向相关的控制器或处理器发送特定的数据序列来实现,从而重新初始化系统并将其恢复到初始状态.
struct no_os_gpio_init_param clkchip_gpio_init_param = {
.number = CLK_RESETB_GPIO,
.platform_ops = &xil_gpio_ops,
.extra = &xil_gpio_param
};
ad9528_param.gpio_resetb = &clkchip_gpio_init_param;
#endif
状态检查及报错
检验是否有初始化失败,同时检验了dev_clk和fmc_clk的状态是否正确。
-如果是fmc7044,检查dev_refclk_A/B,jesd_refclk_tx——obs/rx_AB.
-先round_rate再set_rate
#else
ad9528_clk_set_rate(clkchip_device, DEV_CLK, dev_clk);
ad9528_clk_set_rate(clkchip_device, FMC_CLK, fmc_clk);
#endif
} else {
printf("Requesting device clock %u failed got %u\n",
device_clock_khz * 1000, dev_clk);
goto error_1;
}
check sysref rate -这个check通过判断余数是否小于商,或大于参考时钟减商,使其忽略由于取整而引入的微小偏差,以便确定系统参考时钟的频率是否在可接受的范围内。
-如果速率始终不合适,则通过lmfc_rate_hz/n,n=1-64的方式来寻找一个合适的速率,且由小到大寻找。
-仍然是set_rate,设置的是FMC_SYSREF和DEV_SYSREF。如果是7044的话,区分了两个SYSREF的A/B。
检查CLKGEN-INIT、速率设置状态
检查axi_clkgen_init是否成功,返回状态--------rx\tx\rx_os eg.axi_clkgen_init(&rx_os_clkgen, &rx_os_clkgen_init);
检查: axi_clkgen_set_rate返回状态---------rx_clkgen\tx_clkgen\rx_os_clkgen并返回
eg. axi_clkgen_set_rate(rx_os_clkgen, rx_os_div40_rate_hz);
如果报错的处理方式:移除给定的rx_os_clkgen eg.axi_clkgen_remove