Linux驱动程序开发.ppt
《Linux驱动程序开发.ppt》由会员分享,可在线阅读,更多相关《Linux驱动程序开发.ppt(112页珍藏版)》请在三一办公上搜索。
1、Linux驱动程序移植及分析,程杰http:/,一、Linux内核启动过程概述二、MTD简介及修改Nand MTD分区三、移植YAFFS文件系统四、Framebuffer驱动分析五、嵌入式Linux 音频驱动程序设计六、Linux IIS音频应用程序开发简介,一、Linux内核启动过程概述,1 Linux内核启动,汇编代码部分检测内核是否支持处理器和开发板连接内核使用的虚拟地址,设置页表,使能MMU常规工作:复制数据段、调用strat_kernel函数C代码部分内核初始化调用rest_init函数,创建系统第一个进程init重设页表、设置系统时钟、初始化串口,开始,确定内核是否支持架构_loo
2、kup_processor_type,确定内核是否支持开发板_lookup_machine_type,建立一级页表_creat_page_tables,禁止Icache Dcache_arm720t_setup,使能MMU_enale_mmu,复制数据段清楚BSS段保存CPU ID调用start_kernel,汇编阶段,输出Linux版本信息printk,设置与体系相关的内容setup_arch,初始化控制台console_init,启动init过程 rest_init,C阶段,2 引导阶段代码分析,78 ENTRY(stext)79msrcpsr_c,#PSR_F_BIT|PSR_I_BIT
3、|MODE_SVC ensure svc mode80 and irqs disabled81 mrcp15,0,r9,c0,c0 get processor id82bl_lookup_processor_type r5=procinfo r9=cpuid83movsr10,r5 invalid processor(r5=0)?84beq_error_p yes,error p85bl_lookup_machine_type r5=machinfo86movsr8,r5 invalid machine(r5=0)?87beq_error_a yes,error a88bl_create_pa
4、ge_tables,79 通过设置CPSR寄存器来确保处理器进入SVC模式,并禁止中断81 读取协处理器CP15的寄存器C0获得CPU ID82 调用函数确定是否支持CPU85 调用函数确定是否支持当前开发板如果_lookup_processor_type和_lookup_machine_type返回成功,系统将调用_creat_page_tables来创建一级页表以建立虚拟地址到物理地址的映射关系,接着会调用_enable_mmu来打开MMU,3 start_kernel函数分析,进入start_kernel后,如果在串口中看不到信息,说明启动出现问题,可能原因有两个:bootloader传
5、入参数不对setup_arch针对开发板的设置不正确在执行console_init函数前,系统信息保存在缓冲区中,只有在初始化控制台后才会输出,(1)setup_arch函数分析,arch/arm/kernel/setup.cvoid _init setup_arch(char*cmdline_p)setup_processor();mdesc=setup_machine(machine_arch_type);if(mdesc-boot_params)tags=phys_to_virt(mdesc-boot_params);if(tags-hdr.tag=ATAG_CORE)if(meminf
6、o.nr_banks!=0)squash_mem_tags(tags);parse_tags(tags);memcpy(saved_command_line,from,COMMAND_LINE_SIZE);saved_command_lineCOMMAND_LINE_SIZE-1=0;parse_cmdline(cmdline_p,from);paging_init(,setup_processor()用来进行处理器相关的一些设置。setup_machine()用来获得开发板的machine_desc结构if(mdesc-boot_params)用来确定u-boot传入参数的启动地址之后的每一
7、个tag,在setup.c中都定义了相应的处理函数eg内存tag:parse_tag_mem32()命令行tag:parse_tag_cmdline()parse_cmdline()对一些参数进行先期处理,“mem=”用来限制Linux使用的内存总量系统将调用early_mem对其进行处理“console=”用来指定要使用的控制台名称、序号、参数console_setup函数将处理这个信息,并保存在全局结构console_cmdline中,后面console_init函数初始化控制台时会根据这些信息选择,(2)paging_init函数分析,调用形式:paging_init(其中:meminf
8、o中存放内存信息mdesc是开发板定义参数结构体调用流程:paging_init-devicemapes_init-map_io(),(3)console_init函数分析,位置 drivers/char/tty_io.cvoid _init console_init(void)initcall_t*call;/*Setup the default TTY line discipline.*/(void)tty_register_ldisc(N_TTY,将调用_con_initcall 至 _con_initcall_end之间定义的每个函数,这些函数使用console_initcall宏指定
9、,总结启动函数调用过程,start_kernel-setup_arch-setup_processorsetup_machinepage_tagsparse_cmdlinepaging_init-devicemaps_init-mdesc-map_io()console_init-register_console(),二、MTD简介及修改Nand MTD分区,1 MTD简介,MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间
10、提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。CFI接口的MTD设备分为四层,从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。,1.1 Flash硬件驱动层,硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NORFlash芯片驱动遵循CFI接口标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下,1.2 MTD原始设备,原始设备层有两部分组成,一部分是MTD原始设备的通用代码,另一部分是各个特定的Flash的数据,例如分区。用于描述
11、MTD原始设备的数据结构是mtd_info,这其中定义了大量的关于MTD的数据和操作函数。mtd_table(mtdcore.c)则是所有MTD原始设备的列表mtd_part(mtd_part.c)是用于表示MTD原始设备分区的结构,其中包含了mtd_info,因为每一个分区都是被看成一个MTD原始设备加在mtd_table中的,1.3 MTD设备层,基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。MTD字符设备的定义在mtdchar.c中实现,通过注册一系列file operation函数(lseek、open、close、read、wri
12、te)。MTD块设备则是定义了一个描述MTD块设备的结构 mtdblk_dev,并声明了一个名为mtdblks的指针数组,这数组中的每一个mtdblk_dev和mtd_table中的每一个 mtd_info一一对应。,1.4文件系统,在Bootloader中将JFFS(或JFFS2)的文件系统映像jffs.image(或jffs2.img)烧到flash的某一个分区中,在/arch/arm/mach-your/arch.c文件的 your_fixup函数中将该分区作为根文件系统挂载。文件系统:内核启动后,通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。
13、,2 修改Nand MTD分区,SEP4020 Nand Flash 有64MB空间目前分区情况:mtdblock0 0 x00000000-0 x0100000 1Mmtdblock1 0 x00100000-0 x0600000 5Mmtdblock2 0 x00600000-0 x1E00000 24Mmtdblock3 0 x01E00000-0 x04000000 34M,SEP4020 NAND的驱动程序,其目录位于:./drivers/mtd/nand/sep4020.c 宏定义:#define NUM_PARTITIONS 4/NAND的分区数目(这里分为4个分区)#defin
14、e UBOOT_SIZE SZ_1M*1/UBOOT分区空间大小#define KERNEL_SIZE SZ_1M*5/内核分区空间大小#define ROOT_SIZE SZ_1M*24/根文件系统分区大小#define USER_SIZE SZ_1M*34/用户空间分区大小,static struct mtd_partition partition_info=.name=U-boot,.offset=0,.size=UBOOT_SIZE,.name=linux 2.6.16 kernel,.offset=UBOOT_SIZE,.size=KERNEL_SIZE,.name=root,.of
15、fset=UBOOT_SIZE+KERNEL_SIZE,.size=ROOT_SIZE,.name=user,.offset=UBOOT_SIZE+KERNEL_SIZE+ROOT_SIZE,.size=USER_SIZE;,上面的代码可以看出:NAND被分为4个分区我们可能修改NAND分区数目和各分区的大小(包括增加分区删除分区合并分区等)注意:无论做任何修改,所有分区的大小不能超过NAND的总量(目前64M).,增加一个分区,#define NUM_PARTITIONS 5/NAND的分区数目(修改)#define UBOOT_SIZE SZ_1M*1/UBOOT分区空间大小#define
16、 KERNEL_SIZE SZ_1M*5/内核分区空间大小#define ROOT_SIZE SZ_1M*24/根文件系统分区大小#define USER_SIZE SZ_1M*17/用户空间分区大小(修改)#define USER1_SIZE SZ_1M*17/用户增加的分区(修改),这样就将原来的第四分区(34M)分为两个分区(17M+17M)的空间.在串口调试工具输出的NAND分区信息中可以看到如下五个分区:Creating 5 MTD partitions on NAND 64MiB 3,3V 8-bit:0 x00000000-0 x00100000:U-boot0 x0010000
17、0-0 x00600000:linux 2.6.16 kernel0 x00600000-0 x01e00000:root0 x01e00000-0 x02f00000:user0 x02f00000-0 x04000000:user1,删除(合并)一个分区,#define NUM_PARTITIONS 3/NAND分区数目(修改)#define UBOOT_SIZE SZ_1M*1#define KERNEL_SIZE SZ_1M*5#define ROOT_SIZE SZ_1M*58/根目录空间大小(修改)static struct mtd_partition partition_info
18、=.name=U-boot,.offset=0,.size=UBOOT_SIZE,.name=linux 2.6.16 kernel,.offset=UBOOT_SIZE,.size=KERNEL_SIZE,.name=root,.offset=UBOOT_SIZE+KERNEL_SIZE,.size=ROOT_SIZE,;,这样就将原来的后两个分区就合并成为一个54M空间的分区.在串口调试工具输出的NAND分区信息中可以看到如下三个分区:Creating 3 MTD partitions on NAND 64MiB 3,3V 8-bit:0 x00000000-0 x00100000:U-b
19、oot0 x00100000-0 x00600000:linux 2.6.16 kernel0 x00600000-0 x04000000:root,static struct mtd_partition partition_info=.name=U-boot,.offset=0,.size=UBOOT_SIZE,.name=linux 2.6.16 kernel,.offset=UBOOT_SIZE,.size=KERNEL_SIZE,.name=root,.offset=UBOOT_SIZE+KERNEL_SIZE,.size=ROOT_SIZE,.name=user,.offset=UB
20、OOT_SIZE+KERNEL_SIZE+ROOT_SIZE,.size=USER_SIZE,/以下分区为增加的一个分区,在地偏移量后面要加上USER空间的大小.name=user1,.offset=UBOOT_SIZE+KERNEL_SIZE+ROOT_SIZE+USER_SIZE,.size=USER1_SIZE;,三、移植YAFFS文件系统,1.1简介,Yaffs(Yet Another Flash File System)文件系统是专门针对NAND闪存设计的嵌入式文件系统,目前有YAFFS和YAFFS2两个版本,两个版本的主要区别之一在于YAFFS2能够更好的支持大容量的NAND FL
21、ASH芯片。Yaffs文件系统有些类似于JFFS/JFFS2文件系统,与之不同的是JFFS1/2文件系统最初是针对NOR FLASH的应用场合设计的,而NOR FLASH和NAND FLASH本质上有较大的区别,所以尽管JFFS1/2 文件系统也能应用于NAND FLASH,但由于它在内存占用和启动时间方面针对NOR的特性做了一些取舍,所以对NAND来说通常并不是最优的方案。,NOR和NAND的比较,基本上NOR比较适合存储程序代码,其容量一般较小(比如小于32MB),价格较高,而NAND容量可达1GB以上,价格也相对便宜,适合存储数据。一般来说,128MB以下容量NAND FLASH 芯片的
22、一页大小为528字节,用来存放数据,另外每一页还有16字节的备用空间(SpareData,OOB),用来存储ECC校验/坏块标志等信息,再由若干页组成一个块,通常一块为32页16K。与NOR相比,NAND不是完全可靠的,每块芯片出厂时都有一定比例的坏块存在,对数据的存取不是使用地址映射而是通过寄存器的操作,串行存取数据。,1.2Yaffs文件系统数据在NAND上的存储方式,Yaffs对文件系统上的所有内容(比如正常文件,目录,链接,设备文件等等)都统一当作文件来处理,每个文件都有一个页面专门存放文件头,文件头保存了文件的模式、所有者id、组id、长度、文件名、Parent Object ID等
23、信息。因为需要在一页内放下这些内容,所以对文件名的长度,符号链接对象的路径名等长度都有限制。前面说到对于NAND FLASH上的每一页数据,都有额外的空间用来存储附加信息,Yaffs正是利用了这部分空间中剩余的部分来存储文件系统相关的内容。,以512+16B为一个PAGE的NAND FLASH芯片为例,Yaffs文件系统数据的存储布局如下所示,可以看到在这里YAFFS一共使用了8个BYTE用来存放文件系统相关的信息(yaffs_Tags)。这8个Byte的具体使用情况按顺序如下:,Serial Number在文件系统创建时都为0,以后每次写具有同一ObjectID和ChunkID的page的时
24、候都加一,因为Yaffs在更新一个PAGE的时候总是在一个新的物理Page上写入数据,再将原先的物理Page删除,所以该serial number可以在断电等特殊情况下,当新的page已经写入但老的page还没有被删除的时候用来识别正确的Page,保证数据的正确性。ObjectID号为18bit,所以文件的总数限制在256K即26万个左右。以上这些是针对Yaffs1而言,对于Yaffs2因为针对chunk size大于1k的NAND FLASH,在Tags各分量及总体尺寸上都做了修改,以便更快更好的处理大容量的NAND FLASH芯片。由于Tag尺寸的增大,在512+16B类型的NAND FL
25、ASH上就一个Trunk对应一个page的情况,目前就无法使用Yaffs2文件系统了。由于文件系统的基本组织信息保存在页面的备份空间中,因此,在文件系统加载时只需要扫描各个页面的备份空间,即可建立起整个文件系统的结构,而不需要像JFFS1/2 那样扫描整个介质,从而大大加快了文件系统的加载速度。,1.3yaffs文件系统在内存中的组织方式,操作文件系统的第一步自然是取得SuperBlock了,Yaffs文件系统本身在NAND Flash上并不存在所谓的SuperBlock块,完全是在文件系统mount的过程中由read_super函数填充的.通常一个具体的文件系统在VFS的Super_bloc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 驱动程序 开发
链接地址:https://www.31ppt.com/p-5438166.html