linux驱动移植的重要数据结构
转载:http://www.embeddedlinux.org.cn/html/jishuzixun/201304/14-2538.html
对于嵌入式 Linux 系统来说,有各种体系结构的处理器和硬件平台,并且用户需要根据需求自己定制硬件板。只要是硬件平台有些变化,即使非常小,可能也需要做一些移植工作。内核移植是嵌入式Linux系统中最常见的一项工作。
内核移植工作主要是修改跟硬件平台相关的代码,一般不涉及 Linux 内核通用的程序。
移植的难度也取决于两种硬件平台的差异。Linux 对于特定的硬件平台的软件就叫作 BSP
(Board Support Package)。
由于 Linux 内核具备可移植性的特点,并且已经支持了各种体系结构的很多种目标板,
我们很容易从中找到跟自己硬件类似的目标板。参考内核已经支持的目标板来移植 BSP,就
如同使用模板开发程序。
因此,移植linux内核的过程大多数情况下就是移植BSP的过程。三星公司提供了smdk24xx开发板的BSP。对于mini2440开发板来说,移植linux内核,只要修改smdk24xx开发板的BSP使该linux支持mini2440开发板就可以了。
linux内核源代码的ARCH目录存放的是体系结构相关的代码,对于每个架构的CPU,arm目录下都有一个对应的目录,比如arch/arm、arch/i386。而arm架构的处理器种类又有很多,所以,在arch/arm目录下对于每种arm架构处理器也有一个对应的子目录,比如arch/arm/mach-s3c2440、arch/arm/mach-s3c2410等。在arch/arm目录下有一个plat-s3c24xx目录,根据目录名它应该是与s3c24xx系列处理器的平台设备相关的一个目录。注意,所谓的"平台设备"并不是与字符设备、块设备和网络设备并列的概念,而是linux系统描述设备的一个附加手段。在plat-s3c24xx目录下有一个common-smdk.c文件,根据文件名,它应该是三星公司的smdk24xx系列开发板都需要的一个文件。在移植驱动的时候经常需要修改arch/arm/plat-s3c24xx/common-smdk.c文件。对于arch/arm/mach-s3c2440目录,它是专门用来保存 S3C2410 系列处理器平台相关程序,其中 Kconfig 和 Makefile 是用于内核配置编译的。其他文件分为 2 类,一类是处理器通
用的,例如:clock.c clock.h cpu.c cpu.h s3c2410.c s3c2410.h等;另一类是目标板相关的,例如:bast.h bast-irq.c mach-bast.c等。在这些文件中,实现了处理器和目标板相关的一些定义和初始化函数。还有些相关的定义包含在 include/asm-arm/arch-s3c2410/下的头文件中。
linux内核中对于每种支持的开发板都会使用宏MACHINE_START、MACHINE_END来定义一个machine_desc结构。MACHINE_START、MCHINE_END的定义如下:
(1)/*include/asm-arm/mach/arch.h */
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
在arch/arm/mach-s3c2410/mach-smdk2440.c中可以找到SMDK2440开发板的定义如下:
MACHINE_START(S3C2440, "SMDK2440")
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
把MACHINE_START、MACHINE_END扩展开来就是定义了一个名为__mach_desc_S3C2440的结构体变量:
const struct machine_desc __mach_desc_S3C2440 __used
__attribute__((__section__(".arch.info.init"))) =
{
.nr = MACH_TYPE_S3C2440, //开发板的机器类型ID
.name = "SMDK2440", //开发板名称
.phys_io = S3C2410_PA_UART, //起始IO物理地址
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100, //内核启动参数的地址
.init_irq = s3c24xx_init_irq, //中断初始化函数
.map_io = smdk2440_map_io, //IO映射函数(在这里修改时钟频率)
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
};
MACH_TYPE_S3C2440可以看作是系统平台号,它包含在include/asm- arm/mach-types.h头文件中,不过这个头文件是在配置内核或编译内核时自动生成的,所以不能更改。。真正系统平台号
的定义位置在arch/arm/tools/mach-types文件中。
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
s3c2440 ARCH_S3C2440 S3C2440 362
arch/arm/tools/mach-types中每一行定义一个系统平台号。 "machine_is_xxx"是用来判断当前的平台号是否正确的函数; "CONFIG_xxxx"是在内核配置时生成的; "MACH_TYPE_xxx"
是系统平台号的定义; "number"是系统平台的值。 __mach_desc_S3C2440结构体中的函数将在内核启动过程中,完成系统平台的初始化工作
对于具有相同处理器的系统平台,并不需要对每一个平台都编写一个BSP,如果他们的外围接口电路基本相同,也许只需修改一些数据的定义,修改几个函数的参数就可以了。
(2)linux设计了一个通用的数据结构resource来描述各种I/O资源(比如,IO端口,DMA,中断等)
include/linux/ioport.h
struct resource
{
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
flags:资源标记,用于标识各种资源,例如IORESOURCE_MEM表示内存资源,IORESOURCE_IRQ表示中断资源
对于内存资源,start表示内存起始物理地址,end:表示内存末尾物理地址
对于中断资源,start表示起始中断号,end表示最后一个中断号
常用资源数组来表示一个设备所拥有的各类资源,比如s3c2440的片内LCD控制器拥有的资源如下
static struct resource s3c_lcd_resource[]=
{
[0]={
.start=S3C24XX_PA_LCD,
.end=S3C24XX_PA_LCD+S3C24XX_SZ_LCD-1,
.flags=IORESOURCE_MEM,
}
[1]={
.start=IRQ_LCD,
.end=IRQ_LCD,
.flags=IORESOURCE_IRQ,
}
};
其中S3C24XX_PA_LCD被定义为0x4D000000,S3C24XX_SZ_LCD被定义为1M。所以,在这里给LCD控制器分配的物理地址空间范围为0x4D000000~0x4D0FFFFF,这些是LCD控制器各寄存器使用的地址,但实际上LCD控制器的寄存器地址的范围为0x4D000000~0x4D000060,使用0x4D000000和0x4D000060给他们赋值也应该是可以的。IRQ_LCD算得是32,它会将GPG4引脚设为LCD_PWREN功能,因为GPG4为LCD_PWREN/EINT12复用。
(3)在内核文件include/linux/platform_device.h中,定义了两个数据结构来表示设备和驱动程序:platform_device结构用来描述设备的名称、ID、所占用的资源(比如内存地址/大小、中断号)等;platform_driver结构用来描述各种操作函数,比如枚举函数、移除设备函数、驱动名称等。
//平台设备
struct platform_device
{
const char * name; //设备名
int id;
struct device dev;
u32 num_resources; // 设备所使用的各类资源数量
struct resource * resource; // 设备的资源数组
struct platform_device_id *id_entry;
struct pdev_archdata archdata;
};
//平台驱动
struct platform_driver
{
int (*probe)(struct platform_device *); //探测
int (*remove)(struct platform_device *); //移除
void (*shutdown)(struct platform_device *); //关闭
int (*suspend)(struct platform_device *, pm_message_t state);//挂起
int (*resume)(struct platform_device *); //恢复
//描述驱动的名称(name)和属主(owner)等信息
struct device_driver driver;
struct platform_device_id *id_table;
};
内核启动后,首先构造链表将描述设备的platform_device构造组织起来,得到一个设备的列表;当加载某个驱动程序的platform_driver结构时,使用一些匹配函数来检查驱动程序能否支持这些设备,常用的检查方法很简单:比较驱动程序和设备的名称。
以S3C2440开发板为例,在arch/arm/mach-s3c2440/mach-smdk2440.c中定义了如下设备:
static struct platform_device *smdk2440_devices[] __initdata =
{
&s3c_device_usb, //USB控制器
&s3c_device_lcd, //LCD控制器
&s3c_device_wdt, //看门狗
&s3c_device_i2c,
&s3c_device_iis,
};
在arch/arm/plat-s3c24xx/common-smdk.c中定义了如下设备:
static struct platform_device __initdata *smdk_devs[] =
{
&s3c_device_nand, //NAND FLASH
&smdk_led4,
&smdk_led5,
&smdk_led6,
&smdk_led7,
};
linux驱动移植的重要数据结构的更多相关文章
- I.MX6 SHT20 Linux 驱动移植
/*********************************************************************** * I.MX6 SHT20 Linux 驱动移植 * ...
- linux驱动移植问题点
1.I2C地址是否和其它IC冲突.通过改地址解决 ——通常,以下三种情况的log表现相同:1.ic没连接到主板:2.i2c地址错误:3.该器件I2C地址与同组其它器件冲突 2.I2C通信是否受到其它s ...
- linux网卡驱动移植
这里重要的是物理层PHY receiver,MAC(media access control)层,这里与软件中的协议栈不同,在硬件上MAC是PHY的下一层.DM9000A将MAC和PHY做到一起,也可 ...
- 【转】 linux内核移植和网卡驱动(二)
原文网址:http://blog.chinaunix.net/uid-29589379-id-4708911.html 一,内核移植步骤: 1, 修改顶层目录下的Makefile ARCH ...
- 【转】 linux内核移植和驱动添加(三)
原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED ...
- Linux开源模块迁移概述暨交叉编译跨平台移植总结--从《嵌入式Linux驱动模板简洁和工程实践》
本文摘录<嵌入式Linux驱动模板简洁和工程实践>一本书"开发和调试技术". Linux强大的是,有那么多的开源项目可以使用.通常非常需要可以通过寻找相关的源模块被定义 ...
- 【Linux驱动】TQ2440 DM9000E网卡驱动移植(Linux-2.6.30.4)
花了一天的时间研究了一下Linux-2.6.30.4版本号内核下关于TQ2440 DM9000E的网卡驱动移植.总结一下自己的收获. 事实上.在Linux-2.6.30.4版本号内核下有关于网卡驱动, ...
- Linux Charger IC 驱动移植总结
Linux Charger IC 驱动移植总结 文章目录 Linux Charger IC 驱动移植总结 1 设备树的基本知识 设备树的概念 设备树的基本结构 compatible属性 举个栗子 2 ...
- Linux网卡驱动移植--Dm9000网卡驱动分析
1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...
随机推荐
- linux nc命令使用详解(转)
linux nc命令使用详解 功能说明:功能强大的网络工具 语 法:nc [-hlnruz][-g<网关...>][-G<指向器数目>][-i<延迟秒数>][-o& ...
- 【Codeforces】113 D. Museum
题解 我们设\(f(i,j)\)是\((i,j)\)这个点期望被经过多少次 我们可以列出方程组来消元,由于终点只会被经过0次或者1次,期望就是概率 对于起点的话我们期望经过次数多加一个1 复杂度\(O ...
- Think PHP 3.2 界面及JS多语言实现
1.多语言实现的原理在实现多语言的时候需要调用L()函数.那么L函数是如何实现多语言的输出呢?在L函数内部有一个静态变量$_lang一维数组.所有的语言数据都存在在这个数组中.系统在加载的时候根据选择 ...
- FIFO调度算法和LRU算法
一.理论 FIFO:先进先出调度算法 LRU:最近最久未使用调度算法 两者都是缓存调度算法,经常用作内存的页面置换算法. 打一个比方,帮助你理解.你有很多的书,比如说10000本.由于你的书实在太多了 ...
- QT STUDY
- Java设计模式 - 持续更新
注意,此博客来源于我的 OneNote 笔记本 因此属于图片形式进行展示,这意味着你可以: 不经过我的同意进行保存 不经过我的同意进行发布 我仍然希望搬运时留一个网址指明来处:我的博客园 多谢!以下是 ...
- 最详细的vue-cli安装教程 &^没有之一 ^& 大神亲测。。╮( ̄▽  ̄)╭
这里介绍使用git安装,电脑自带命令行依然可以使用进行安装 第一步 node环境安装 1.1 如果本机没有安装node运行环境,请下载node 安装包进行安装 1.2 如果本机已经安装node的运行换 ...
- 镣铐之舞:美团安全工程师Black Hat USA演讲
背景 2018年8月9日,全球顶级安全会议——Black Hat USA在美国拉斯维加斯的曼德勒海湾会议中心落下了帷幕,这场盛会在全球黑客心中几乎等同于“世界杯”和“奥斯卡”一样的存在.这场一年一度的 ...
- 用UltraEdit转换大小写
alt+F5转大写: ctrl+F5转小写: F5每个单词的首字母大写: Shift+F5大小写互换.
- java面试 关键字
1. final关键字有哪些用法? 修饰类.方法和变量. (1) final变量是只读的,不允许改变其引用,与static共用可声明常量.JVM会对final变量进行优化,比如常量折叠. (2) fi ...