Day5: platformDriver-1

Linux驱动开发之platform驱动 本文通过设计使用platform架构的ds18b20程序驱动,来介绍如何编写platform驱动。 阅读详情

Platform Driver (1)

Linux kernel中大部分设备可以归结为平台设备,因此大部分的驱动是平台驱动(patform driver)

什么是平台设备

平台设备是linux的设备模型中一类设备的抽象。 内核中的描述:

Platform devices are devices that typically appear as autonomous entities in the system. This includes legacy port-based devices and host bridges to peripheral buses, and most controllers integrated into system-on-chip platforms. What they usually have in common is direct addressing from a CPU bus. Rarely, a platform_device will be connected through a segment of some other kind of bus; but its registers will still be directly addressable.

一句话来描述就是: CPU能够直接寻址的SOC上的外设

请添加图片描述

图1:Platform设备

图1中的uart控制器,I2C控制器,GPIO控制器等,都是平台设备。

可以说,paltform设备对Linux驱动工程师是非常重要的,因为我们编写的大多数设备驱动,都是为了驱动plaftom设备。

Platform设备在内核中的实现主要包括三个部分:

  • Platform Bus,基于底层bus模块,抽象出一个虚拟的Platform bus,用于挂载Platform设备;
  • Platform Device,基于底层device模块,抽象出Platform Device,用于表示Platform设备;
  • Platform Driver,基于底层device_driver模块,抽象出Platform Driver,用于驱动Platform设备

对于图1中的I2C控制器挂载在platform Bus上,因此我们在linux kernel中常说的I2C driver,都是指I2C controller driver,都是以platform driver的形式存在,当然,对应的控制器是platform device。

与此同时,kernel抽象出I2C bus(/sys/bus/i2c),用于挂载和I2C controller通过I2C总线连接的各个I2C slave device。

串口驱动开发

驱动开发框架

得益于设备模型,Linux kernel平台驱动的开发有了一套非常固定的框架

1)模块的入口和出口
用于注册/注销platform driver,这一部分的代码基本固定,包括函数和变量的命名方式也可固定,如下:

 /* 驱动模块加载 */
 static int __init xxxdriver_init(void)
 {
     return platform_driver_register(&xxx_driver);
 }

 /* 驱动模块卸载 */
 static void __exit xxxdriver_exit(void)
 {
 platform_driver_unregister(&xxx_driver);
 }

 module_init(xxxdriver_init);
 module_exit(xxxdriver_exit);
 MODULE_LICENSE("GPL V2");
 MODULE_AUTHOR("QianRuShi-ABC");

2)platform driver

基本的platform driver包含三要素:struct platform_driver变量、probe/remove函数、用于和device tree匹配的match table,如下:

/*
 * platform 平台驱动结构体
 */
static struct platform_driver xxx_driver = {
 .driver = {
 .name = "xxx",
 .of_match_table = xxx_of_match,
 },
 .probe = xxx_probe,
 .remove = xxx_remove,
};

 /*
 * platform 驱动的 probe 函数
 * 驱动与设备匹配成功以后此函数就会执行
 */
 static int xxx_probe(struct platform_device *dev)
 {

   match = of_match_device(xxx_of_match, &pdev->dev);
  if (!match) {
      dev_err(&pdev->dev, "Error: No device match found\n");
      return -ENODEV;
  }
  
  return 0;
 }

 static int xxx_remove(struct platform_device *dev)
 {
 ......
 
 /* 函数具体内容 */
 return 0;
 }

 /* 匹配列表 */
 static const struct of_device_id xxx_of_match[] = {
 { .compatible = "xxx-xxx" },
 { /* Sentinel */ }
 };

注意,xxx_of_match中的.compatible需要和DTS文件中的compatible对应,一般格式是“厂商名称,芯片系列-模块名”,例如“actions,s900-serial”

##串口驱动
串口设备(serial or uart,后面不再区分)是TTY设备的一种,Linux kernel为了方便串口驱动的开发,在TTY framework的基础上,封装了一层串口框架(serial framework)。该框架尽可能的屏蔽了TTY有关的技术细节(比较难懂),驱动工程师在编写串口驱动的时候,只需要把精力放在串口以及串口控制器本身即可。

Linux kernel serial framework位于“drivers/tty/serial”目录中,其软件架构(如下面图2所示)比较简单:
请添加图片描述

图2: serialFramework

Serial core是Serial framework的核心实现,对上封装、屏蔽TTY的技术细节,对下为具体的串口驱动提供简单、统一的编程API。
Serial drivers就是具体的串口驱动。

Serial Core

serial core主要实现如下三类功能
1)将串口设备有关的物理对象(及其操作方法)封装成一个一个的数据结构,以达到用软件语言描述硬件的目的。

2)向底层driver提供串口驱动的编程接口。

3)基于TTY framework所提供的TTY driver的编写规则,将底层driver看到的serial driver,转换为TTY driver,并将所有的serial操作,转换为对应的tty操作。

关键数据结构

struct uart_port
struct uart_state
struct uart_ops
struct uart_driver

API:

int uart_register_driver(struct uart_driver *uart);
void uart_unregister_driver(struct uart_driver *uart);

int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_match_port(struct uart_port *port1, struct uart_port *port2);

int uart_suspend_port(struct uart_driver *reg, struct uart_port *port);
int uart_resume_port(struct uart_driver *reg, struct uart_port *port);

static inline int uart_tx_stopped(struct uart_port *port)

extern void uart_insert_char(struct uart_port *port, unsigned int status,
                 unsigned int overrun, unsigned int ch, unsigned int flag);

串口驱动的移植步骤

  • 定义并注册uart driver
  • 注册uart port
  • 定义并实现uart ops
定义并注册uart driver
static struct uart_driver imx_reg = {
	.owner          = THIS_MODULE,
	.driver_name    = DRIVER_NAME,
	.dev_name       = DEV_NAME,
	.major          = SERIAL_IMX_MAJOR,
	.minor          = MINOR_START,
	.nr             = ARRAY_SIZE(imx_ports),
	.cons           = IMX_CONSOLE,
};
注册uart port

platform device代表uart控制器,是实体抽象。对应的,uart port代表“串口”. 因此,我们需要在platform device probe的时候(platform driver的probe接口),动态分配并注册一个uart port(struct uart_port)。在后续的串口操作中,都是以uart port指针为对象. 见下一章节代码中i.mx6的驱动代码。

定义并实现uart ops

struct uart_ops结构包含了各式各样的uart端口的操作函数,需要在添加uart port的时候提供.见下一章节代码中i.mx6的驱动代码

完整代码
对应驱动开发框架中,1)模块的入口和出口
static int __init imx_serial_init(void)
{
	int ret = uart_register_driver(&imx_reg);

	if (ret)
		return ret;

	ret = platform_driver_register(&serial_imx_driver);
	if (ret != 0)
		uart_unregister_driver(&imx_reg);

	return ret;
}

static void __exit imx_serial_exit(void)
{
	platform_driver_unregister(&serial_imx_driver);
	uart_unregister_driver(&imx_reg);
}

module_init(imx_serial_init);
module_exit(imx_serial_exit);

MODULE_AUTHOR("Sascha Hauer");
MODULE_DESCRIPTION("IMX generic serial port driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:imx-uart");
对应驱动开发框架中,2)platform driver

基本的platform driver包含三要素:struct platform_driver变量、probe/remove函数、用于和device tree匹配的match table

  • struct platform_driver变量
static struct platform_driver serial_imx_driver = {
	.probe		= serial_imx_probe,
	.remove		= serial_imx_remove,

	.suspend	= serial_imx_suspend,
	.resume		= serial_imx_resume,
	.id_table	= imx_uart_devtype,
	.driver		= {
		.name	= "imx-uart",
		.of_match_table = imx_uart_dt_ids,
	},
};
  • robe/remove函数
serial_imx_probe
 
static int serial_imx_probe(struct platform_device *pdev)
{
	struct imx_port *sport;
	void __iomem *base;
	int ret = 0;
	struct resource *res;
	int txirq, rxirq, rtsirq;
	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
	if (!sport)
		return -ENOMEM;
	ret = serial_imx_probe_dt(sport, pdev);
	if (ret > 0)
		serial_imx_probe_pdata(sport, pdev);
	else if (ret < 0)
		return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
	return PTR_ERR(base);

rxirq = platform_get_irq(pdev, 0);
txirq = platform_get_irq(pdev, 1);
rtsirq = platform_get_irq(pdev, 2);

sport->port.dev = &pdev->dev;
sport->port.mapbase = res->start;
sport->port.membase = base;
sport->port.type = PORT_IMX,
sport->port.iotype = UPIO_MEM;
sport->port.irq = rxirq;
sport->port.fifosize = 32;
sport->port.ops = &imx_pops;
sport->port.rs485_config = imx_rs485_config;
sport->port.rs485.flags =
	SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
sport->port.flags = UPF_BOOT_AUTOCONF;
init_timer(&sport->timer);
sport->timer.function = imx_timeout;
sport->timer.data     = (unsigned long)sport;

sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(sport->clk_ipg)) {
	ret = PTR_ERR(sport->clk_ipg);
	dev_err(&pdev->dev, "failed to get ipg clk: %d\n", ret);
	return ret;
}

sport->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(sport->clk_per)) {
	ret = PTR_ERR(sport->clk_per);
	dev_err(&pdev->dev, "failed to get per clk: %d\n", ret);
	return ret;
}

sport->port.uartclk = clk_get_rate(sport->clk_per);
if (sport->port.uartclk > IMX_MODULE_MAX_CLK_RATE) {
	ret = clk_set_rate(sport->clk_per, IMX_MODULE_MAX_CLK_RATE);
	if (ret < 0) {
		dev_err(&pdev->dev, "clk_set_rate() failed\n");
		return ret;
	}
}
sport->port.uartclk = clk_get_rate(sport->clk_per);

/*
 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
 * chips only have one interrupt.
 */
if (txirq > 0) {
	ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
			       dev_name(&pdev->dev), sport);
	if (ret)
		return ret;

	ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
			       dev_name(&pdev->dev), sport);
	if (ret)
		return ret;
} else {
	ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
			       dev_name(&pdev->dev), sport);
	if (ret)
		return ret;
}
imx_ports[sport->port.line] = sport;
platform_set_drvdata(pdev, sport);
return uart_add_one_port(&imx_reg, &sport->port);

}

serial_imx_remove

static int serial_imx_remove(struct platform_device *pdev)
{
	struct imx_port *sport = platform_get_drvdata(pdev);
	return uart_remove_one_port(&imx_reg, &sport->port);
}

  • 用于和device tree匹配的match table
static const struct of_device_id imx_uart_dt_ids[] = {
	{ .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
对应串口驱动的移植步骤中,定义并注册uart driver

在驱动init函数中注册了uart driver

int ret = uart_register_driver(&imx_reg);

在linux serial framework中,uart driver是一个平行于platform driver的概念,用于驱动“虚拟”的“串口”设备。

#define DRIVER_NAME "IMX-uart"

static struct uart_driver imx_reg = {
	.owner          = THIS_MODULE,
	.driver_name    = DRIVER_NAME,
	.dev_name       = DEV_NAME,
	.major          = SERIAL_IMX_MAJOR,
	.minor          = MINOR_START,
	.nr             = ARRAY_SIZE(imx_ports),
	.cons           = IMX_CONSOLE,
};
对应串口驱动的移植步骤中,注册uart port

假如一个soc中有5个串口控制器(也可称作uart控制器,后面我们不再区分),每个uart控制器都可引出一个串口(uart port)。那么:
每个uart控制器,都是一个platform device,由dts文件的一个node描述。而这5个platform device,可由同一个driver驱动,即platform driver。
相对于uart控制器实实在在的存在,我们更为熟悉的串口(uart port),则是虚拟的设备,它们由“struct uart_port”描述(后面会介绍),并在platform driver的probe接口中,注册到kernel。它们可由同一个driver驱动,即这里所说的uart driver。

struct imx_port {
	struct uart_port	port;
	struct timer_list	timer;
	unsigned int		old_status;
	unsigned int		have_rtscts:1;
	unsigned int		dte_mode:1;
	unsigned int		irda_inv_rx:1;
	unsigned int		irda_inv_tx:1;
	unsigned short		trcv_delay; /* transceiver delay */
	struct clk		*clk_ipg;
	struct clk		*clk_per;
	const struct imx_uart_data *devdata;

	/* DMA fields */
	unsigned int		dma_is_inited:1;
	unsigned int		dma_is_enabled:1;
	unsigned int		dma_is_rxing:1;
	unsigned int		dma_is_txing:1;
	struct dma_chan		*dma_chan_rx, *dma_chan_tx;
	struct scatterlist	tx_sgl[2];
	struct imx_dma_rxbuf	rx_buf;
	unsigned int		tx_bytes;
	unsigned int		dma_tx_nents;
	struct delayed_work	tsk_dma_tx;
	wait_queue_head_t	dma_wait;
	unsigned int            saved_reg[10];
#define DMA_TX_IS_WORKING 1
	unsigned long		flags;
};

在platform driver的probe函数中会动态分配并注册一个uart port(struct uart_port)然后初始化并注册其中的port变量。初始化完之后,直接调用uart_add_one_port接口,将该port添加到kernel serial core

再返回上面的static int serial_imx_probe(struct platform_device *pdev)展开看到

//分配struct xxx_port类型的指针
struct imx_port *sport;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
//获取中断号,该串口对应的中断号, 一般是从DTS中解析得到的;
	rxirq = platform_get_irq(pdev, 0);
	txirq = platform_get_irq(pdev, 1);
	rtsirq = platform_get_irq(pdev, 2);
//初始化并注册其中的port变量
    sport->port.dev = &pdev->dev;
	sport->port.mapbase = res->start;
	sport->port.membase = base;
	sport->port.type = PORT_IMX,
	sport->port.iotype = UPIO_MEM;
	sport->port.irq = rxirq;
	sport->port.fifosize = 32;
	sport->port.ops = &imx_pops;
	sport->port.rs485_config = imx_rs485_config;
	sport->port.rs485.flags =
		SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
	sport->port.flags = UPF_BOOT_AUTOCONF;
	init_timer(&sport->timer);
	sport->timer.function = imx_timeout;
	sport->timer.data     = (unsigned long)sport;

在proble函数的最后,调用uart_add_one_port接口,将该port添加到kernel serial core
return uart_add_one_port(&imx_reg, &sport->port);

对应串口驱动的移植步骤中,定义并实现uart ops

上面platform driver的probe函数serial_imx_probe,展开中看到
sport->port.ops = &imx_pops;
struct uart_ops结构包含了各式各样的uart端口的操作函数,需要在添加uart port的时候提供。

static struct uart_ops imx_pops = {
	.tx_empty	= imx_tx_empty,
	.set_mctrl	= imx_set_mctrl,
	.get_mctrl	= imx_get_mctrl,
	.stop_tx	= imx_stop_tx,
	.start_tx	= imx_start_tx,
	.stop_rx	= imx_stop_rx,
	.enable_ms	= imx_enable_ms,
	.break_ctl	= imx_break_ctl,
	.startup	= imx_startup,
	.shutdown	= imx_shutdown,
	.flush_buffer	= imx_flush_buffer,
	.set_termios	= imx_set_termios,
	.type		= imx_type,
	.config_port	= imx_config_port,
	.verify_port	= imx_verify_port,
#if defined(CONFIG_CONSOLE_POLL)
	.poll_init      = imx_poll_init,
	.poll_get_char  = imx_poll_get_char,
	.poll_put_char  = imx_poll_put_char,
#endif
};

个人公众号交流
请添加图片描述

#参考
http://www.wowotech.net/x_project/serial_driver_porting_1.html
http://www.wowotech.net/x_project/serial_driver_porting_2.html
http://www.wowotech.net/x_project/serial_driver_porting_3.html
http://www.wowotech.net/x_project/serial_driver_porting_4.html

http://www.wowotech.net/comm/serial_overview.html

GPU服务器选购避坑指南:从硬件配置到场景化性能调优 本文提供GPU服务器选购的全面指南,涵盖硬件架构解析、应用场景配置策略和性能调优实践。针对大模型训练、推理服务和科学计算等场景,详细分析GPU选型、内存带宽匹配和散热设计等关键因素,帮助技术决策者避免常见配置误区,实现成本效益最大化。 阅读详情

相关推荐

CDH Hue连接Hbase报错TSocket read 0 bytes

问题描述 安装好CDH集群后,在Hue中查看HBase信息时,Hue界面报错如下: Api 错误:TSocket read 0 bytes Hue日志报错: exceptions_renderable ERROR Potential trace: [('/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hue/apps/hbase/src/hbase/api.py', 46, 'query', 'return getattr(self

邢为栋 3492

设备树——platform_driver

设备树浅谈--led一、设备树是什么?二、自己写一个简单的LED驱动配合自己的treeinit: 注册driver到platformexit: 从platform卸载driverled_drvled_probe:myled_oprsled_remove总结 文章目录一、设备树是什么?二、自己写一个简单的LED驱动配合自己的treeinit: 注册driver到platformexit: 从platform卸载driverled_drvled_probe:myled_oprsled_remove总结 一、设备

qq_40943525的博客 5431

泛微ecology9 HRMwebservice接口实战:企业组织架构与人员信息同步指南

本文详细介绍了泛微ecology9 HRMwebservice接口在企业系统集成中的实战应用,重点解析了如何通过该接口实现组织架构与人员信息的双向同步。内容涵盖环境配置、核心接口调用、数据格式规范及常见错误排查,旨在帮助开发与运维工程师高效完成主数据同步,提升企业IT管理效率。

weixin_29323365的博客 498

嵌入式Linux 开发经验:platform_driver_register 的使用方法

嵌入式Linux 开发经验:platform_driver_register 的使用方法

坚韧与专注 7806

Vite与Webpack路径配置大不同:从Vue2迁移到Vue3必须知道的public目录使用技巧

本文详细解析了Vite与Webpack在public目录路径配置上的核心差异,为Vue2迁移到Vue3的开发者提供实用指南。重点对比了两种构建工具的资源处理逻辑,给出典型编译警告的解决方案,并分享路径适配表与高级优化技巧,帮助开发者高效完成技术栈升级。

weixin_30836759的博客 485

matlab/simulink saw谐振器仿真,基于Matlab的SAW模态耦合模型的仿真研究

第32卷 第 4 期Vol. 32 No. 4重 庆 理 工 大 学 学 报 (自然科学)Journal of Chongqing University of Technology( Natural Science)2 0 1 8年 4 月Apr. 2018doi : 10.3969/j . issn. 1674-8425(z). 2018.04.002本文引用格式 :李志鹏,马龙祥,孟旭,等•基...

weixin_36192634的博客 1385

Linux驱动_Platform平台驱动

在Linux操作系统中,驱动程序占用了Linux内核代码量的大头,如果不进行管理,将会造成数量庞大的结果。因此引入了驱动的分离。 上图所示就是驱动的分离,相当于驱动使用标准方法去获取到设备信息(比如从设备树中获取到设备信息),然后根据获取到的设备信息来初始化设备。 这样就相当于驱动只负责驱动,设备只负责设备,想办法将两者进行匹配即可。这个就是 Linux 中的总线(bus)、驱动(driver)和设备(device)模型,也就是常说的驱动分离。总线就是驱动和设备信息的月老...

qq_42174306的博客 4872

51单片机+HX711电子秤Proteus仿真保姆级教程(附完整源码与避坑指南)

本文详细介绍了51单片机与HX711电子秤在Proteus仿真中的全流程实战指南,包括电路设计、核心代码实现、典型问题排查及系统集成等关键步骤。特别提供了HX711驱动程序的编写技巧和称重数据处理算法,帮助开发者快速搭建高精度电子秤仿真系统,并避免常见的设计陷阱。

weixin_30752699的博客 413

platform driver

platform driver 1、注册设备驱动 1.1、申请设备号 alloc_chrdev_region(dev_t *dev,unsigned int -firstminor,unsigned int -count,char *name); 功能:动态的分配(驱动)设备编号 firstminor: 设备号 count: 设备数量 name: 设备名称 缺点 无法预知在/dev下创建设备节点,因为动态分配设备号不能保证在每次加载驱动module时始终一致(其实若在两次加载同一个驱动module之间并

hanhailong0525的博客 849

手把手教你学RDMA驱动开发专栏--第7章 队列对(QP)与数据传输实现​7.3 完成队列(CQ):事件通知机制与轮询/中断模式

本章详细探讨了RDMA驱动中完成队列(CQ)的事件通知机制,重点分析了轮询与中断两种模式的实现原理及优化策略。CQ作为操作结果的报告载体,其核心功能包括结果反馈、事件通知和资源同步。轮询模式通过主动查询实现低延迟,适合高性能场景;中断模式通过被动通知节省CPU资源,适用于低频事件处理。驱动实现需考虑CQ溢出防护、多QP共享同步等关键问题,并提供事件通道机制将CQE传递给用户态。通过对比两种模式的优缺点及适用场景,揭示了RDMA系统在性能与资源间的权衡机制。

MHD0815的博客 396

华为OD机考双机位C卷 - 池化资源共享 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 池化资源共享 (OD上机考试双机位C卷)。提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 1071

Day6: platformDriver-2

在上文中说到,Linux kernel中大部分设备可以归结为平台设备,因此大部分的驱动是平台驱动(patform driver)而对于I2C控制器, 其挂载在platform Bus上,因此我们在linux kernel中常说的I2C driver,都是指I2C controller driver,都是以platform driver的形式存在,当然,对应的控制器是platform device。

feiwatson的博客 467

ABB机器人与S7-1200PLC实现位置坐标数据发送和接收的具体方法

ABB机器人与S7-1200PLC实现位置坐标数据发送和接收的具体方法

Robot_PLC_HMI_Automation 2916

[特殊字符] 驱动开发硬核特训 · Day 5 - 深入解析 Platform Driver 驱动框架

Platform Driver 是 Linux 内核中用于管理“平台设备”的驱动框架。那些无法通过标准总线(如 PCI 或 USB)自动识别的固定连接外设。是 SoC(系统级芯片)内部集成的硬件模块,如 UART、GPIO、I2C 控制器;或通过固定方式连接在主控的管脚上,如 LED、按键、蜂鸣器、电源管理芯片 PMIC 等;没有专门的总线控制器进行自动枚举,需开发者主动在设备树中声明其存在。驱动专注实现控制逻辑,而设备信息由设备树提供,二者通过内核的 platform 总线完成匹配与绑定。

Interview_TC的博客 929

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Linux驱动开发——(九)platform设备驱动

介绍了Linux下的platform及其驱动实现。

wJen的博客 3219

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

platform 设备驱动实验

在操作platform总线下分别做不使用设备树实验和使用设备树实验

weixin_46829095的博客 1001

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

平台驱动程序: Platform drivers

Platform drivers On embedded systems, devices are often not connected through a bus allowing enumeration, hotplugging, and providing unique identiers for devices. However, we still want the devi...

RToax 1945

Linux驱动中platfrom-driver/device注册及probe执行过程分析

1、platform系统 platfrom系统在linux内核中包含三个部分 ①platfrom-bus虚拟总线,是一个内核抽象出来的虚拟的总线,在linux内核中以链表的形式表示,platform-driver/device通过挂载在platform虚拟总线上,实现设备和驱动之间的匹配,在内核表现形式为一系列platform-driver/device结构体组成的链表形式; ②platform-driver模型,内核中抽象出来的driver模型,表现形式为platfrom-driver的结构体,它的

QQ135102692的博客 2485

如何理解驱动程序、设备树、platform、device、driver之间的关系

理解驱动程序、设备树、platform、device、driver之间的关系,学习利用设备树来使用或者编写驱动程序

weixin_42408707的博客 6532

platform_driver 、 platform_device、device_driver 对这三种结果体详细说明,并说明三者之间的关系

platform_driver 、 platform_device、device_driver 对这三种结果体详细说明,并说明三者之间的关系

xie__jin__cheng的博客 803

platform与设备树

要掌握什么 笔者认为,platform最大的好处有两点:一是驱动分离,二是更加简单,采用了自动匹配的方法,不用搜索设备树去找节点。 实际上,platfrom由三部分组成:bus、driver、device。一般而言(也是力求最简单的情况下),bus已经被linux自己写好了,device用设备树描述。所以驱动开发者只需要对driver进行操作即可。而这个driver和普通的驱动的套路相差不大。 用...

下雨夏云的博客 1811

Linux驱动编程 - platform平台设备驱动总线

Linux系统中的platform平台设备驱动

hinewcc的博客 1719

最简单的platform驱动

platform驱动与设备树匹配

1168

驱动开发中platform设备驱动架构详解

总线是一条虚拟总线(只有一条),这类总线没有对应的硬件结构。为相应的设备,为相应的驱动。

让技术没有门槛 4065

linux (platform_driver)平台设备驱动常用API函数

Table of Contents 1、设备层注册、注销函数 1.1、platform_device_register 1.2、platform_device_unregister 1.3、platform_add_devices 2、驱动层注册注销函数 2.1、platform_driver_register 2.2、platform_driver_ unregister 3、...

shenlong1356的博客 5983

paltform设备驱动精讲

 总线设备驱动模型主要包含总线、设备、驱动三个部分,总线可以是一条真实存在的总线,例如USB、I2C等典型的设备。但是对于一些设备(内部的设备)可能没有现成的总线。Linux 2.6内核中引入了总线设备驱动模型。总线设备驱动模型与之前的三类驱动(字符、块设备、网络设备)没有必然的联系。设备只是搭载到了总线中。在linux内核中假设存在一条虚拟总线,称之为platform总线。plat

aaahza的博客 928
上一篇: Day4: 应用篇-1
下一篇: Day6: platformDriver-2
feiwatson
博客等级 码龄11年 49粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值