1. 下载AD9361 版本内核
从GitHub 上下载含ad9361(ad9371)的驱动,网址为:analogdevicesinc/linux at adi-4.19.0 (github.com),选择对应的内核版本。
2. 修改ad9361 驱动
在/drivers/iio/adc/ad9361.c 中修改添加of匹配表,修改匹配规则。原程序如下:
添加匹配规则,匹配"兼容性"属性为'ad9361'的spi设备,支持通过查找驱动名称为ad9361-phy的spi驱动。(兼容性必须为'ad9361', 否则在ad9361_id 表中找不到对应的模式,会导致系统崩溃。)
可打开该驱动的_DEBUG 宏,可以看到spi 读写寄存器的情况。
3. 修改设备树文件
首先需要将pcw.dtsi 、 pl.dtsi 、system-top.dts 以 及 zynq-7000.dtsi 四个文件直接 拷贝到arch/arm/boot/dts 目录下。详情见1. 设备树生成 章节。
与之前不同的是,需要在system-top.dts 中引用adi-fmcomms2.dtsi 设备描述文件。其余属性如下所示:
adi-fmcomms2.dtsi 是设备树的一个片段文件,定义了与FMCOMMS2/3/4板相关的设备配置,特别是AD9361芯片的配置。它通常包括SPI总线配置、GPIO配置和相关的时钟配置。
其中FMCOMMS 的架构如下:
- FMCOMMS2:
采用单个AD9361芯片,提供双通道(2x2 MIMO)配置,即两个接收(RX)和两个发送(TX)通道。
- FMCOMMS5:
采用两个AD9361芯片,提供四通道(4x4 MIMO)配置,即四个接收(RX)和四个发送(TX)通道。这个设计允许进行更复杂的MIMO系统开发,如4x4 MIMO的无线通信系统。
本板卡对应的是adi-fmcomms2.dtsi文件,因此引用adi-fmcomms2.dtsi 文件并对其修改。
-
- 找到&fmc_spi结点,在其前面添加#define fmc_spi spi0,使fmc_spi等同于spi0 结点。
- 修改compatible 值为 "ad9361" (去掉adi)。
- 在 SPI Setup 中配置SPI 分频后的时钟,当前设置的是500K,可根据需要调整。
- 添加reset-gpios 属性,该属性用于复位Ad9361 ,并且会在驱动中调用该属性进行复位,该属性挂载EMIO 2 接口,然后通过XDC 连接到ad9361的管脚,低有效。
如图所示:
附上完整设备树代码:
bash
/ {
clocks {
ad9361_clkin: clock@0 {
compatible = "fixed-clock";
clock-frequency = <40000000>;
clock-output-names = "ad9361_ext_refclk";
#clock-cells = <0>;
};
};
};
#define fmc_spi spi0
&fmc_spi {
adc0_ad9361: ad9361-phy@0 {
compatible = "ad9361";
reg = <0>;
/* SPI Setup */
spi-cpha;
//spi-cpol;
spi-max-frequency = <5000000>;
txnrx-gpios = <&gpio0 54 0>;
enable-gpios = <&gpio0 55 0>;
reset-gpios = <&gpio0 56 0>;
sync-gpios = <&gpio0 57 0>;
en_agc-gpios = <&gpio0 58 0>;
ctrl_in_0-gpios = <&gpio0 59 0>;
ctrl_in_1-gpios = <&gpio0 60 0>;
ctrl_in_2-gpios = <&gpio0 61 0>;
ctrl_in_3-gpios = <&gpio0 62 0>;
//xlnx,spi-clk-freq = <166666672>; // 指定SPI控制器的输入时钟频率为166.666672 MHz
/* Clocks */
clocks = <&ad9361_clkin 0>;
clock-names = "ad9361_ext_refclk";
clock-output-names = "rx_sampl_clk", "tx_sampl_clk";
#clock-cells = <1>;
//adi,debug-mode-enable;
/* Digital Interface Control */
/* adi,digital-interface-tune-skip-mode:
* 0 = TUNE RX&TX
* 1 = SKIP TX
* 2 = SKIP ALL
*/
adi,digital-interface-tune-skip-mode = <0>;
adi,pp-tx-swap-enable;
adi,pp-rx-swap-enable;
adi,rx-frame-pulse-mode-enable;
adi,lvds-mode-enable;
adi,lvds-bias-mV = <150>;
adi,lvds-rx-onchip-termination-enable;
adi,rx-data-delay = <4>;
adi,tx-fb-clock-delay = <7>;
//adi,fdd-rx-rate-2tx-enable;
adi,dcxo-coarse-and-fine-tune = <8 5920>;
//adi,xo-disable-use-ext-refclk-enable;
/* Mode Setup */
adi,2rx-2tx-mode-enable = <1>;
//adi,split-gain-table-mode-enable;
/* ENSM Mode */
adi,frequency-division-duplex-mode-enable = <1>;
adi,ensm-enable-pin-pulse-mode-enable = <0>;
adi,ensm-enable-txnrx-control-enable = <1>;
/* adi,rx-rf-port-input-select:
* 0 = (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced
* 1 = (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced
* 2 = (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced
*
* 3 = RX1A_N and RX2A_N enabled; unbalanced
* 4 = RX1A_P and RX2A_P enabled; unbalanced
* 5 = RX1B_N and RX2B_N enabled; unbalanced
* 6 = RX1B_P and RX2B_P enabled; unbalanced
* 7 = RX1C_N and RX2C_N enabled; unbalanced
* 8 = RX1C_P and RX2C_P enabled; unbalanced
*/
adi,rx-rf-port-input-select = <0>; /* (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced */
/* adi,tx-rf-port-input-select:
* 0 TX1A, TX2A
* 1 TX1B, TX2B
*/
adi,tx-rf-port-input-select = <0>; /* TX1A, TX2A */
adi,update-tx-gain-in-alert-enable = <0>;
adi,tx-attenuation-mdB = <10000>;
adi,tx-lo-powerdown-managed-enable = <1>;
adi,rf-rx-bandwidth-hz = <18000000>;
adi,rf-tx-bandwidth-hz = <18000000>;
adi,rx-synthesizer-frequency-hz = /bits/ 64 <1500000000>;
adi,tx-synthesizer-frequency-hz = /bits/ 64 <1500000000>;
/* BBPLL ADC R2CLK R1CLK CLKRF RSAMPL */
adi,rx-path-clock-frequencies = <983040000 245760000 122880000 61440000 30720000 30720000>;
/* BBPLL DAC T2CLK T1CLK CLKTF TSAMPL */
adi,tx-path-clock-frequencies = <983040000 122880000 122880000 61440000 30720000 30720000>;
/* Gain Control */
//adi,gaintable-name = "ad9361_std_gaintable";
/* adi,gc-rx[1|2]-mode:
* 0 = RF_GAIN_MGC
* 1 = RF_GAIN_FASTATTACK_AGC
* 2 = RF_GAIN_SLOWATTACK_AGC
* 3 = RF_GAIN_HYBRID_AGC
*/
adi,gc-rx1-mode = <1>;
adi,gc-rx2-mode = <1>;
adi,gc-adc-ovr-sample-size = <4>; /* sum 4 samples */
adi,gc-adc-small-overload-thresh = <47>; /* sum of squares */
adi,gc-adc-large-overload-thresh = <58>; /* sum of squares */
adi,gc-lmt-overload-high-thresh = <800>; /* mV */
adi,gc-lmt-overload-low-thresh = <704>; /* mV */
adi,gc-dec-pow-measurement-duration = <8192>; /* 0..524288 Samples */
adi,gc-low-power-thresh = <24>; /* 0..-64 dBFS vals are set pos */
//adi,gc-dig-gain-enable;
//adi,gc-max-dig-gain = <15>;
/* Manual Gain Control Setup */
//adi,mgc-rx1-ctrl-inp-enable; /* uncomment to use ctrl inputs */
//adi,mgc-rx2-ctrl-inp-enable; /* uncomment to use ctrl inputs */
adi,mgc-inc-gain-step = <2>;
adi,mgc-dec-gain-step = <2>;
/* adi,mgc-split-table-ctrl-inp-gain-mode:
* (relevant if adi,split-gain-table-mode-enable is set)
* 0 = AGC determine this
* 1 = only in LPF
* 2 = only in LMT
*/
adi,mgc-split-table-ctrl-inp-gain-mode = <0>;
/* Automatic Gain Control Setup */
adi,agc-attack-delay-extra-margin-us= <1>; /* us */
adi,agc-outer-thresh-high = <5>; /* -dBFS */
adi,agc-outer-thresh-high-dec-steps = <2>; /* 0..15 */
adi,agc-inner-thresh-high = <10>; /* -dBFS */
adi,agc-inner-thresh-high-dec-steps = <1>; /* 0..7 */
adi,agc-inner-thresh-low = <12>; /* -dBFS */
adi,agc-inner-thresh-low-inc-steps = <1>; /* 0..7 */
adi,agc-outer-thresh-low = <18>; /* -dBFS */
adi,agc-outer-thresh-low-inc-steps = <2>; /* 0..15 */
adi,agc-adc-small-overload-exceed-counter = <10>; /* 0..15 */
adi,agc-adc-large-overload-exceed-counter = <5>; /* 0..15 */
adi,agc-adc-large-overload-inc-steps = <2>; /* 0..15 */
//adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable;
adi,agc-lmt-overload-large-exceed-counter = <5>; /* 0..15 */
adi,agc-lmt-overload-small-exceed-counter = <10>; /* 0..15 */
adi,agc-lmt-overload-large-inc-steps = <2>; /* 0..7 */
//adi,agc-dig-saturation-exceed-counter = <3>; /* 0..15 */
//adi,agc-dig-gain-step-size = <4>; /* 1..8 */
//adi,agc-sync-for-gain-counter-enable;
adi,agc-gain-update-interval-us = <1000>; /* 1ms */
//adi,agc-immed-gain-change-if-large-adc-overload-enable;
//adi,agc-immed-gain-change-if-large-lmt-overload-enable;
/* Fast AGC */
adi,fagc-dec-pow-measurement-duration = <16>; /* 64 Samples */
adi,fagc-allow-agc-gain-increase-enable = <0>;
adi,fagc-lp-thresh-increment-steps = <1>;
adi,fagc-lp-thresh-increment-time = <5>;
adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt = <8>;
adi,fagc-final-overrange-count = <3>;
//adi,fagc-gain-increase-after-gain-lock-enable;
adi,fagc-gain-index-type-after-exit-rx-mode = <0>;
adi,fagc-lmt-final-settling-steps = <1>;
adi,fagc-lock-level = <10>;
adi,fagc-lock-level-gain-increase-upper-limit = <5>;
adi,fagc-lock-level-lmt-gain-increase-enable;
adi,fagc-lpf-final-settling-steps = <1>;
adi,fagc-optimized-gain-offset = <5>;
adi,fagc-power-measurement-duration-in-state5 = <64>;
adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable;
adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll = <10>;
adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable;
adi,fagc-rst-gla-if-en-agc-pulled-high-mode = <0>;
adi,fagc-rst-gla-large-adc-overload-enable;
adi,fagc-rst-gla-large-lmt-overload-enable;
adi,fagc-rst-gla-stronger-sig-thresh-above-ll = <10>;
adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable;
adi,fagc-state-wait-time-ns = <30>;
adi,fagc-use-last-lock-level-for-set-gain-enable;
/* RSSI */
/* adi,rssi-restart-mode:
* 0 = AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN,
* 1 = EN_AGC_PIN_IS_PULLED_HIGH,
* 2 = ENTERS_RX_MODE,
* 3 = GAIN_CHANGE_OCCURS,
* 4 = SPI_WRITE_TO_REGISTER,
* 5 = GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH,
*/
adi,rssi-restart-mode = <3>;
//adi,rssi-unit-is-rx-samples-enable;
adi,rssi-delay = <1>; /* 1us */
adi,rssi-wait = <1>; /* 1us */
adi,rssi-duration = <1000>; /* 1ms */
/* Control Outputs */
adi,ctrl-outs-index = <0>;
adi,ctrl-outs-enable-mask = <0xFF>;
/* AuxADC Temp Sense Control */
adi,temp-sense-measurement-interval-ms = <1000>;
adi,temp-sense-offset-signed = <0xCE>;
adi,temp-sense-periodic-measurement-enable;
/* AuxDAC Control */
adi,aux-dac-manual-mode-enable;
adi,aux-dac1-default-value-mV = <0>;
//adi,aux-dac1-active-in-rx-enable;
//adi,aux-dac1-active-in-tx-enable;
//adi,aux-dac1-active-in-alert-enable;
adi,aux-dac1-rx-delay-us = <0>;
adi,aux-dac1-tx-delay-us = <0>;
adi,aux-dac2-default-value-mV = <0>;
//adi,aux-dac2-active-in-rx-enable;
//adi,aux-dac2-active-in-tx-enable;
//adi,aux-dac2-active-in-alert-enable;
adi,aux-dac2-rx-delay-us = <0>;
adi,aux-dac2-tx-delay-us = <0>;
};
};
#define fmc_i2c i2c0
&fmc_i2c {
ad7291@2f {
compatible = "adi,ad7291";
reg = <0x2f>;
};
eeprom@50 {
compatible = "at24,24c02";
reg = <0x50>;
};
};
附上ad9361驱动代码:
cpp
static int ad9361_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad9361_rf_phy_state *st;
struct ad9361_rf_phy *phy;
struct clk *clk = NULL;
int ret, rev;
dev_info(&spi->dev, "%s : enter (%s)", __func__,
spi_get_device_id(spi)->name);
// add from meng
ad9361_cfg();
init_gpio(spi);
clk = devm_clk_get(&spi->dev, NULL);
if (IS_ERR(clk)) {
return -EPROBE_DEFER;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*phy));
if (indio_dev == NULL)
return -ENOMEM;
st = devm_kzalloc(&spi->dev, sizeof(*st), GFP_KERNEL);
if (st == NULL)
return -ENOMEM;
phy = iio_priv(indio_dev);
phy->state = st;
phy->indio_dev = indio_dev;
phy->spi = spi;
phy->clk_refin = clk;
ad9361_init_state(phy);
phy->pdata = ad9361_phy_parse_dt(indio_dev, &spi->dev);
if (phy->pdata == NULL)
return -EINVAL;
// phy->pdata->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
// GPIOD_OUT_HIGH);
phy->pdata->reset_gpio = meng_gpio.resetb_gpio;
if (IS_ERR(phy->pdata->reset_gpio))
return PTR_ERR(phy->pdata->reset_gpio);
/* Optional: next three used for MCS synchronization */
// phy->pdata->sync_gpio = devm_gpiod_get_optional(&spi->dev, "sync",
// GPIOD_OUT_LOW);
phy->pdata->sync_gpio = meng_gpio.sync_in_gpio;
if (IS_ERR(phy->pdata->sync_gpio))
return PTR_ERR(phy->pdata->sync_gpio);
phy->pdata->cal_sw1_gpio = devm_gpiod_get_optional(&spi->dev, "cal-sw1",
GPIOD_OUT_LOW);
if (IS_ERR(phy->pdata->cal_sw1_gpio))
return PTR_ERR(phy->pdata->cal_sw1_gpio);
phy->pdata->cal_sw2_gpio = devm_gpiod_get_optional(&spi->dev, "cal-sw2",
GPIOD_OUT_LOW);
if (IS_ERR(phy->pdata->cal_sw2_gpio))
return PTR_ERR(phy->pdata->cal_sw2_gpio);
ret = ad9361_register_ext_band_control(phy);
if (ret < 0)
dev_warn(&spi->dev,
"%s: failed to initialize ext band control\n",
__func__);
phy->gt_info = ad9361_adi_gt_info;
ad9361_request_gt(phy, NULL);
ad9361_reset(phy);
ret = ad9361_spi_read(spi, REG_PRODUCT_ID);
printk("%s : read PRODUCT_ID 0x%X",
__func__, ret);
if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) {
printk("%s : Unknown PRODUCT_ID 0x%X",
__func__, ret);
return -ENODEV;
}
rev = ret & REV_MASK;
if (spi_get_device_id(spi)->driver_data == ID_AD9364) {
phy->pdata->rx2tx2 = false;
phy->pdata->rx1tx1_mode_use_rx_num = 1;
phy->pdata->rx1tx1_mode_use_tx_num = 1;
}
INIT_WORK(&phy->work, ad9361_work_func);
init_completion(&phy->complete);
ret = register_clocks(phy);
if (ret < 0)
return ret;
ret = ad9361_setup(phy);
if (ret < 0)
goto out_unregister_notifier;
ret = of_clk_add_provider(spi->dev.of_node,
of_clk_src_onecell_get, &phy->clk_data);
if (ret)
goto out_disable_clocks;
sysfs_bin_attr_init(&phy->bin);
phy->bin.attr.name = "filter_fir_config";
phy->bin.attr.mode = S_IWUSR | S_IRUGO;
phy->bin.write = ad9361_fir_bin_write;
phy->bin.read = ad9361_fir_bin_read;
phy->bin.size = 4096;
sysfs_bin_attr_init(&phy->bin_gt);
phy->bin_gt.attr.name = "gain_table_config";
phy->bin_gt.attr.mode = S_IWUSR | S_IRUGO;
phy->bin_gt.write = ad9361_gt_bin_write;
phy->bin_gt.read = ad9361_gt_bin_read;
phy->bin_gt.size = 4096;
indio_dev->dev.parent = &spi->dev;
if (spi->dev.of_node)
indio_dev->name = spi->dev.of_node->name;
else
indio_dev->name = "ad9361-phy";
indio_dev->info = &ad9361_phy_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad9361_phy_chan;
indio_dev->num_channels = ARRAY_SIZE(ad9361_phy_chan) -
(phy->pdata->rx2tx2 ? 0 : 2);
ret = iio_device_register(indio_dev);
if (ret < 0)
goto out_clk_del_provider;
ret = ad9361_register_axi_converter(phy);
if (ret < 0)
goto out_iio_device_unregister;
ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &phy->bin);
if (ret < 0)
goto out_iio_device_unregister;
ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &phy->bin_gt);
if (ret < 0)
goto out_iio_device_unregister;
ret = ad9361_register_debugfs(indio_dev);
// if (ret < 0)
// dev_warn(&spi->dev, "%s: failed to register debugfs", __func__);
// added from meng
ad9361_Base_Parameters_Cfg(phy);
ad9361_gpio_cfg();
ad9361_module_cfg();
Get_Reg_Value(*spi);
dev_info(&spi->dev, "%s : AD936x Rev %d successfully initialized",
__func__, rev);
return 0;
out_iio_device_unregister:
iio_device_unregister(indio_dev);
out_clk_del_provider:
of_clk_del_provider(spi->dev.of_node);
out_disable_clocks:
ad9361_clks_disable(phy);
out_unregister_notifier:
clk_notifier_unregister(phy->clks[RX_RFPLL], &phy->clk_nb_rx);
clk_notifier_unregister(phy->clks[TX_RFPLL], &phy->clk_nb_tx);
return ret;
}
static int ad9361_remove(struct spi_device *spi)
{
struct ad9361_rf_phy *phy = ad9361_spi_to_phy(spi);
ad9361_unregister_ext_band_control(phy);
sysfs_remove_bin_file(&phy->indio_dev->dev.kobj, &phy->bin_gt);
sysfs_remove_bin_file(&phy->indio_dev->dev.kobj, &phy->bin);
iio_device_unregister(phy->indio_dev);
of_clk_del_provider(spi->dev.of_node);
clk_notifier_unregister(phy->clks[RX_RFPLL], &phy->clk_nb_rx);
clk_notifier_unregister(phy->clks[TX_RFPLL], &phy->clk_nb_tx);
ad9361_clks_disable(phy);
return 0;
}
static const struct spi_device_id ad9361_id[] = {
{"ad9361", ID_AD9361}, /* 2RX2TX */
{"ad9364", ID_AD9364}, /* 1RX1TX */
{"ad9361-2x", ID_AD9361_2}, /* 2 x 2RX2TX */
{"ad9363a", ID_AD9363A}, /* 2RX2TX */
{}
};
MODULE_DEVICE_TABLE(spi, ad9361_id);
/* 匹配列表 */
static const struct of_device_id myspi_of_match[] = {
{ .compatible = "ad9361", },
// { .compatible = "alientek,spidev" },
{ /* Sentinel */ }
};
static struct spi_driver ad9361_driver = {
.driver = {
.name = "ad9361-phy",
.of_match_table = myspi_of_match,
.owner = THIS_MODULE,
},
.probe = ad9361_probe,
.remove = ad9361_remove,
.id_table = ad9361_id,
};
module_spi_driver(ad9361_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD9361 ADC");
MODULE_LICENSE("GPL v2");
4. 编译内核
依次执行以下命令,在执行命令前,需要按 修改顶层 Makefile 章节的流程修改Makefile 文件。
make clean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_zynq_defconfig
make menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j20 #> res.txt
在打开的配置界面中,使用方向键导航到以下路径:
Device Drivers -> Industrial I/O support -> Analog to digital converters
- 启用 Analog Devices AD9361 RF Agile Transceiver(配置为模块或内置)。
如图所示:
保存配置并退出。
然后生成设备树文件:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- system-top.dtb -j20
然后替换掉内核和设备树文件即可,对应pl设计如下:
硬件约束如下:
bash
#***************************************************************
#作者 : Meng
#版本 : V1.0
#描述 : Ad9364约束文件。
#其他 : 无
#日志 : 初版V1.0 2024/12/02 Meng创建
#修改 :无
#***************************************************************
# SPI 配置部分
# SPI 配置:片选信号
# 引脚名称:SPI_ENB
set_property PACKAGE_PIN M14 [get_ports SPI0_SS_O_0]
set_property IOSTANDARD LVCMOS25 [get_ports SPI0_SS_O_0]
set_property PULLUP true [get_ports SPI0_SS_O_0]
# SPI 配置:时钟信号
# 引脚名称:SPI_CLK
set_property -dict {PACKAGE_PIN M15 IOSTANDARD LVCMOS25} [get_ports SPI0_SCLK_O_0]
# SPI 配置:主设备数据输出
# 引脚名称:SPI_DI (MOSI)
set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS25} [get_ports SPI0_MOSI_O_0]
# SPI 配置:主设备数据输入
# 引脚名称:SPI_DO (MISO)
set_property -dict {PACKAGE_PIN J16 IOSTANDARD LVCMOS25} [get_ports SPI0_MISO_I_0]
# AD9364 配置部分
# 使能状态机控制信号。该引脚控制数据端口总线方向。
# 逻辑低电平选择 RX 方向,逻辑高电平选择 TX 方向。
# 引脚名称:TXNRX
set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS25} [get_ports GPIO_O_0[0]]
# 控制输入信号。用于在各种运行状态之间切换。
# 引脚名称:ENABLE
set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS25} [get_ports GPIO_O_0[1]]
# 异步复位信号。逻辑低电平复位 AD9364 器件。
# 引脚名称:RESETB
set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS25} [get_ports GPIO_O_0[2]]
# 用于同步多个 AD9364 器件之间数字时钟的输入信号。
# 若未使用此引脚,则将其接地。
# 引脚名称:SYNC_IN
set_property -dict {PACKAGE_PIN J19 IOSTANDARD LVCMOS25} [get_ports GPIO_O_0[3]]
# 自动增益控制 (AGC) 的手动控制输入信号。
# 引脚名称:EN_AGC
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS25} [get_ports GPIO_O_0[4]]
5. 启动系统
正常启动后,会在日志中读取到AD9361 的配置信息,如图所示:
启动完成后,查看IIO下挂载的设备信息,ls /sys/bus/iio/devices/ ,顺利的话,你应该能看到在 iio:deviceX 目录下的产品信息,其中 X 是设备编号。AD9361 的设备节点通常会包含以下信息:
/sys/bus/iio/devices/iio:deviceX/in_voltage_rf_bandwidth
/sys/bus/iio/devices/iio:deviceX/out_voltage_rf_bandwidth
如图所示:
可以看到ad9361 驱动已经成功挂载,in 代表配置ad9361的文件,out 代表读取ad9361 信息的文件。可以读取到当前RX 的中频为2.4G。
参考网站:AD9361 高性能、高度集成的 RF 捷变收发器™ Linux 器件驱动程序 [Analog Devices Wiki]