驱动中platform resource 和 porbe 之间的关系

Altera CPLD maxII 的 JTAG 编程 最近在调试JTAG,通过对ATOM的GPIO 操作,把ATOM的GPIO口模拟成JTAG信号,然后把CPLD的firmware,从ATOM平台烧进CPLD中。 这里主要是使用了Altera的 STAPL工具, 叫jamplayer, 这是一个开源的工具,再source下,直接make就能生成jamplayer工具。 还需要在quartusII中把xxx.pof 格式的CPLD firmware 阅读详情

1. platform_device 会包含platform_data 和 resource定义:

一般platform device信息,会定义在 arch/arm/mach-xxx/board-xxx.c 中。

如这里的sarac模块,被定义在arch/arm/mach-cartesio/core-sta2065.c中

static struct platform_device sarac_device = {
        .name           = "cartesio-sarac",
        .id             = 1,
        .dev = {
                .init_name = "cartesio-sarac",
                 //设备中包含的 platform数据 
                .platform_data = &sarac_platform_data,
        },
        .num_resources  = ARRAY_SIZE(sarac_resource),
         //包含的资源
        .resource       = sarac_resource,
  };

这里的 .name 很重要,驱动会根据这个名字,在probe的时候进行匹配,如果有名字相同,就会匹配上。

platform_device 的定义如下:

struct platform_device {
        const char      * name;
        int             id;
        struct device   dev;
        u32             num_resources;
        struct resource * resource;
        
        const struct platform_device_id *id_entry;
        
        /* arch specific additions */
        struct pdev_archdata    archdata;
};      
他包含了一个设备dev,还有resource. 这些都是platform的优势,可以包含很多信息。

如上面的sarac_device,就包含了sarac_platform_data 和 sarac_resource 两块内容,具体定义如下:

static struct sarac_platform_data_container sarac_platform_data = {
        //这个platform data 其实就是一个DMA slave 的定义
        .mem2sarac_slave = {
                .dma_dev        = &dma0_device.dev,     /* SARAC bound to DMA0 */
                .tx_req_line    = DMA0_REQ_SRC_DMA_DRE,
                .rx_req_line    = DMA0_REQ_SRC_DMA_DRF,
                .nr_descs       = 2048,
                .channel        = DMA_CHANNEL_AUTO,
                .slave_width    = DMA_TRANSFER_WIDTH_32BIT,
                .flow_ctrlr     = DMA_FLOW_CONTROLLER_DMA,
                .burst_size     = DMA_BURST_SIZE_1,     /* fifo packet size */
                .ahb_master     = DMA_AHB_MASTER_0,
        },
};
static struct resource sarac_resource[] = {
        //resource 包含了两块,一块是寄存器访问地址, 一块是中断号信息
        [0] = {
                .start  = CARTESIO_SARAC_BASE,
                .end    = CARTESIO_SARAC_BASE + SZ_4K - 1,
                .name   = "SaRaC registers",
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
                .start  = IRQ_SARAC_DRF,
                .end    = IRQ_SARAC_DRF,
                .name   = "CartesioPlus SaRaC interrupt",
                .flags  = IORESOURCE_IRQ,
        },
};      
2.  驱动probe中对platform的使用

模块加载时,会注册platform driver: 也就是 platform_driver_register()函数;

static int __init cartesio_sarac_init(void)
{
        return platform_driver_register(&cartesio_sarac_driver);
}
module_init(cartesio_sarac_init);
cartesio_sarac_driver的定义如下:

static struct platform_driver cartesio_sarac_driver = {
        .probe          = cartesio_sarac_probe,
        .remove         = __devexit_p(cartesio_sarac_remove),
        .driver = {
                .name   = DEVICE_NAME,
                .owner  = THIS_MODULE,
        },
};
这里的.name 定义必须跟之前platform定义中的.name 一致,这样platform驱动和设备才能匹配上。

/*
 * Asynchronous SaRaC device name
 */
#define DEVICE_NAME     "cartesio-sarac"
该驱动被加载时,会自动运行cartesio_sarac_probe 函数:
static int __devinit cartesio_sarac_probe(struct platform_device *pdev)
{
        struct sarac_device_data *sarac_device;
        struct resource *res;
        struct sarac_platform_data_container *sarac_plat_data=NULL;

        int ret;

        sarac_device = kzalloc(sizeof(struct sarac_device_data), GFP_KERNEL);
        if (!sarac_device) {
                dev_err(&pdev->dev, "not enough memory for driver status\n");
                return -ENOMEM;
        }

        //通过这个函数,就把 platform_device 中的内容,赋给 sarac_device,就可以在这驱动中使用了
        //这里的pdev 就是指向platform_device的指针。
        platform_set_drvdata(pdev, sarac_device);

        printk("SARAC probe called\n");

        //该函数用来获取platform中的resource资源
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "register area not defined\n");
                ret = -ENODEV;
                goto out_free;
        }

        //把IO空间,赋值给sarac_device
        sarac_device->base_addr = ioremap(res->start, resource_size(res));
        if (!sarac_device->base_addr) {
                dev_err(&pdev->dev, "unable to remap register area\n");
                ret = -ENODEV;
                goto out_free;
        }

        //把platform_device->dev.platform_data 赋值过来
        sarac_plat_data = pdev->dev.platform_data;

        if (sarac_plat_data->mem2sarac_slave.dma_dev) {
                sarac_device->dma_to_sarac_client = &sarac_plat_data->mem2sarac_slave;

                sarac_device->dma_to_sarac_client->tx_reg = res->start + SARAC_DILR;

                sarac_device->dma_from_sarac_address = res->start + SARAC_DOLR;

        } else {
                dev_err(&pdev->dev, "DMA info not found in platform data\n");
                ret = -1;
                goto dma_err;
        }

        //把platform_device 中的IRQ 信息赋值过来
        sarac_device->irq = platform_get_irq(pdev, 0);

        //注册中断
        ret = request_irq(sarac_device->irq, cartesio_sarac_irq_handler, 0,
                                         dev_name(&pdev->dev), &pdev->id);
        if (ret) {
                dev_err(&pdev->dev, "failed to allocate IRQ %d\n", sarac_device->irq);
                goto out_unmap;
        }
        else {
                aab_peripheral_enable(AAB_SARAC, AAB_AC_WRITE | AAB_AC_READ);
        }

        //在sys中创建信息接口
        sarac_kobj = kobject_create_and_add("audio_sarac", NULL);
        if (!sarac_kobj)
                return -ENOMEM;

        ret = sysfs_create_group(sarac_kobj, &cartesio_sarac_attr_group);
        if (ret)
                return ret;

        dev_info(&pdev->dev, "Module initialized, version" DRV_VERSION  "\n");
        return 0;

dma_err:
out_unmap:
        iounmap(sarac_device->base_addr);
out_free:
        kfree(sarac_device);
        return ret;
}











mmap读写/dev/mem设备,可用于读取物理内存内容 mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍,面向流的设备不能进行mmap,mmap的实现和硬件有关。 mmap原型: #include void *mmap(void *start, size_t length, int prot, int flags 阅读详情

相关推荐

Screenshot_2026-11-03-16-23-09-34.jpg

Screenshot_2026-11-03-16-23-09-34.jpg

Linux驱动开发笔记(十三)——platform设备驱动

(本次实验只需要用到name和of_match_table)// 定义在include/linux/device.h// 驱动名,在没有设备树的情况下用于和设备匹配。// 用于有设备树时的匹配// 定义在include/linux/mod_devicetable.h// 用于和设备树中的节点的compatible属性进行匹配3.2.2 注册和卸载// 定义在include\linux\platform_device.h。

qq_56920196的博客 842

研发流程后端开发工具,提示功能开发效率

后端开发工具

队列 -- fifo

linux 内核通用队列称为 kfifo.  定义于中 linux 的 kfifo 和多数其他队列一样,也提供了两个主要函数,enqueue(入队列) 和 dequeue(出队列) kfifo 对象 维护了两个偏移量,入口偏移 和 出口偏移。 入口偏移 指下一次入队列时的位置 出口偏移 指下一次出队列的位置。 出口偏移 总是小于等于 入口偏移,否则就意味着要出队列的元素根本没有入队列。

1182

机器人具有扰动抑制功能的有限时间基于方位角的领航者-跟随者编队控制(Matlab代码实现)

内容概要:本文档标题为《Plecs全桥LLC谐振变换器仿真模型.txt》,但实际内容并未涉及该主题的具体技术细节或仿真建模过程。相反,文档实质是一份由科研服务团队发布的跨学科资源目录,集中展示了大量基于Matlab、Simulink、Python、PSCAD等平台实现的科研项目与算法开发案例,涵盖电力系统、无人机路径规划、微电网优化、状态估计、信号处理、车间调度、图像处理、通信技术、雷达追踪、智能优化算法等多个工程技术领域。每个条目以“【】”标注研究主题,并注明“Matlab代码实现”“Python代码实现”等形式,表明其为可提供技术支持与代码资源的服务项目。文档末尾频繁出现“完整资源下载:公众号——荔枝科研社”及百度网盘链接,明确体现出其作为科研辅助服务推广与引流工具的功能属性。; 适合人群:面向电气工程、自动化、控制科学与工程、计算机科学、智能制造、新能源、航空航天、通信工程及相关交叉学科的研究生、高校教师、科研人员及企业研发工程师。; 使用场景及目标:①为科研人员提供课题选题、技术路线设计与算法实现的参考范例;②辅助学生或研究人员完成课程设计、毕业论文、项目仿真与算法复现任务;③作为第三方技术服务团队的能力展示目录,便于潜在客户快速了解其在多领域提供的定制化仿真与算法开发服务范围。; 阅读建议:此文档并非传统意义上的学术论文或技术教程,而是一份高度碎片化、广告性质浓厚的资源索引清单。读者应忽略其误导性的文件名,将其视为一个综合性科研技术服务目录,重点关注自身研究方向相关的条目,并通过文末提供的公众号或网盘链接进一步获取具体代码与资料。同时,需注意甄别资源的技术质量、原创性与适用性,避免盲目依赖外部服务。

基于RK3588与Gstreamer的端侧实时视频流AI推理系统构建

本文详细介绍了基于RK3588芯片与Gstreamer框架构建端侧实时视频流AI推理系统的完整方案。通过硬件选型、环境配置、OpenCV编译优化、视频流处理实战及模型部署等关键环节的深入解析,展示了如何利用RK3588的6TOPS NPU算力与Gstreamer的低延迟特性,实现工业质检、智能交通等场景下的高效边缘计算。特别针对RTSP推拉流优化、RKNN模型转换等核心技术难点提供了实用解决方案。

weixin_30516243的博客 381

uboot 和 kernel 中的分区修改

1.uboot中修改分区, 在/uboot/include/configs/pdk7105.h 中:   #ifdef CONFIG_CMD_NAND    /* NAND flash present ? */ # define CFG_MAX_NAND_DEVICE 1 # define NAND_MAX_CHIPS  CFG_MAX_NAND_DEVICE # define CFG

879

瑞萨MCU定时器API实战:从Smart Configurator配置到中断与输入捕获应用

在嵌入式系统开发中,定时器(Timer)是实现精准时序控制、PWM输出和信号测量的核心硬件外设。其工作原理基于计数器在稳定时钟源驱动下递增或递减,达到预设值后触发中断或改变输出电平,从而为系统提供节拍和事件基准。通过图形化配置工具(如瑞萨的Smart Configurator),开发者可以高效地将复杂的硬件寄存器操作转化为清晰、标准化的C语言API函数,这极大地提升了开发效率并降低了出错风险。这种从硬件抽象到软件接口的技术价值在于,它使得开发者能更专注于应用逻辑,而非底层细节,尤其适用于工业控制、汽车电子等

weixin_42519733的博客 274

模块的声明与描述

1. 模块的许可证明 (MODULE_LICENSE): 声明描述内核模块的许可权限。如果不声明LICENSE,模块被加载时,会收到内核被污染(kernel tainted)的警告。 linux2.6内核中,可接受的MODULE_LICENSE包括: "GPL" "GPL v2" "GPL and additional rights" "Dual BSD/GPL" "Dual MPL/

763

ContextCapture导入点云进行重建

ContextCapture导入点云进行重建

天桥飞熊的博客 1万+

别再为Word转PDF表格变形发愁了!Aspose.Words for Java 19.5 保姆级避坑指南

本文详细介绍了使用Aspose.Words for Java 19.5解决Word转PDF时表格变形问题的完整方案。从格式转换原理到实战技巧,涵盖固定表格宽度、禁用自动调整、强制文本换行等核心方法,并提供高级场景应对策略和性能优化建议,帮助开发者高效处理复杂文档转换需求。

weixin_28702105的博客 266

copy_from_user() and copy_to_user()

Defined in /arch/arm/include/asm/uaccess.h 1. copy_from_user() and copy_to_user() 调用了__*** static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned l

692

Nengo神经工程框架:脉冲神经网络的实时编译与硬件部署

脉冲神经网络(SNN)作为类脑计算的核心范式,正从生物模拟走向工程落地。其本质是用离散脉冲建模神经动力学,关键在于实现可预测、可复现的神经行为而非单纯拟合函数。Nengo基于神经工程学框架(NEF),将动态系统理论与硬件约束深度融合,通过解析式权重计算、确定性时间步长(dt)和多后端编译能力,支撑从CPU仿真到Loihi/FPGA的端到端部署。它不替代深度学习框架,而是提供面向神经形态芯片的‘神经编译器’能力,使LIF神经元参数、突触动力学与硬件时序严格对齐,显著提升实时性、能效比与物理可解释性。

weixin_32533659的博客 637

BSS段_数据段_代码段_堆_栈

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。 数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。 代码段:代码段(code segment/text segment)通常是指用

656

naca翼型_STARCCM+计算二维翼型气动性能

STAR-CCM+计算二维翼型气动性能一算例背景机翼理论主要研究翼型在流体中运动时的力学特性。在工程领域中,机翼以升力面、控制面、叶片或桨叶等形式出现。舰船上的舵、水翼、减摇鳍等都是机翼,螺旋桨、汽轮机叶片和压缩机叶片也都是利用机翼原理工作的,而在研究船舶操纵性时,甚至还可把船体的水下部分看作一个巨大的机翼。随着航空科学的发展,世界各主要航空发达的国家建立了各种翼型系列。美国有NACA系...

weixin_39863741的博客 1万+

信捷PLC XD5系列运动控制(10轴)编程应用篇

项目PLC采用XD5-60T10-E,36DI 24DO 晶体管输出,支持10路脉冲输出功能。TMR指令定时器时基可以自己设定,这点比其他品牌PLC方便。ZRN指令我们需要上升沿指令触发。 5、变址寻址 该说不说这个变址寻址是真的强,比西门子指针、三菱的变址寄存器Z 、V都要更加灵活。 7、特殊寄存器:时钟 8、如何建立PLC通讯...............

RXXW_Dor的博客 1万+

错误: 初始值设定项里有未知的字段‘ioctl’

这个错误网上搜索发现3.0.0.15版本内核 file_operation结构体已经删除了ioctl函数,取代的是: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); fi

593

vue2 - 详细实现播放AMR格式音频并实现自定义播放器样式,支持amr音频文件在线地址URL播放、调用服务端API接口获取二进制文件流amr形式、用户本地上传amr文件并实现立即播放(详细代码)

vue2,amr,amr文件播放,vue播放amr音频文件以及在线url跨域问题解决,vue使用audio标签播放amr音频,amr跨域解决,amr网页解码播放,文件上传后怎么播放,vue2播放.amr语音文件,api接口形式调用获取的amr如何播放,vue中如何使用audio元素播放AMR格式的文件,进度条,vue前端如何播放AMR格式的音频文件,vue播放语音文件AMR格式,播放amr格式音频AMR录音机,h5原生audio播放amr格式的音频,VUE2使用benz-amr-recorder 实现解码、

✅ 精选推荐文章 7415

printk _dmesg 打印显示等级

要将linux内核的带级别控制的printk内容打印出来,在命令行 输入 dmesg -n 8 就将所有级别的信息都打印出来 Linux命令:dmesg  功能说明:显示开机信息。   语 法:dmesg [-cn][-s ]   补充说明:kernel会将开机信息存储在ring buffer中。您若是开机时来不及查看信息,可利用dmesg来查看。开机信息亦保存在/var/log目录中,

563

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

返汇编-objdump

arm-none-linux-gnueabi-objdump -d vmlinux >111 objdump -d

546

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

导出符号 --- EXPORT_SYMBOL()

linux2.6的 /proc/kallsyms 文件对应着内核符号表,它记录了符号及符号的内存地址。 模块可以使用如下宏 导出符号到内核符号表: EXPORT_SYMBOL(name); EXPORT_SYMBOL_GPL(name); //只适用于包含GPL许可权的模块。 示例:export_symb.c 导出整数加,减运算函数符号的内核模块。 xxha@xxha-Op

542

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

模块参数 --- parameters

为模块定义一个参数: module_param(参数名,参数类型,参数读/写权限)   //可定义各种类型参数,该参数可由加载模块时,外部传入。 以下示例定义了一个整型参数和一个字符指针参数: static char *bookname = "dissecting linux device driver"; static int num = 4000; module_param(num, i

502

linux下错误的捕获:errno和strerror的使用

经常在调用linux 系统api 的时候会出现一些错误,比方说使用open() write() creat()之类的函数有些时候会返回-1,也就是调用失败,这个时候往往需要知道失败的原因。这个时候使用errno这个全局变量就相当有用了。     在程序代码中包含 #include ,然后每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量

417

module_param除了在加载模块时,另外一种传递参数的方法

module_param 最后的字段是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。 你应当使用 中定义的值,这个值控制谁可以存取这些模块参数在 sysfs 中的表示. 当perm为0时,表示此参数不存在 sysfs文件系统下对应的文件节点。 否则, 模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录, 带有给定的权限.。 sys/mo

406
上一篇: 一个把字符串变成16进制数的函数
下一篇: xloader bootlog access
lamdoc
博客等级 码龄18年 155粉丝 655原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值