《linux驱动:s3c2410_ts/s3c2440_ts模块加载流程》

发布者:HarmoniousCharm最新更新时间:2024-07-09 来源: elecfans关键字:linux驱动 手机看文章 扫描二维码
随时随地手机看文章

前言

通过分析s3c2410_ts/s3c2440_ts模块加载流程,分析linux驱动中的总线-设备-驱动模型以及输入子系统框架。

主要流程分析图示

s3c2440_ts 主要流程分析




系统初始化

MACHINE_START(SMDK2410,'SMDK2410')

MACHINE_START(SMDK2410, 'SMDK2410') /* @TODO: request a new identifier and switch

    * to SMDK2410 */

/* Maintainer: Jonas Dietsche */

.phys_io = S3C2410_PA_UART,

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100,

.map_io = smdk2410_map_io,

.init_irq = s3c24xx_init_irq,

.init_machine = smdk2410_init,

.timer = &s3c24xx_timer,

MACHINE_END

将上面的宏展开:


static const struct machine_desc __mach_desc_SMDK2410

 __attribute_used__

 __attribute__((__section__('.arch.info.init'))) = {

 .nr = MACH_TYPE_SMDK2410, /* architecture number */

 .name = 'SMDK2410', /* architecture name */

 /* Maintainer: Jonas Dietsche */

 .phys_io = S3C2410_PA_UART, /* start of physical io */

 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

 .boot_params = S3C2410_SDRAM_PA + 0x100, /* tagged list */

 .map_io = smdk2410_map_io, /* IO mapping function */

 .init_irq = s3c24xx_init_irq,

 .init_machine = smdk_machine_init,

 .timer = &s3c24xx_timer,

MACHINE_START主要是定义了'struct machine_desc'的类型,放在 section('.arch.info.init'),是初始化数据,Kernel 起来之后将被丢弃。各个成员函数在不同时期被调用:

1. init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用;

2. init_irq在start_kernel() -> init_IRQ() -> init_arch_irq() 被调用;

3. map_io 在 setup_arch() -> paging_init() -> devicemaps_init()被调用;

其他主要都在 setup_arch() 中用到;

smdk2410_init

static void __init smdk2410_init(void)

{

        s3c24xx_fb_set_platdata(&smdk2410_lcd_cfg);

platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));

smdk_machine_init();

}

smdk_machine_init

void __init smdk_machine_init(void)

{

/* Configure the LEDs (even if we have no LED support)*/


s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);

s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);

s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);

s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);


s3c2410_gpio_setpin(S3C2410_GPF4, 1);

s3c2410_gpio_setpin(S3C2410_GPF5, 1);

s3c2410_gpio_setpin(S3C2410_GPF6, 1);

s3c2410_gpio_setpin(S3C2410_GPF7, 1);


if (machine_is_smdk2443())

smdk_nand_info.twrph0 = 50;


s3c_device_nand.dev.platform_data = &smdk_nand_info;

#ifdef CONFIG_TOUCHSCREEN_S3C2410

set_s3c2410ts_info(&s3c2410_ts_cfg);

#endif

platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));


s3c2410_pm_init();

}

platform_add_devices

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;

}

platform_device_register注册smdk_devs数组中的各设备

static struct platform_device __initdata *smdk_devs[] = {

&s3c_device_nand,

&smdk_led4,

&smdk_led5,

&smdk_led6,

&smdk_led7,

#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)

    &s3c_device_dm9k,

#endif    

#ifdef CONFIG_SERIAL_EXTEND_S3C24xx

    &s3c_device_8250,

#endif

#ifdef CONFIG_TOUCHSCREEN_S3C2410

&s3c_device_ts,

#endif

};

自此,s3c_device_ts设备被注册到平台总线。

内核加载触摸模块

编译进内核加载驱动

编译内核设置,make menuconfig

Symbol: TOUCHSCREEN_S3C2410 [=y]                                                                                                                                           │   

  │ Prompt: S3C2410/S3C2440 touchscreens                                                                                                                                       │   

  │   Defined at drivers/input/touchscreen/Kconfig:14                                                                                                                          │   

  │   Depends on: !S390 && INPUT && INPUT_TOUCHSCREEN                                                                                                                          │   

  │   Location:                                                                                                                                                                │   

  │     -> Device Drivers                                                                                                                                                      │   

  │       -> Input device support                                                                                                                                              │   

  │         -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])                                                                                              │   

  │           -> Touchscreens (INPUT_TOUCHSCREEN [=y])  

然后make uImage,将s3c2410_ts驱动编译进内核,系统启动便会加载,即执行驱动的s3c2410ts_init函数。

驱动被加载调用其初始化函数s3c2410ts_init

static int __init s3c2410ts_init(void)

{

// init_MUTEX(&gADClock);

return platform_driver_register(&s3c2410ts_driver);

}

s3c2410ts_driver结构体

static struct platform_driver s3c2410ts_driver = {

       .driver         = {

       .name   = 's3c2410-ts',

       .owner  = THIS_MODULE,

       },

       .probe          = s3c2410ts_probe,

       .remove         = s3c2410ts_remove,

};

自此,s3c2410_ts驱动被注册到平台总线。

平台总线-设备-驱动模型

s3c2410_ts设备通过platform_device_register注册到平台总线。

s3c2410_ts驱动通过platform_driver_register注册到平台总线。

在总线层处,调用s3c2410_ts驱动的probe函数。

调用s3c2410_ts驱动的probe函数的过程

platform_driver_register->

driver_register->

bus_add_driver->

driver_attach->

bus_for_each_dev->

__driver_attach->

driver_probe_device->

really_probe->

drv->probe(dev)

__driver_attach(kernel 2.6.22)

static int __driver_attach(struct device * dev, void * data)

{

struct device_driver * drv = data;


/*

* Lock device and try to bind to it. We drop the error

* here and always return 0, because we need to keep trying

* to bind to devices and some drivers will return an error

* simply if it didn't support the device.

*

* driver_probe_device() will spit a warning if there

* is an error.

*/


if (dev->parent) /* Needed for USB */

down(&dev->parent->sem);

down(&dev->sem);

if (!dev->driver)

driver_probe_device(drv, dev);

up(&dev->sem);

if (dev->parent)

up(&dev->parent->sem);


return 0;

}

__driver_attach(kernel 3.4)

static int __driver_attach(struct device *dev, void *data)

{

struct device_driver *drv = data;


/*

* Lock device and try to bind to it. We drop the error

* here and always return 0, because we need to keep trying

* to bind to devices and some drivers will return an error

* simply if it didn't support the device.

*

* driver_probe_device() will spit a warning if there

* is an error.

*/


if (!driver_match_device(drv, dev))

return 0;


if (dev->parent) /* Needed for USB */

device_lock(dev->parent);

[1] [2]
关键字:linux驱动 引用地址:《linux驱动:s3c2410_ts/s3c2440_ts模块加载流程》

上一篇:《Linux驱动:s3c2410/s3c2440 ts驱动分析》
下一篇:嵌入式学习笔记之点亮一个LED

推荐阅读最新更新时间:2026-03-21 04:12

迅为工业RK3568 itop-3568开发板Linux驱动开发实战:RK3568内核模块符号导出详解
迅为工业级稳定可靠的RK3568平台itop-3568开发板驱动开发实战:RK3568内核模块符号导出深入解析 选择迅为iTOP-3568开发板,获取完整驱动开发套件与工业级稳定性保障 在复杂的Linux驱动开发中,模块化设计是提升代码可维护性和复用性的关键。内核模块符号导出正是实现模块间的基础技术。本期将基于迅为RK3568开发板,深入讲解这一核心机制。 迅为提供的完整驱动开发套件,包含从基础教程到进阶实战的全套代码示例,助您快速掌握此类核心驱动开发技巧。 第5章 内核模块符号导出实验 本章节我们学习内核模块符号导出,什么是内核模块符号导出呢?内核模块之间是相互独 立的,互相不能直接访问。将内核模块的符号(函
[嵌入式]
迅为工业RK3568 itop-3568开发板<font color='red'>Linux</font><font color='red'>驱动</font>开发实战:RK3568内核<font color='red'>模块</font>符号导出详解
STM32MP157 Linux系统移植开发篇12:Linux内核MIPI LCD驱动移植
本文章为《STM32MP157 Linux系统移植开发篇》系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板)。stm32mp157是ARM双核,2个A7核,1个M4核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统,STM32MP157开发板所以既可以学嵌入式linux,也可以学stm32单片机。针对FS-MP1A开发板,除了Linux系统移植篇外,还包括其他多系列教程,包括Cortex-A7开发篇、Cortex-M4开发篇、扩展板驱动移植篇、Linux应用开发篇、FreeRTOS系统移植篇、Linux驱动开发篇、硬件设计篇、人工智能机器
[单片机]
Linux下实现流水灯等功能的LED驱动代码及测试实例
驱动代码: #include linux/errno.h #include linux/kernel.h #include linux/module.h #include linux/slab.h #include linux/input.h #include linux/init.h #include linux/serio.h #include linux/delay.h #include linux/clk.h #include linux/miscdevice.h #include linux/gpio.h #include asm/io.h #include asm/irq.h #incl
[单片机]
Linux下18b20温度传感器驱动代码及测试实例
驱动代码: #include linux/module.h #include linux/fs.h #include linux/kernel.h #include linux/init.h #include linux/delay.h #include linux/cdev.h #include linux/device.h #include linux/gpio.h #include plat/gpio-cfg.h #define DEVICE_NAME TEM0 #define TEM_SHOW_CODE 0x01 //static struct cdev
[单片机]
linux设备驱动的学习之一
由于项目上要用到,于是乎我要学习linux设备驱动的编写,开始的时候还比较清楚,能够对简单的GPIO控制操作实现出来,但是项目上要用到的是SPI和GPIO的输入中断来读取AD的电压值,然后就陷入到了一个庞大的设备代码阅读中去了,尤其是platform device的学习,到现在都还没有理清其中的关系,虽然搜索了很多网上的文章,但庆幸的是我有一种比着框框买鸭蛋的精神,我想要比着这些源码画一个出来。以前没有在LPC1768上使用过SPI,导致对SPI是一个完全陌生的状态,不清楚他的传输方式,这也是学习中的一个问题,也是一开始我的盲目无方向感的原因,因为这里的linux SPI设备驱动和SPI协议就是两个要学习的问题。 先来把“简单
[单片机]
Smart210学习记录-------Linux设备驱动结构
cdev结构体 1 struct cdev { 2 struct kobject kobj; /* 内嵌的 kobject 对象 */ 3 struct module *owner; /*所属模块*/ 4 struct file_operations *ops; /*文件操作结构体*/ 5 struct list_head list; 6 dev_t dev; /*设备号*/ 7 unsigned int count; 8 }; 1.struct file_operations { 2 struct module *owner; 3 /* 拥有该结构的模块的指针,一般为 THIS_MODULES */ 4 l
[单片机]
Smart210学习记录-------<font color='red'>Linux</font>设备<font color='red'>驱动</font>结构
Smart210学习记录----beep linux字符设备驱动
今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈。。。但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决方法,但是我还是没看懂,只能慢慢找,,, 我在insmod字符设备是,出现了一下提示信息 这里只列出主要部分: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000 *pgd=00000000 Internal error: Oops: 7 Modules lin
[单片机]
Linux驱动入门(三)Led驱动
一、注册字符设备驱动 二、操作硬件 2.1 控制led 2.2 通用方式实现 2.3 gpiolib实现 三、源码 3.1 通用方式实现 3.2 gpiolib实现 四、测试 目的:实现一个led驱动,应用层写入1led亮,写0led灭 一、注册字符设备驱动 led驱动是一个字符设备驱动,编写led驱动首先要注册字符设备,生成设备节点,然后再是完善文件操作集合 关于如何注册字符设备和生成设备字节,在Linux驱动入门(一)字符设备驱动基础中讲得比较详细了,这里给出代码 #include linux/module.h #include linux/init.h #include linux/fs.h #include linux/c
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved