xilinx zynq7000, ad9361与spi驱动移植问题

心上枫叶红 心上枫叶红 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
各位大神请教一下。我用的是xilinux zynq7000的板子。我现在,需要移植SPI驱动和ADI的AD9361驱动进去。添加spidev.c驱动执行到init函数之后probe函数就没执行了。在/sys/bus/spi/drivers目录下有spidev驱动。但是/dev目录下一直没有设备文件。而且ad9361编译之后在报错好像就是因为是spi驱动的问题。我想知道这是怎么回事?谢谢
spidev.c的部分驱动
static int spidev_probe(struct spi_device *spi)
{
printk("========================enter spi0_probe======================\n");
struct spidev_data *spidev;
int status;
unsigned long minor;

/*
* spidev should never be referenced in DT without a specific
* compatible string, it is a Linux implementation thing
* rather than a description of the hardware.
*/
if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n");
WARN_ON(spi->dev.of_node &&
!of_match_device(spidev_dt_ids, &spi->dev));
}



/* Allocate driver data */
spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
if (!spidev)
return -ENOMEM;

/* Initialize the driver data */
spidev->spi = spi;
spin_lock_init(&spidev->spi_lock);
mutex_init(&spidev->buf_lock);

INIT_LIST_HEAD(&spidev->device_entry);

/* If we can allocate a minor number, hook up this device.
* Reusing minors is fine so long as udev or mdev is working.
*/
mutex_lock(&device_list_lock);
minor = find_first_zero_bit(minors, N_SPI_MINORS);
if (minor < N_SPI_MINORS) {
struct device *dev;

spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
dev = device_create(spidev_class, &spi->dev, spidev->devt,
spidev, "spidev%d.%d",
spi->master->bus_num, spi->chip_select);
status = PTR_ERR_OR_ZERO(dev);
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
status = -ENODEV;
}
if (status == 0) {
set_bit(minor, minors);
list_add(&spidev->device_entry, &device_list);
}
mutex_unlock(&device_list_lock);

spidev->speed_hz = spi->max_speed_hz;

if (status == 0)
spi_set_drvdata(spi, spidev);
else
kfree(spidev);

return status;
}

static int spidev_remove(struct spi_device *spi)
{
struct spidev_data *spidev = spi_get_drvdata(spi);
printk("========================enter spi remove======================\n");
/* make sure ops on existing fds can abort cleanly */
spin_lock_irq(&spidev->spi_lock);
spidev->spi = NULL;
spin_unlock_irq(&spidev->spi_lock);

/* prevent new opens */
mutex_lock(&device_list_lock);
list_del(&spidev->device_entry);
device_destroy(spidev_class, spidev->devt);
clear_bit(MINOR(spidev->devt), minors);
if (spidev->users == 0)
kfree(spidev);
mutex_unlock(&device_list_lock);

return 0;
}

static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.of_match_table = of_match_ptr(spidev_dt_ids),
},
.probe = spidev_probe,
.remove = spidev_remove,
/* NOTE: suspend/resume methods are not necessary here.
* We don't do anything except pass the requests to/from
* the underlying controller. The refrigerator handles
* most issues; the controller driver handles the rest.
*/
};

/*-------------------------------------------------------------------------*/

static int __init spidev_init(void)
{
int status;

/* Claim our 256 reserved device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* the driver which manages those device numbers.
*/
BUILD_BUG_ON(N_SPI_MINORS > 256);
status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
if (status < 0)
return status;

spidev_class = class_create(THIS_MODULE, "spidev");
if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
return PTR_ERR(spidev_class);
}
status = spi_register_driver(&spidev_spi_driver);
if (status < 0) {
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
printk("==============:%d:==========spi0_init out ======================\n",status);
return status;
}
module_init(spidev_init);
内核打印信息::
bootconsole [earlycon0] disabled
bootconsole [earlycon0] disabled
xdevcfg f8007000.devcfg: ioremap 0xf8007000 to f08b0000
[drm] Initialized drm 1.1.0 20060810
brd: module loaded
loop: module loaded
==============:0:==========spi0_init out ======================
m25p80 spi0.0: SPI-NOR-UniqueID 0000000000000000000000000000000000
m25p80 spi0.0: m25p80 (2048 Kbytes)
4 ofpart partitions found on MTD device spi0.0
Creating 4 MTD partitions on "spi0.0":
0x000000000000-0x000000500000 : "boot"
mtd: partition "boot" extends beyond the end of device "spi0.0" -- size truncated to 0x200000
0x000000500000-0x000000520000 : "bootenv"
mtd: partition "bootenv" is out of reach -- disabled
0x000000520000-0x000000fa0000 : "kernel"
mtd: partition "kernel" is out of reach -- disabled
0x000000fa0000-0x000000200000 : "spare"
mtd: partition "spare" is out of reach -- disabled
CAN device driver interface
libphy: MACB_mii_bus: probed
macb e000b000.ethernet eth0: Cadence GEM rev 0x00020118 at 0xe000b000 irq 146 (00:0a:35:00:1e:53)
Generic PHY e000b000.etherne:00: attached PHY driver [Generic PHY] (mii_bus:phy_addr=e000b000.etherne:00, irq=-1)
e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-pci: EHCI PCI platform driver
usbcore: registered new interface driver usb-storage
mousedev: PS/2 mouse device common for all mice
i2c /dev entries driver
EDAC MC: ECC not enabled
Xilinx Zynq CpuIdle Driver started
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
mmc0: SDHCI controller on e0101000.sdhci [e0101000.sdhci] using ADMA
ledtrig-cpu: registered to indicate activity on CPUs
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
ad9361 spi32766.0: ad9361_probe : enter (ad9361)
ad9361 spi32766.0: ---------------gpio:0--------------------------!
ad9361 spi32766.0: --------------------------1----------------!
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Write Error -110
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Write Error -110
ad9361 spi32766.0: ad9361_reset: by SPI, this may cause unpredicted behavior!
ad9361 spi32766.0: SPI transfer timed out
ad9361 spi32766.0: Read Error -110
ad9361 spi32766.0: ad9361_probe : Unsupported PRODUCT_ID 0xFFFFFF92
NET: Registered protocol family 10
sit: IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
can: controller area network core (rev 20120528 abi 9)
NET: Registered protocol family 29
can: raw protocol (rev 20120528)
can: broadcast manager protocol (rev 20120528 t)
can: netlink gateway (rev 20130117) max_hops=1
zynq_pm_remap_ocm: OCM pool is not available
zynq_pm_suspend_init: Unable to map OCM.
Registering SWP/SWPB emulation handler
hctosys: unable to open rtc device (rtc0)

这里ad9361的部分驱动代码:
static int ad9361_reset(struct ad9361_rf_phy *phy)
{

dev_err(&phy->spi->dev, " ---------------gpio:%d--------------------------!\n",phy->pdata->reset_gpio);
if (phy->pdata->reset_gpio) {
dev_err(&phy->spi->dev, " --------------------------in----------------!\n");
gpiod_set_value(phy->pdata->reset_gpio, 0);
mdelay(1);
gpiod_set_value(phy->pdata->reset_gpio, 1);
mdelay(1);
dev_dbg(&phy->spi->dev, "%s: by GPIO", __func__);
return 0;
}
dev_err(&phy->spi->dev, " --------------------------1----------------!\n");

/* SPI Soft Reset was removed from the register map, since it doesn't
* work reliably. Without a prober HW reset randomness may happen.
* Please specify a RESET GPIO.
*/

ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET);
ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0);
dev_err(&phy->spi->dev,
"%s: by SPI, this may cause unpredicted behavior!", __func__);

return -ENODEV;
}

static int ad9361_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
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);

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;

phy = iio_priv(indio_dev);
phy->indio_dev = indio_dev;
phy->spi = spi;
phy->clk_refin = clk;

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);


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);
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);


phy->current_table = -1;
phy->bypass_tx_fir = true;
phy->bypass_rx_fir = true;
phy->rate_governor = 1;
phy->rfdc_track_en = true;
phy->bbdc_track_en = true;
phy->quad_track_en = true;

phy->gt_info = ad9361_adi_gt_info;

ad9361_request_gt(phy, NULL);

ad9361_reset(phy);


ret = ad9361_spi_read(spi, REG_PRODUCT_ID);
if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) {
dev_err(&spi->dev, "%s : Unsupported 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;
}
.....................................
...全文

相关推荐

超扭滑模与快速终端滑模的永磁同步电机无感控制:理论、离散化实现与仿真研究(Simulink仿真实现)

内容概要:本文聚焦于超扭滑模控制(STSMC)与快速终端滑模控制(FTSMC)在永磁同步电机(PMSM)无位置传感器控制中的应用,系统地开展了理论分析、离散化实现与Simulink仿真实验研究。重点探讨了这两种高阶滑模控制策略在零低速工况下的控制性能,通过设计基于磁链观测器的无感估计算法,实现了对电机转子位置与速度的精确估计,有效规避了传统机械传感器带来的成本增加与可靠性下降问题。文中详尽阐述了控制算法的数学建模与推导过程,并针对数字控制系统的特点进行了严谨的离散化处理,最终在Simulink环境中搭建了完整的电机控制仿真模型,通过对比实验全面评估了不同控制策略在动态响应速度、抗外部干扰能力和稳态控制精度等方面的综合性能。; 适合人群:具备自动控制理论、电机驱动原理等专业知识,并熟悉MATLAB/Simulink仿真环境操作的电气工程、自动化等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入研究超扭滑模与快速终端滑模等高阶滑模控制理论在高性能电机驱动系统中的具体应用与实现方法;②掌握永磁同步电机在零低速段无位置传感器控制的核心算法,特别是基于磁链观测的转子状态估算技术;③学习如何将连续域的先进控制理论转化为适用于实际数字控制器的离散化算法,并完成从理论到仿真的完整闭环验证。; 阅读建议:此文理论深度与实践操作紧密结合,读者应重点关注控制算法的设计思想、离散化实现的关键步骤以及Simulink仿真模型的构建细节,建议在阅读过程中动手复现仿真模型,通过调整控制器参数来深入理解各模块的功能作用及系统整体的动静态性能表现。

荔枝科研社

政府如何精准掌握园区企业创新能力,以制定更有效的科技政策?.docx

政府如何精准掌握园区企业创新能力,以制定更有效的科技政策?

BIZKEEN

旋转高频信号注入法在PMSM零低速无位置控制中的仿真研究(Matlab代码实现)

内容概要:本文围绕旋转高频信号注入法在永磁同步电机(PMSM)零低速无位置传感器控制中的应用展开深入的仿真研究,基于Matlab/Simulink平台构建完整的控制系统模型,系统阐述了高频信号注入法的理论基础、转子位置观测机制及整体控制策略设计。重点探讨了在零低速运行工况下,通过注入旋转高频电压信号并结合先进的信号处理技术(如带通滤波、坐标变换、锁相环等)有效提取转子位置信息的技术路径,成功克服了传统反电动势法在极低速时信号微弱、无法准确观测的固有缺陷。研究详细分析了高频响应信号的调制解调过程、位置估算环路的动态特性,并考察了电机参数漂移、外部干扰等因素对系统鲁棒性与估计精度的影响,通过大量仿真实验验证了该方法在提升位置观测准确性、增强系统抗干扰能力方面的显著优势。; 适合人群:具备电机控制、电力电子及自动控制理论基础,熟悉Matlab/Simulink仿真环境,从事PMSM驱动系统开发或无位置传感器控制算法研究的研发人员,特别适合电气工程、自动化等相关专业的研究生及具有1-5年工作经验的工程师。; 使用场景及目标:①深入掌握旋转高频信号注入法在PMSM无感控制中的实现原理、关键技术环节与工程实现难点;②学习并实践基于Matlab/Simulink的先进电机控制算法仿真建模、信号处理与性能分析方法;③为解决实际工程中电机在零速启动、低速精确控制等场景下的位置传感器依赖问题,提供有效的技术方案参考与系统的仿真验证手段。; 阅读建议:此资源以Matlab代码实现为核心载体,建议读者在学习过程中紧密结合提供的文档说明与仿真模型,逐模块剖析高频信号发生器、注入策略、响应信号解调、位置估算器等关键环节的设计原理,通过修改系统参数、设置不同工况进行仿真实验,深入理解算法内部机理与系统动态响应特性之间的关联。

逝川长叹

【高速串行通信】基于S参数去嵌与信道劣化建模的PCIe链路表征:物理层测试中发射机与接收机性能验证方法研究

内容概要:本文围绕PCI Express通道在信道退化情况下的表征方法展开,重点介绍了物理层测试中的关键技术与流程。文章详细阐述了如何通过S参数提取和去嵌入(de-embedding)技术,将测量结果还原至发送端或接收端引脚,以准确评估信号完整性;同时探讨了合规性通道的嵌入、接收端均衡(如CTLE/DFE)对闭合眼图的恢复效果,以及如何生成带有预加重、去加重、抖动损伤和信道仿真的接收端测试信号。此外,还分析了短通道实例的测试结果,并强调高质量PCB设计和S参数数据对去嵌入精度的重要性。; 适合人群:从事高速接口设计、信号完整性分析或PCIe相关芯片开发的工程师,具备一定电磁场理论和高速数字电路基础的研发人员; 使用场景及目标:①用于精确表征PCIe链路在真实信道退化条件下的性能表现;②支持接收端容限测试与合规性验证,提升系统鲁棒性; 阅读建议:本资料适用于需要深入理解PCIe物理层测试机制的技术人员,建议结合实际测试工具(如示波器、通道仿真软件)进行实践操作,重点关注S参数获取、去嵌入设置及均衡后信号分析等关键步骤。

Kernel_RDMA

MATLAB实现了可移动天线,实现了ISCC的总速率优化。.zip

1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

海神之光
评论 11
收藏 已收藏
分享
返回顶部