博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20150501调试分析之 自制工具<寄存器编辑器>
阅读量:4611 次
发布时间:2019-06-09

本文共 16385 字,大约阅读时间需要 54 分钟。

20150501调试分析之 自制工具<寄存器编辑器>

2015-05-1 Lover雪儿

今天还是继续我们内核错误调试,今天是制作一个寄存器编辑器,可以自由的读写某些我们需要调试的寄存器.

.首先完成一个可自动创建设备节点的字符设备驱动程序

这儿我们前面都写过了N,此处不再赘述,直接附上代码:

1 /****************************** 2 内核调试之自制寄存器读写工具(驱动) 3  *****************************/ 4 #include 
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 20 21 static int major;22 23 //auto to create device node24 static struct class *class;25 static struct class_device *kernel_class_dev;26 27 28 static int kernel1_rw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)29 {30 31 return 0;32 }33 34 //定义字符设备结构体35 static struct file_operations kernel_rw_ops = {36 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */37 .ioctl = kernel1_rw_ioctl,38 };39 40 static int kernel_rw_init(void)41 {42 printk("<0>kernel_rw_init\n");43 major = register_chrdev(0, "kernel_rw", &kernel_rw_ops);44 class = class_create(THIS_MODULE,"kernel_rw");45 kernel_class_dev = device_create(class,NULL,MKDEV(major,0),NULL,"kernel_rw"); /*/dev/kernel_rw*/46 47 48 return 0;49 }50 51 static void kernel_rw_exit(void)52 {53 printk("<0>kernel_rw_exit\n");54 device_unregister((void *)kernel_class_dev);55 class_destroy((struct class *)class);56 unregister_chrdev(major,"kernel_rw");57 }58 59 module_init(kernel_rw_init);60 module_exit(kernel_rw_exit);61 MODULE_LICENSE("GPL");62 MODULE_AUTHOR("Lover雪儿");
kernel_rw_1.c

 

.ioctl中增加寄存器的读写功能

定义ioctlcommand命令.

1 #define KERNEL_RW_R8     02 #define KERNEL_RW_R16     13 #define KERNEL_RW_R32     64 5 #define KERNEL_RW_W8     36 #define KERNEL_RW_W16     47 #define KERNEL_RW_W32     5

 

实现ioctl函数.

1 static int kernel1_rw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 2 { 3     volatile unsigned char  *p8; 4     volatile unsigned short *p16; 5     volatile unsigned int   *p32; 6     unsigned long val; 7     unsigned long addr; 8  9     unsigned int buf[2];10 11     12     copy_from_user(buf, (const void __user *)arg, 8);13     addr = buf[0];14     val  = buf[1];15     printk("<0>\naddr %x : %d \n",addr, val);16     p8  = (volatile unsigned char *)ioremap(addr, 4);17     p16 = p8;18     p32 = p8;19 20     switch (cmd)21     {22         case KERNEL_RW_R8:23         {24             val = *p8;25             copy_to_user((void __user *)(arg+4), &val, 4);26             printk("<0>enter r8\n");27             break;28         }29 30         case KERNEL_RW_R16:31         {32             val = *p16;33             copy_to_user((void __user *)(arg+4), &val, 4);34             printk("<0>enter r16\n");35             break;36         }37 38         case KERNEL_RW_R32:39         {40             val = *p32;41             copy_to_user((void __user *)(arg+4), &val, 4);42             printk("<0>enter r32\n");43             break;44         }45 46         case KERNEL_RW_W8:47         {48             *p8 = val;49             printk("<0>enter w8, val = %x\n",val);50             break;51         }52 53         case KERNEL_RW_W16:54         {55             *p16 = val;56             printk("<0>enter w16, val = %x\n",val);57             break;58         }59 60         case KERNEL_RW_W32:61         {62             *p32 = val;63             printk("<0>enter w32, val = %x\n",val);64             break;65         }66         default:67             printk("<0>enter default\n");68             break;69     }    70 71     iounmap(p8);72     return 0;73 }

 

附上驱动程序kernel_rw.c

 

1 /******************************  2 内核调试之自制寄存器读写工具(驱动)  3  *****************************/  4 #include 
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 20 #define KERNEL_RW_R8 0 21 #define KERNEL_RW_R16 1 22 #define KERNEL_RW_R32 6 23 24 #define KERNEL_RW_W8 3 25 #define KERNEL_RW_W16 4 26 #define KERNEL_RW_W32 5 27 28 static int major; 29 30 //auto to create device node 31 static struct class *class; 32 static struct class_device *kernel_class_dev; 33 34 35 static int kernel1_rw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 36 { 37 volatile unsigned char *p8; 38 volatile unsigned short *p16; 39 volatile unsigned int *p32; 40 unsigned long val; 41 unsigned long addr; 42 43 unsigned int buf[2]; 44 45 46 copy_from_user(buf, (const void __user *)arg, 8); 47 addr = buf[0]; 48 val = buf[1]; 49 printk("<0>\naddr %x : %d \n",addr, val); 50 p8 = (volatile unsigned char *)ioremap(addr, 4); 51 p16 = p8; 52 p32 = p8; 53 54 switch (cmd) 55 { 56 case KERNEL_RW_R8: 57 { 58 val = *p8; 59 copy_to_user((void __user *)(arg+4), &val, 4); 60 printk("<0>enter r8\n"); 61 break; 62 } 63 64 case KERNEL_RW_R16: 65 { 66 val = *p16; 67 copy_to_user((void __user *)(arg+4), &val, 4); 68 printk("<0>enter r16\n"); 69 break; 70 } 71 72 case KERNEL_RW_R32: 73 { 74 val = *p32; 75 copy_to_user((void __user *)(arg+4), &val, 4); 76 printk("<0>enter r32\n"); 77 break; 78 } 79 80 case KERNEL_RW_W8: 81 { 82 *p8 = val; 83 printk("<0>enter w8, val = %x\n",val); 84 break; 85 } 86 87 case KERNEL_RW_W16: 88 { 89 *p16 = val; 90 printk("<0>enter w16, val = %x\n",val); 91 break; 92 } 93 94 case KERNEL_RW_W32: 95 { 96 *p32 = val; 97 printk("<0>enter w32, val = %x\n",val); 98 break; 99 }100 default:101 printk("<0>enter default\n");102 break;103 } 104 105 iounmap(p8);106 return 0;107 }108 109 //定义字符设备结构体110 static struct file_operations kernel_rw_ops = {111 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */112 .ioctl = kernel1_rw_ioctl,113 };114 115 static int kernel_rw_init(void)116 {117 printk("<0>kernel_rw_init\n");118 major = register_chrdev(0, "kernel_rw", &kernel_rw_ops);119 class = class_create(THIS_MODULE,"kernel_rw");120 kernel_class_dev = device_create(class,NULL,MKDEV(major,0),NULL,"kernel_rw"); /*/dev/kernel_rw*/121 122 123 return 0;124 }125 126 static void kernel_rw_exit(void)127 {128 printk("<0>kernel_rw_exit\n");129 device_unregister((void *)kernel_class_dev);130 class_destroy((struct class *)class);131 unregister_chrdev(major,"kernel_rw");132 }133 134 module_init(kernel_rw_init);135 module_exit(kernel_rw_exit);136 MODULE_LICENSE("GPL");137 MODULE_AUTHOR("Lover雪儿");
kernel_rw.c

 

 

 

 

.编写测试函数

1 /******************************  2 内核调试之自制寄存器读写工具(应用)  3  *****************************/  4 #include 
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 19 #define KERNEL_RW_R8 (unsigned int)0 20 #define KERNEL_RW_R16 (unsigned int)1 21 #define KERNEL_RW_R32 (unsigned int)6 22 23 #define KERNEL_RW_W8 (unsigned int)3 24 #define KERNEL_RW_W16 (unsigned int)4 25 #define KERNEL_RW_W32 (unsigned int)5 26 27 /* 28 Usage: ./reg_editor bit位数 读的地址 数据的个数 29 读取内核寄存器: 30 ./reg_editor r8 addr [num] 31 ./reg_editor r16 addr [num] 32 ./reg_editor r32 addr [num] 33 34 Usage: ./reg_editor bit位数 写的地址 数据 35 写入内核寄存器: 36 ./reg_editor w8 addr val 37 ./reg_editor w16 addr val 38 ./reg_editor w32 addr val 39 */ 40 41 void print_usage(char *file) 42 { 43 printf("Usage: \n"); 44 printf("%s
[num]\n",file); 45 printf("%s
\n",file); 46 } 47 48 int main(int argc, char **argv) 49 { 50 int fd; 51 unsigned int buf[2]; 52 unsigned int i; 53 unsigned int num; 54 55 buf[0] = 0; 56 buf[1] = 1; 57 58 if((argc != 3) && (argc != 4)){ 59 print_usage(argv[0]); 60 return -1; 61 } 62 63 fd = open("/dev/kernel_rw", O_RDWR); 64 if(fd < 0){ 65 printf("can't open /dev/kernel_rw "); 66 return -1; 67 } 68 buf[0] = strtoul(argv[2], NULL, 0); 69 70 if (argc == 4) 71 { 72 buf[1] = strtoul(argv[3], NULL, 0); 73 num = buf[1]; 74 } 75 else 76 { 77 num = 1; 78 } 79 80 if(strcmp(argv[1], "r8") == 0){ 81 for(i = 0; i< num; i++){ 82 ioctl(fd, KERNEL_RW_R8, buf); //结果放在buf[1]里 83 printf("%02d. [%08x] = %02x\n",i,buf[0],(unsigned char )buf[1]); 84 buf[0] += 1; //地址加1 85 } 86 }else if(strcmp(argv[1], "r16") == 0){ 87 for(i = 0; i< num; i++){ 88 ioctl(fd, KERNEL_RW_R16, buf); //结果放在buf[1]里 89 printf("%02d. [%08x] = %02x\n",i,buf[0],(unsigned short )buf[1]); 90 buf[0] += 2; //地址加2 91 } 92 }else if(strcmp(argv[1], "r32") == 0){ 93 for(i = 0; i< num; i++){ 94 ioctl(fd, KERNEL_RW_R32, buf); //结果放在buf[1]里 95 96 printf("%02d. [%08x] = %02x\n",i,buf[0],(unsigned short )buf[1]); 97 buf[0] += 2; //地址加2 98 } 99 }else if(strcmp(argv[1], "w8") == 0){100 ioctl(fd, KERNEL_RW_W8, buf); //addr = buf[0] val = buf[1]101 }else if(strcmp(argv[1], "w16") == 0){102 ioctl(fd, KERNEL_RW_W16, buf); //addr = buf[0] val = buf[1]103 }else if(strcmp(argv[1], "w32") == 0){104 ioctl(fd, KERNEL_RW_W32, buf); //addr = buf[0] val = buf[1]105 }else{106 print_usage(argv[0]);107 return -1;108 }109 110 return 0;111 }112 113 /*114 0x53FCC000 0x53FC_FFFF 16 Kbytes GPIO-1115 116 */
reg_editor.c

 

.err_led驱动程序

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 15 #define Driver_NAME "err_led_dev" 16 #define DEVICE_NAME "err_led_dev" 17 18 static int major = 0; 19 20 #define LED_ON 0 21 #define LED_OFF 1 22 23 24 //auto to create device node 25 static struct class *drv_class = NULL; 26 static struct class_device *drv_class_dev = NULL; 27 28 //寄存器基址; 29 static unsigned long mem_iomux; 30 static unsigned long mem_gpio3; 31 static unsigned long base_iomux; //iomux基址 0X 43FA C000 - 0X 43FA FFFF 32 static unsigned long base_gpio3; //gpio3 0X 53FA 4000 - 0X 53FA 7FFF 33 // MUX_CTL模式选择 配置寄存器 34 #define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060)) 35 // PAD_CTL GPIO常用功能设置 36 #define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270)) 37 // GPIO DR 数据寄存器 DR 38 #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000)) 39 // GPIO GDIR 方向控制寄存器 GDIR 40 #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004)) 41 42 43 static int key_open(struct inode *inode, struct file *file) 44 { 45 printk("<0>function open!\n\n"); 46 return 0; 47 } 48 49 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) 50 { 51 return 0; 52 } 53 54 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) 55 { 56 printk("<0>function write!\n\n"); 57 return 1; 58 } 59 60 static int key_release(struct inode *inode, struct file *filp) 61 { 62 printk("<0>function write!\n\n"); 63 return 0; 64 } 65 66 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg) 67 { 68 printk("<0>function ioctl!\n\n"); 69 70 switch(command) 71 { 72 case LED_ON: 73 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零 亮 74 break; 75 case LED_OFF: 76 77 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1 灭 78 break; 79 default: 80 break; 81 } 82 83 return 0; 84 } 85 static struct file_operations key_fops = { 86 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ 87 .open = key_open, 88 .read = key_read, 89 .write = key_write, 90 .release= key_release, 91 .ioctl = key_ioctl, 92 }; 93 94 void gpio_addr(void){ 95 printk("<0>addr base_iomux : %x \n",base_iomux); 96 printk("<0>addr base_gpio3 : %x \n",base_gpio3); 97 printk("<0>addr MUX_CTL : %x \n",&MUX_CTL); 98 printk("<0>addr PAD_CTL : %x \n",&PAD_CTL); 99 printk("<0>addr GDIR_GPIO3 : %x \n",&GDIR_GPIO3);100 printk("<0>addr DR_GPIO3 : %x \n",&DR_GPIO3);101 }102 103 104 105 void led_on_off(void){106 ssleep(1);107 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1108 ssleep(1);109 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零110 ssleep(1);111 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1112 ssleep(1);113 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零114 ssleep(1);115 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1116 ssleep(1);117 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零118 ssleep(1);119 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1120 ssleep(1);121 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零122 ssleep(1);123 DR_GPIO3 |= (0x01 << 23); //将GPIO2_23置1124 }125 126 static int __init key_irq_init(void)127 {128 printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);129 //register and mknod130 major = register_chrdev(0,Driver_NAME,&key_fops);131 drv_class = class_create(THIS_MODULE,Driver_NAME);132 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/133 134 //IO端口申请 ioremap 可以直接通过指针来访问这些地址135 base_iomux = ioremap(0x43FAC000,0xFFF);136 base_gpio3 = ioremap(0x53FA4000,0xFFF);137 138 //MUX_CTL139 MUX_CTL &= ~(0x07 << 0); 140 MUX_CTL |= (0X05 << 0); //设置为ALT5 GPIO3_23 ERR_LED141 //PAD_CTL142 PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0); //1.8v 不需要上拉下拉 CMOS输出 slew rate143 //GDIR_GPIO3 配置为输出模式144 GDIR_GPIO3 &= ~(0x01 << 23); 145 GDIR_GPIO3 |= (0x01 << 23); //配置为输出模式 146 147 //DR_GPIO3 配置为输出0 点亮ERR_LED148 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零149 DR_GPIO3 &= ~(0x01 << 23); //将GPIO2_23清零150 gpio_addr();151 led_on_off();152 return 0; 153 }154 155 static void __exit key_irq_exit(void)156 {157 gpio_addr();158 printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);159 led_on_off();160 161 unregister_chrdev(major,Driver_NAME);162 device_unregister(drv_class_dev);163 class_destroy(drv_class);164 165 //释放IO端口166 iounmap(base_iomux);167 iounmap(base_gpio3);168 }169 170 171 /* 这两行指定驱动程序的初始化函数和卸载函数 */172 module_init(key_irq_init);173 module_exit(key_irq_exit);174 175 /* 描述驱动程序的一些信息,不是必须的 */176 MODULE_AUTHOR("Lover雪儿");177 MODULE_VERSION("0.1.0");178 MODULE_DESCRIPTION("IMX257 key Driver");179 MODULE_LICENSE("GPL");
err_led.c

 

.err_led测试程序.

1 /****************************** 2 内核调试之自制寄存器读写工具(应用) 3  *****************************/ 4 #include 
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 18 #define LED_ON 019 #define LED_OFF 120 21 /* 22 Usage: 23 ./err_led_test
24 */25 26 void print_usage(char *file)27 {28 printf("Usage: \n");29 printf("%s
\n",file);30 }31 32 int main(int argc, char **argv)33 {34 int fd ;35 36 if(argc != 2){37 print_usage(argv[0]);38 return -1;39 }40 41 fd = open("/dev/err_led_dev", O_RDWR);42 if(fd < 0){43 printf("can't open /dev/err_led_dev \n");44 return -1;45 }46 47 if(strcmp(argv[1], "on") == 0){48 ioctl(fd, LED_ON); 49 }else if(strcmp(argv[1], "off") == 0){50 ioctl(fd, LED_OFF);51 }else{52 print_usage(argv[0]);53 return -1;54 }55 56 return 0;57 }
err_led_test.c

 

.编译测试

步骤:

加载err_led.ko

加载kernel_rw.ko

使用reg_editor应用程序读取 0x53fa4002 led灯引脚的数据

使用err_led的应用程序熄灭led

再次使用reg_editor应用程序读取 0x53fa4002 led灯引脚的数据

使用reg_editor应用程序往0x53fa4000地址写入1000000,观察LED是否熄灭

使用reg_editor应用程序往0x53fa4000地址写入0000000,观察LED是否点亮

1 //加载 kernel_rw.ko 2 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# insmod kernel_rw.ko  3 kernel_rw_init 4 //读取地址 0x53fa4002的数据,由于此时灯是亮的,所以数据为0x05 5 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# ./app/reg_editor r32 0x53fa4002  6 enter r32 7 00. [53fa4002] = 05 8 //熄灭led灯,也就是给led的引脚高电平 9 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# ./err_gpio/app/err_led_test off10 function open!11 //再次 读取地址 0x53fa4002的数据,发现数据变为85了12 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# ./app/reg_editor r32 0x53fa4002 13 enter r3214 00. [53fa4002] = 8515 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw#16 17 *********************************************************************18 写地址:灭灯19 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# ./app/reg_editor w32 0x520 3fa4000 1000000021 er w32, val = 989680  灯被熄灭22 23 写地址:亮灯24 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw# ./app/reg_editor w32 0x525 3fa4000 0000000026  val = 0   写完后,发现IMX257板子的LED被点亮27 28 root@EasyARM-iMX257 /mnt/nfs/module/38_debug_kernel_rw#

 

如图所示:

转载于:https://www.cnblogs.com/lihaiyan/p/4470390.html

你可能感兴趣的文章
[转]免费api大全
查看>>
python函数调用顺序、高阶函数、嵌套函数、闭包详解
查看>>
git 认证问题之一的解决 : http ssh 互换
查看>>
sql where 1=1作用
查看>>
搜索算法----二分查找
查看>>
Python语言编程
查看>>
事务并发、事务隔离级别 .
查看>>
[poj 1469]Courses
查看>>
Xcode8出现AQDefaultDevice(173):Skipping input stram 0 0 0x0
查看>>
数据结构(二十四)二叉树的链式存储结构(二叉链表)
查看>>
LeetCode刷题笔记(2)HashMap相关应用
查看>>
Material Design Lite,简洁惊艳的前端工具箱 之 布局组件。
查看>>
关于bootstrap Modal弹窗 滚动条的问题
查看>>
Django----------路由控制
查看>>
将数字转化为字符串的快捷方式
查看>>
JAVA 序列化 与 反序列化
查看>>
java23种设计模式
查看>>
冲刺周期一--站立会议04
查看>>
支持IE6以上阴影效果纯CSS
查看>>
优化算法与特征缩放
查看>>