petalinux-adi ---添加AD9361驱动(二)

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 的架构如下:

  1. FMCOMMS2:

采用单个AD9361芯片,提供双通道(2x2 MIMO)配置,即两个接收(RX)和两个发送(TX)通道。

  1. FMCOMMS5:

采用两个AD9361芯片,提供四通道(4x4 MIMO)配置,即四个接收(RX)和四个发送(TX)通道。这个设计允许进行更复杂的MIMO系统开发,如4x4 MIMO的无线通信系统。

本板卡对应的是adi-fmcomms2.dtsi文件,因此引用adi-fmcomms2.dtsi 文件并对其修改。

    1. 找到&fmc_spi结点,在其前面添加#define fmc_spi spi0,使fmc_spi等同于spi0 结点。
    2. 修改compatible 值为 "ad9361" (去掉adi)。
    3. 在 SPI Setup 中配置SPI 分频后的时钟,当前设置的是500K,可根据需要调整。
    4. 添加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]

相关推荐
C++忠实粉丝4 分钟前
多线程 - 自旋锁
linux
不想被吃掉氩2 小时前
linux-多线程
java·linux·运维·c++
哭哭啼2 小时前
Linux实现两台服务器之间ssh连接
linux·运维·ssh
网络安全Max2 小时前
Debian 10上使用UFW设置防火墙
linux·服务器·debian
ℳ₯㎕ddzོꦿ࿐2 小时前
在Linux上将 `.sh` 脚本、`.jar` 包或其他脚本文件添加到开机自启动
linux·运维·jar
等一场春雨2 小时前
linux 根据名称 杀死linux 上某个jar进程或其他进程
linux·pycharm·jar
helloasimo2 小时前
如何重新设置VSCode的密钥环密码?
linux·运维·服务器
c洛#3 小时前
Linux缓存管理:如何安全地清理系统缓存
linux·运维·缓存
redreamSo3 小时前
Docker Compose 日志管理:高效搜索与上下文查看指南
linux·后端·docker
小林熬夜学编程4 小时前
【Linux网络编程】第十三弹---构建HTTP响应与请求处理系统:从HttpResponse到HttpServer的实战
linux·运维·服务器·c语言·网络·c++·http