未调用 Linux 自定义设备驱动程序探测和初始化函数

如何解决未调用 Linux 自定义设备驱动程序探测和初始化函数

我在 Vivado 中为 Xilinx SoC 板构建了一个自定义硬件配置,并使用 petalinux 创建了一个自定义驱动程序来控制硬件逻辑。似乎在运行 insmod 命令后,驱动程序永远不会被初始化,也不会调用 ->probe() 函数。

我是这个域的新手,想知道是否有人遇到过类似的问题,并有一些关于检查位置和检查内容的指示,以便查看问题所在。任何建议都会非常有帮助!

将驱动程序插入内核后运行dmesg命令:

root@plzwork3:/proc/device-tree/amba_pl@0/simpleMultiplier@a0000000# dmesg 
[ 3351.680317] <1>Hello module world.
[ 3351.683735] <1>Module parameters were (0xdeadbeef) and "default"

Vivado 创建的设备树实体:

/ {
    amba_pl: amba_pl@0 {
        #address-cells = <2>;
        #size-cells = <2>;
        compatible = "simple-bus";
        ranges ;
        simpleMultiplier_0: simpleMultiplier@a0000000 {
            clock-names = "axiliteregport_aclk";
            clocks = <&zynqmp_clk 71>;
            compatible = "xlnx,simpleMultiplier-1.0";
            reg = <0x0 0xa0000000 0x0 0x10000>;
            xlnx,axiliteregport-addr-width = <0x4>;
            xlnx,axiliteregport-data-width = <0x20>;
        };
    };
}; 

设备驱动程序代码片段:

#ifdef CONFIG_OF
static struct of_device_id simpmod_of_match[] = {
    { .compatible = "xlnx,simpleMultiplier-1.0",},{ /* end of list */ },};

完整的设备驱动代码:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>

#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

#include <linux/uaccess.h>
#include <linux/cdev.h>
#include <linux/fs.h>

/* Standard module information,edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
    ("Xilinx Inc.");

MODULE_DESCRIPTION("simpmod - loadable module template generated by petalinux-create -t modules");
#define DRIVER_NAME "simpmod"
#define CLASS_NAME "CLASS_TUT"

static char ker_buf[100];
static int currLen = 0;
// Parts of the math operation (2,2,+) is 2+2
static int operand_1 = 0;
static int operand_2 = 0;
static int result = 0;
static struct class *driver_class = NULL;
static dev_t first;
static struct cdev c_dev; // Global variable for the character device
static struct device *ourDevice;

// Pointer to the IP registers
volatile unsigned int *regA;
volatile unsigned int *regB;
volatile unsigned int *regC;

// Structure to hold device specific data
struct simpmod_local {
    int irq;
    unsigned long mem_start;
    unsigned long mem_end;
    void __iomem *base_addr;
};

// Character callbacks prototype
static int dev_open(struct inode *inod,struct file *fil);
static ssize_t dev_read(struct file *fil,char *buf,size_t len,loff_t *off);
static ssize_t dev_write(struct file *fil,const char *buf,loff_t *off);
static int dev_release(struct inode *inod,struct file *fil);


static struct file_operations fops = {
        .read=dev_read,.write=dev_write,.open=dev_open,.release=dev_release,};

static irqreturn_t simpmod_irq(int irq,void *lp){
    printk("simpmod interrupt\n");
    return IRQ_HANDLED;
}

static int simpmod_probe(struct platform_device *pdev){
    struct resource *r_irq; /* Interrupt resources */
    struct resource *r_mem; /* IO mem resources */
    struct device *dev = &pdev->dev;
    static struct simpmod_local *lp = NULL;
    int rc = 0;

    printk("Device Tree Probing\n");

    // Get data of type IORESOURCE_MEM(reg-addr) from the device-tree
    // Other types defined here:
    // http://lxr.free-electrons.com/source/include/linux/ioport.h#L33
    r_mem = platform_get_resource(pdev,IORESOURCE_MEM,0);
    if (!r_mem) {
        dev_err(dev,"invalid address\n");
        return -ENODEV;
    }

    // Allocate memory (continuous physical)to hold simpmod_local struct
    lp = (struct simpmod_local *) kmalloc(sizeof(struct simpmod_local),GFP_KERNEL);
    if (!lp) {
        printk("Cound not allocate simpmod device\n");
        return -ENOMEM;
    }

    dev_set_drvdata(dev,lp);

    // Save data on simpmod_local strucutre
    lp->mem_start = r_mem->start;
    lp->mem_end = r_mem->end;

    // Ask the kernel the memory region defined on the device-tree and
    // prevent other drivers to overlap on this region
    // This is needed before the ioremap
    if (!request_mem_region(lp->mem_start,lp->mem_end - lp->mem_start + 1,DRIVER_NAME)) {
        dev_err(dev,"Couldn't lock memory region at %p\n",(void *)lp->mem_start);
        rc = -EBUSY;
        goto error1;
    }

    // Get an virtual address from the device physical address with a
    // range size: lp->mem_end - lp->mem_start + 1
    lp->base_addr = ioremap(lp->mem_start,lp->mem_end - lp->mem_start + 1);
    if (!lp->base_addr) {
        dev_err(dev,"simpmod: Could not allocate iomem\n");
        rc = -EIO;
        goto error2;
    }
    // ****************** NORMAL Device diver *************************
    // register a range of char device numbers
    if (alloc_chrdev_region(&first,1,"Leonardo") < 0){
        printk(KERN_ALERT "alloc_chrdev_region failed\n");
        return -1;
    }

    // Create class (/sysfs)
    driver_class = class_create(THIS_MODULE,CLASS_NAME);
    if (driver_class == NULL) {
        printk(KERN_ALERT "Create class failed\n");
        unregister_chrdev_region(first,1);
        return -1;
    }

    ourDevice = device_create(driver_class,NULL,first,"tutDevice");
    if ( ourDevice == NULL){
        printk(KERN_ALERT "Create device failed\n");
        class_destroy(driver_class);
        unregister_chrdev_region(first,1);
        return -1;
    }

    // Create a character device /dev/tutDevice
    cdev_init(&c_dev,&fops);
    if (cdev_add(&c_dev,1) == -1){
        printk(KERN_ALERT "Create character device failed\n");
        device_destroy(driver_class,first);
        class_destroy(driver_class);
        unregister_chrdev_region(first,1);
    return -1;petalinux-config -c rootfs
    }

    // Create the attribute file on /sysfs/class/CLASS_TUT/ called
    // parCrtl and isBusy


    // Get data of type IORESOURCE_IRQ(interrupt) from the device-tree
    r_irq = platform_get_resource(pdev,IORESOURCE_IRQ,0);
    if (!r_irq) {
        printk("no IRQ found\n");
        printk("simpmod at 0x%08x mapped to 0x%08x\n",(unsigned int __force)lp->mem_start,(unsigned int __force)lp->base_addr);

        // Configuring pointers to the IP registers
        regA = (unsigned int __force)lp->base_addr + 0x10;
        regB = (unsigned int __force)lp->base_addr + 0x18;
        regC = (unsigned int __force)lp->base_addr + 0x26;
        printk("regA: 0x%08x\n",(unsigned int)regA);
        printk("regB: 0x%08x\n",(unsigned int)regB);
        printk("regC: 0x%08x\n",(unsigned int)regC);
        return 0;
    }
    lp->irq = r_irq->start;

    rc = request_irq(lp->irq,&simpmod_irq,DRIVER_NAME,lp);
    if (rc) {
        dev_err(dev,"testmodule: Could not allocate interrupt %d.\n",lp->irq);
        goto error3;
    }
    return 0;
error3:
    free_irq(lp->irq,lp);
error2:
    release_mem_region(lp->mem_start,lp->mem_end - lp->mem_start + 1);
error1:
    kfree(lp);
    dev_set_drvdata(dev,NULL);
    return rc;
}

static int simpmod_remove(struct platform_device *pdev){
    struct device *dev = &pdev->dev;
    struct simpmod_local *lp = dev_get_drvdata(dev);
    free_irq(lp->irq,lp);
    release_mem_region(lp->mem_start,lp->mem_end - lp->mem_start + 1);
    kfree(lp);
    dev_set_drvdata(dev,NULL);
    return 0;
}

// Indicate which type of hardware we handle on this case(simpleAlu-1.0)
#ifdef CONFIG_OF
static struct of_device_id simpmod_of_match[] = {
    { .compatible = "xlnx,};
MODULE_DEVICE_TABLE(of,simpmod_of_match);
#else
# define simpmod_of_match
#endif


static struct platform_driver simpmod_driver = {
    .driver = {
        .name = DRIVER_NAME,.owner = THIS_MODULE,.of_match_table = simpmod_of_match,.probe      = simpmod_probe,.remove     = simpmod_remove,};

static int __init simpmod_init(void)
{
    printk("<1>Simple device driver.\n");
  printk("Hussam was here,and he init the module\n");

    return platform_driver_register(&simpmod_driver);
}

static void __exit simpmod_exit(void)
{
    platform_driver_unregister(&simpmod_driver);
    printk(KERN_ALERT "Goodbye module world.\n");
}

static int dev_open(struct inode *inod,struct file *fil){
    printk(KERN_ALERT "Character device opened\n");
    return 0;
}

// Just send to the user a string with the value of result
static ssize_t dev_read(struct file *fil,loff_t *off){
    // Return the result only once (otherwise a simple cat will loop)
    // Copy from kernel space to user space
    printk(KERN_ALERT "Reading device rx: %d\n",(int)len);
    int n = sprintf(ker_buf,"%d\n",*regC);
    // Copy back to user the result (to,from,size)
    copy_to_user(buf,ker_buf,n);
    printk(KERN_ALERT "Returning %s rx: %d\n",n);
    return n;
}

// Parse the input stream ex: "50,*" to some operand variables.
static ssize_t dev_write(struct file *fil,loff_t *off){
    // Get data from user space to kernel space
    copy_from_user(ker_buf,buf,len);
    sscanf (ker_buf,"%d,%d,%c",&operand_1,&operand_2);
    ker_buf[len] = 0;
    // Change the IP registers to the parsed operands (on rega and regb)
    *regA = (unsigned int)operand_1;
    *regB = (unsigned int)operand_2;
    printk(KERN_ALERT "Receiving math operation <%d %d>\n",operand_1,operand_2);
    return len;
}

static int dev_release(struct inode *inod,struct file *fil){
    printk(KERN_ALERT "Device closed\n");
    return 0;
}

module_init(simpmod_init);
module_exit(simpmod_exit);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res