Platform_device_register向系统注册设备 Platform_driver_register向系统注册驱动过程中在系统寻找注册的设备(根据.name)找到后运行.probe进行初始化。 所以Platform_device_register必须先于Platform_driver_register执行。1. Platform_device_register执行流程。1)zx297520v3-device.c中zx29_device_table中定义了所有的设备#ifdef CONFIG_MTD_ZXIC_SPIFC static struct resource spi_nand_resource[] { [0] { .start ZX_SPIFC0_BASE, .end ZX_SPIFC0_BASE SZ_4K - 1, .flags IORESOURCE_MEM, .name spifc_reg, }, [2] { .start SPI_FC0_INT, .end SPI_FC0_INT, .flags IORESOURCE_IRQ, }, }; #endif#ifdef CONFIG_MTD_ZXIC_SPIFC struct platform_device zx29_device_spi_nand { .name spi-nand-dt, .id -1, .num_resources ARRAY_SIZE(spi_nand_resource), .resource spi_nand_resource, }; #endifstruct platform_device *zx29_device_table[] __initdata{ #ifdef CONFIG_SERIAL_ZX29_UART zx29_uart0_device, zx29_uart1_device, zx29_uart2_device, #endif #ifdef CONFIG_MTD_NAND_DENALI zx29_device_nand, #endif #ifdef CONFIG_DWC_OTG_USB zx29_usb0_device, #endif #ifdef CONFIG_USB_DWC_OTG_HCD zx29_usb1_device, #endif #ifdef CONFIG_MTD_ZXIC_SPIFC zx29_device_spi_nand, #endif #ifdef CONFIG_ZX29_DMA zx29_dma_device, #endif ...... }2)board-zx297520v3.c中board_init()函数中调用platform_add_devicesstatic void __init board_init(void) { ...... platform_add_devices(zx29_device_table, zx29_device_table_num); ...... }3)platform_add_devices中对table进行遍历调用platform_device_register进行注册int platform_add_devices(struct platform_device **devs, int num) { int i, ret 0; for (i 0; i num; i) { ret platform_device_register(devs[i]); if (ret) { while (--i 0) platform_device_unregister(devs[i]); break; } } return ret; }4)platform_device_register先调用device_initialize再调用platform_device_add device_initialize主要是初始化设备结构体包括kobject、mutex、spin_lock、list、pm初始化等方便后面的platform_device_add使用 platform_device_add中先调用insert_resource(p,r)将platform资源(上面截图的resource)添加进内核由内核进行统一管理然后再调用device_add()。2. Platform_driver_register执行流程。1)调用Platform_driver_register注册驱动static const struct of_device_id spifc_nand_dt_ids[] { { .compatible spifc,spifc-nand-dt }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, spifc_nand_dt_ids); static struct platform_driver spifc_dt_driver { .probe spifc_drv_probe, .remove spifc_drv_remove, .driver { .name spi-nand-dt, .owner THIS_MODULE, .of_match_table spifc_nand_dt_ids, }, }; module_platform_driver(spifc_dt_driver);module_platform_driver(xxx)最终展开后就是如下形式static int __init xxx_init(void){return platform_driver_register(xxx);}module_init(xxx_init);static void __exit xxx_init(void){return platform_driver_unregister(xxx);}module_exit(xxx_exit);2)platform_driver_register(xx_driver) 会向系统注册xx_driver这个驱动程序这个函数会根据 xx_driver中的.name内容搜索系统注册的device中有没有这个platform_device,如果有就会执行 platform_driver(也就是xx_driver的类型)中的.probe函数即上述截图的spifc_drv_probe()函数。I2C设备/驱动的注册1. 设备的注册1)zx297520v3-devices.c中定义了需要添加的I2C设备#ifdef CONFIG_MFD_ZX234290_I2C static struct zx234290_board zx234290_platform { .irq_gpio_num PIN_PMU_INT, //EX0_INT, .irq_gpio_func PMU_INT_FUNC_SEL, .pshold_gpio_num PIN_PMU_PSHOLD, .pshold_gpio_func PMU_PSHOLD_FUNC_SEL, .irq_base ENT_ZX234290_IRQ_BASE, }; #endifstatic struct i2c_board_info zx29_i2c0_devices[] { #ifdef CONFIG_MFD_ZX234290_I2C [0]{ I2C_BOARD_INFO(zx234290, 0x12), .irq EX0_INT, .platform_data zx234290_platform, }, #endif };void __init i2c_add_devices(void) { unsigned devices_num 0; int ret 0; /* *i2c devices on bus 0 */ devices_num ARRAY_SIZE(zx29_i2c0_devices); if (devices_num){ ret i2c_register_board_info(0,zx29_i2c0_devices, devices_num); if(ret) BUG(); } /* *i2c devices on bus 1 */ devices_num ARRAY_SIZE(zx29_i2c1_devices); if (devices_num){ ret i2c_register_board_info(1,zx29_i2c1_devices, devices_num); if(ret) BUG(); } }3)i2c_add_devices里面将各个设备的信息插入到__i2c_board_list的list中4)在I2C驱动初始化时例如i2c-zx29.c中将I2C的驱动注册进platform驱动static struct platform_driver zx29_i2c_driver { .probe zx29_i2c_probe, .remove zx29_i2c_remove, #ifdef CONFIG_PM .suspend zx29_i2c_suspend, .resume zx29_i2c_resume, #endif .driver { .owner THIS_MODULE, .name zx29_i2c, .of_match_table zx29_i2c_match, }, }; static int __init i2c_adap_zx29_init(void) { int ret; retplatform_driver_register(zx29_i2c_driver); if (ret0) { printk(KERN_INFO zx29 i2c driver register fail\n); } return ret; } subsys_initcall(i2c_adap_zx29_init);5)在平台驱动的probe函数中通过调用i2c_add_numbered_adapter()--i2c_register_adapter()--i2c_scan_static_board_info()--i2c_new_device()--device_register()完成设备的注册的。2. 驱动的注册1)通过调用i2c_add_driver添加对应的驱动#if 1 static struct i2c_driver zx234290_i2c_driver { .driver { .name zx234290, .owner THIS_MODULE, }, .probe zx234290_i2c_probe, .remove zx234290_i2c_remove, .id_table zx234290_i2c_id, }; #endif static int __init zx234290_i2c_init(void) { int ret; ret i2c_add_driver(zx234290_i2c_driver); if (ret ! 0) pr_err(Failed to register ZX234290 I2C driver: %d\n, ret); return ret; } /* init early so consumer devices can complete system boot */ subsys_initcall(zx234290_i2c_init);2)I2c_add_driver()--i2c_register_driver()--driver_register()注册驱动里面会进行驱动与设备的匹配匹配成功后会调用到驱动注册的probe函数。SPI设备/驱动的注册1.设备的注册1)zx297520v3-devices.c中定义了需要添加的SPI设备;static struct spi_board_info zx29_spi_devices[] { #ifdef CONFIG_FB_LEADT15DS26 { .modalias lead_t15ds26, .bus_num 0, .chip_select 0, .max_speed_hz 13000000, .mode SPI_MODE_3, .platform_data lead_lcd_platform, .controller_data lead_lcd_chip_info, }, #endif #ifdef CONFIG_TRANSCEIVER_XN297L { .modalias xn297l_tx, .bus_num 0, .chip_select 0, .max_speed_hz 1*1000*1000, .mode SPI_MODE_0, .controller_data 25, }, #endif #ifdef CONFIG_TRANSCEIVER_XN297L { .modalias xn297l_rx, .bus_num 1, .chip_select 0, .max_speed_hz 1*1000*1000, .mode SPI_MODE_0, .controller_data 87, }, #endif };2)Board-zx297520v3.c中调用spi_add_devices()函数添加SPI设备;3)spi_add_devices()中通过调用spi_register_board_info来进行设备的注册;void __init spi_add_devices(void) { unsigned devices_num ARRAY_SIZE(zx29_spi_devices); int ret 0; printk(spi_register_board_info success,devices_num%d\n,devices_num); if (devices_num){ ret spi_register_board_info(zx29_spi_devices, devices_num); printk(spi_register_board_info success,ret%d\n,ret); if(ret) BUG(); } }4)spi_register_board_info中遍历spi设备表中的所有设备并通过spi_match_master_to_boardinfo()--spi_new_device()--spi_add_device()--device_add()来进行设备的注册;2. 驱动的注册1)调用spi_register_driver注册spi驱动static int __init xn297l_init(void) { int ret; int minor 0; XN_DATA(register char dev for xn297l.); ret spi_register_driver(xn297l_spi_tx_driver); if (ret ! 0){ XN_ERR(failed to register xn297l_tx_spi_driver : %d, ret); return ret; } ret spi_register_driver(xn297l_spi_rx_driver); if (ret ! 0){ XN_ERR(failed to register xn297l_rx_spi_driver : %d, ret); return ret; } }/*spi driver begin*/ static const struct spi_device_id xn297l_tx_id[] { {xn297l_tx, 0 }, { } }; MODULE_DEVICE_TABLE(spi, xn297l_tx_id); static struct spi_driver xn297l_spi_tx_driver { .driver { .name xn297l_tx, .owner THIS_MODULE, }, .probe xn297l_tx_probe, .remove __devexit_p(xn297l_tx_remove), .id_table xn297l_tx_id, }; static const struct spi_device_id xn297l_rx_id[] { {xn297l_rx, 1 }, { } }; MODULE_DEVICE_TABLE(spi, xn297l_rx_id); static struct spi_driver xn297l_spi_rx_driver { .driver { .name xn297l_rx, .owner THIS_MODULE, }, .probe xn297l_rx_probe, .remove __devexit_p(xn297l_rx_remove), .id_table xn297l_rx_id, }; /*spi driver end*/2)spi_register_driver里面会调用driver_register进行驱动的注册里面会进行驱动与设备的匹配匹配成功后会调用到驱动注册的probe函数
企业数字化 ERP 产品动态
相关推荐
Matrix-Game-3.0与Wan2.2-TI2V-5B对比:性能提升与技术创新详解 Matrix-Game-3.0与Wan2.2-TI2V-5B对比:性能提升与技术创新详解
在人工智能视频生成领域,Matrix-Game-3.0作为基于Wan2.2-TI2V-5B的升级版本,带来了显著的性能提升和技术创新。本文将深入解析这两个模型的核心差异,帮助新手和普通… · 2026/11/3 9:18:07
Matrix-Game-3.0开发者指南:自定义动作控制与模型微调教程 Matrix-Game-3.0开发者指南:自定义动作控制与模型微调教程
Matrix-Game-3.0是一款功能强大的AI模型开发框架,提供了灵活的自定义动作控制和高效的模型微调功能,帮助开发者快速构建和优化AI应用。本指南将详细介绍如何利用Matrix-Game-3.0进行… · 2026/11/3 9:18:07
【系统架构设计师-Redis(2)】Redis 五大核心数据结构与典型场景实战(含秒杀、限流、队列、排行榜) /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:53:58
TabPFN-3终极指南:如何在5分钟内掌握这个革命性表格预测模型 TabPFN-3终极指南:如何在5分钟内掌握这个革命性表格预测模型
你想知道如何快速上手最先进的表格预测模型吗?TabPFN-3作为一款基于Transformer架构的表格预测基础模型,通过上下文学习技术,能够在单次前向传播中解决复杂的表格预测… · 2026/11/3 9:53:58
LTX-Best-Face-ID vs 传统视频生成工具:为什么它是人脸保留的最佳选择 LTX-Best-Face-ID vs 传统视频生成工具:为什么它是人脸保留的最佳选择
LTX-Best-Face-ID是一款基于LTX-2.3(22B)模型的身份保留参考转视频LoRA工具,它能根据人物参考照片和文本提示生成保持人物身份的视频。与传统视频生成工具相… · 2026/11/3 9:53:58
BBDown 下载 B 站视频完整指南:从单集视频到批量番剧的命令行工具 BBDown 下载 B 站视频完整指南:从单集视频到批量番剧的命令行工具 【免费下载链接】BBDown Bilibili Downloader. 一个命令行式哔哩哔哩下载器. 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown
BBDown 是一个免费开源的命令行 B 站视频下载器ÿ… · 2026/11/3 9:53:58
如何快速部署Mistral Medium 3.5 128B:5步完成本地vLLM服务器搭建 如何快速部署Mistral Medium 3.5 128B:5步完成本地vLLM服务器搭建
Mistral Medium 3.5 128B是一款具有1280亿参数的强大开源AI模型,支持256k超长上下文窗口,具备多模态输入、函数调用和推理能力。本文将通过5个简单步骤,教你如何… · 2026/11/3 9:52:57
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46