字符设备驱动高级篇5——静态映射表、动态映射结构体方式操作寄存器
来源:互联网 发布:成都家政公司办公软件 编辑:程序博客网 时间:2024/06/06 20:56
以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。
一、静态映射表建立过程分析
1、建立映射表的三个关键部分
(1)映射表描述
- 具体物理地址和虚拟地址的值相关的宏定义;
(2)映射表建立函数
a、
- 该函数负责(由(1)中的映射表(一些宏定义)来)建立linux内核的页表映射关系。
- 该函数位于kernel/arch/arm/mach-s5pv210/mach-smdkc110.c中,即smdkc110_map_io函数。
- smdkc110_map_io
- s5p_init_io
- iotable_init
b、
- 经过分析,真正的静态映射表在arch/arm/plat-s5p/cpu.c中的s5p_iodesc这个变量中;
- 本质是一个结构体数组,数组中每一个元素就是一个映射;
- 这个映射描述了一段物理地址到虚拟地址之间的映射。
- 这个结构体数组所记录的几个映射关系被iotable_init所使用,该函数负责将这个结构体数组格式的表建立成MMU所能识别的页表映射关系;
- 这样在开机后可以直接使用相对应的虚拟地址来访问对应的物理地址。
(3)开机时调用映射表建立函数
- kernel启动时,smdkc110_map_io怎样被调用的?
- 第二阶段的start_kernel函数
- setup_arch函数
- paging_init函数(mmu.c文件中)
- devicemaps_init函数
二、动态映射结构体方式操作寄存器
1、问题描述
- 上图是之前讲解的多次映射(分开独立映射);
- 下面仿效真实驱动中,用结构体封装的方式来进行单次多寄存器的地址映射;
2、实践编码
typedef struct GPJ0REG{volatile unsigned int gpj0con;volatile unsigned int gpj0dat;}gpj0_reg_t;#define GPJ0CONS5PV210_GPJ0CON#define GPJ0DATS5PV210_GPJ0DAT#define rGPJ0CON*((volatile unsigned int *)GPJ0CON)#define rGPJ0DAT*((volatile unsigned int *)GPJ0DAT)#define GPJ0_REGBASE0xe0200240gpj0_reg_t *pGPJ0REG;/****省略部分代码****/static int __init chrdev_init(void){printk(KERN_INFO "chrdev_init helloworld init\n");// 在module_init宏调用的函数中去注册字符设备驱动// major传0进去表示要让内核帮我们自动分配一个合适的空白的没被使用的主设备号// 内核如果成功分配就会返回分配的主设备好;如果分配失败会返回负数mymajor = register_chrdev(0, MYNAME, &test_fops);if (mymajor < 0){printk(KERN_ERR "register_chrdev fail\n");return -EINVAL;}printk(KERN_INFO "register_chrdev success... mymajor = %d.\n", mymajor);/*// 使用动态映射的方式来操作寄存器if (!request_mem_region(GPJ0CON_PA, 4, "GPJ0CON"))return -EINVAL;if (!request_mem_region(GPJ0DAT_PA, 4, "GPJ0CON"))return -EINVAL;pGPJ0CON = ioremap(GPJ0CON_PA, 4);pGPJ0DAT = ioremap(GPJ0DAT_PA, 4);*pGPJ0CON = 0x11111111;*pGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));// 亮*/// 2步完成了映射if (!request_mem_region(GPJ0_REGBASE, sizeof(gpj0_reg_t), "GPJ0REG"))return -EINVAL;pGPJ0REG = ioremap(GPJ0_REGBASE, sizeof(gpj0_reg_t));// 映射之后用指向结构体的指针来进行操作// 指针使用->结构体内元素的方式来操作各个寄存器pGPJ0REG->gpj0con = 0x11111111;pGPJ0REG->gpj0dat = ((0<<3) | (0<<4) | (0<<5));// 亮return 0;}// 模块下载函数static void __exit chrdev_exit(void){printk(KERN_INFO "chrdev_exit helloworld exit\n");//*pGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));pGPJ0REG->gpj0dat = ((1<<3) | (1<<4) | (1<<5));// 解除映射/*iounmap(pGPJ0CON);iounmap(pGPJ0DAT);release_mem_region(GPJ0CON_PA, 4);release_mem_region(GPJ0DAT_PA, 4);*/iounmap(pGPJ0REG);release_mem_region(GPJ0_REGBASE, sizeof(gpj0_reg_t));// 在module_exit宏调用的函数中去注销字符设备驱动unregister_chrdev(mymajor, MYNAME);}module_init(chrdev_init);module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息MODULE_LICENSE("GPL");// 描述模块的许可证MODULE_AUTHOR("aston");// 描述模块的作者MODULE_DESCRIPTION("module test");// 描述模块的介绍信息MODULE_ALIAS("alias xxx");// 描述模块的别名信息
阅读全文
0 0
- 字符设备驱动高级篇5——静态映射表、动态映射结构体方式操作寄存器
- 动态映射之结构体方式操作寄存器
- 字符设备驱动基础篇5——驱动如何操控硬件(动静态映射操作LED)
- Linux驱动中建立动态映射来实现操作寄存器
- linux设备驱动归纳总结(五):3.操作硬件——IO静态映射
- linux设备驱动归纳总结(五):3.操作硬件——IO静态映射
- 字符设备驱动高级篇6——内核提供的读写寄存器接口
- 设备寄存器静态映射的建立
- 【Linux开发】linux设备驱动归纳总结(五):3.操作硬件——IO静态映射
- 字符设备驱动高级篇3——自动创建字符设备驱动的设备文件
- Linux内核访问外设I/O资源的方式(设备物理地址和设备虚拟地址),静态映射和动态映射
- Linux内核访问外设I/O资源的方式(设备物理地址和设备虚拟地址),静态映射和动态映射
- 驱动学习7--led动态映射与结构体
- 字符设备驱动高级篇2——字符设备驱动注册代码分析
- Linux设备驱动——字符驱动各种结构体
- 动态映射和静态映射
- linux设备驱动学习(5) 高级字符驱动程序操作--ioctl
- 字符设备驱动基础篇4——字符设备驱动读写接口的操作实践
- 贪心好题(两种变量的贪心)poj3262 Protecting the Flowers
- stm32 GPIO 浮空输入的理解
- 继承的虚函数缺省参数值不要重新定义的原因
- observer
- js 数组
- 字符设备驱动高级篇5——静态映射表、动态映射结构体方式操作寄存器
- Spring AOP 增强类型
- Spring data redis-StringRedisTemplate 用法
- opengl es着色器原理和过程
- codeforces 625-D. Finals in arithmetic(构造+模拟)
- 07读书笔记之详解四种基本布局
- IIS+php环境下:上传文件出现:windows server PHP Warning: mkdir(): Permission denied 解决办法
- Kotlin-42.kotlin调用Java之四(Call Java from Kotlin)
- ubuntu 服务器搭建 Shadowsocks 服务