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

相关推荐
夜听莺儿鸣9 小时前
502-003_Linux 中断与异常(一):从Linux角度理解中断与异常
linux·中断与异常·linux中断
杨云龙UP10 小时前
TDengine 3.4.2.8 Community 三节点三副本生产集群部署实战(DNode/MNode/taosAdapter/Explorer)
大数据·linux·运维·数据库·tdengine·时序库
向成科技10 小时前
XC3576H工控主板|深度适配Ubuntu 26.04 LTS,释放边缘AI与工业开发新潜能
linux·人工智能·ubuntu·机器人·硬件·主板·边缘ai
Fcy64811 小时前
Linux下 进程间关系与守护进程
linux·运维·服务器·守护进程
码农小韩11 小时前
Linux驱动理论(二)——Linux字符设备驱动
linux·嵌入式软件开发·linux操作系统·linux应用开发·linux驱动理论
well061212 小时前
Linux粘滞位与Makefile机制深度解析
linux·运维·服务器
再写一行代码就下班12 小时前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
额额额对了12 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
子木HAPPY阳VIP12 小时前
Ubuntu 关闭防火墙操作步骤
linux·运维·ubuntu
王振超wzc13 小时前
嵌入式开发环境搭建--WM软件安装,Ubuntu操作系统安装
linux·运维·ubuntu