驱动调试(五)寄存器读写

驱动调试(五)寄存器读写

这个章节没什么新知识,就是先写一个能够读写寄存器的驱动,再写一个app调用提供的读写接口

bug

这里应该有个问题,就是当传入的地址不是4字节对齐的时候,读取u32的时候,指针转换是有问题的,但实际上这也属于app传输进来的错误

驱动程序#

Copy
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <linux/poll.h> #include <linux/device.h> #define KER_RW_R8 0 #define KER_RW_R16 1 #define KER_RW_R32 2 #define KER_RW_W8 3 #define KER_RW_W16 4 #define KER_RW_W32 5 static int major; static struct class *class; static struct class_device *ker_dev; static int ker_rw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { volatile unsigned char *p8; volatile unsigned short *p16; volatile unsigned int *p32; unsigned int val; unsigned int addr; unsigned int buf[2]; copy_from_user(buf, (const void __user *)arg, 8); addr = buf[0]; val = buf[1]; p8 = (volatile unsigned char *)ioremap(addr, 4); p16 = p8; p32 = p8; switch (cmd) { case KER_RW_R8: { val = *p8; copy_to_user((void __user *)(arg+4), &val, 4); break; } case KER_RW_R16: { val = *p16; copy_to_user((void __user *)(arg+4), &val, 4); break; } case KER_RW_R32: { val = *p32; copy_to_user((void __user *)(arg+4), &val, 4); break; } case KER_RW_W8: { *p8 = val; break; } case KER_RW_W16: { *p16 = val; break; } case KER_RW_W32: { *p32 = val; break; } } iounmap(p8); return 0; } static struct file_operations ker_rw_ops = { .owner = THIS_MODULE, .ioctl = ker_rw_ioctl, }; static int ker_rw_init(void) { major = register_chrdev(0, "ker_rw", &ker_rw_ops); class = class_create(THIS_MODULE, "ker_rw"); /* 为了让mdev根据这些信息来创建设备节点 */ ker_dev = class_device_create(class, NULL, MKDEV(major, 0), NULL, "ker_rw"); /* /dev/ker_rw */ return 0; } static void ker_rw_exit(void) { class_device_unregister(ker_dev); class_destroy(class); unregister_chrdev(major, "ker_rw"); } module_init(ker_rw_init); module_exit(ker_rw_exit); MODULE_LICENSE("GPL");

APP程序#

Copy
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <poll.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #define KER_RW_R8 0 #define KER_RW_R16 1 #define KER_RW_R32 2 #define KER_RW_W8 3 #define KER_RW_W16 4 #define KER_RW_W32 5 /* Usage: * ./regeditor r8 addr [num] * ./regeditor r16 addr [num] * ./regeditor r32 addr [num] * * ./regeditor w8 addr val * ./regeditor w16 addr val * ./regeditor w32 addr val */ void print_usage(char *file) { printf("Usage:\n"); printf("%s <r8 | r16 | r32> <phy addr> [num]\n", file); printf("%s <w8 | w16 | w32> <phy addr> <val>\n", file); } int main(int argc, char **argv) { int fd; unsigned int buf[2]; unsigned int i; unsigned int num; if ((argc != 3) && (argc != 4)) { print_usage(argv[0]); return -1; } fd = open("/dev/ker_rw", O_RDWR); if (fd < 0) { printf("can't open /dev/ker_rw\n"); return -2; } /* addr */ buf[0] = strtoul(argv[2], NULL, 0); if (argc == 4) { buf[1] = strtoul(argv[3], NULL, 0); num = buf[1]; } else { num = 1; } if (strcmp(argv[1], "r8") == 0) { for ( i = 0; i < num; i++) { ioctl(fd, KER_RW_R8, buf); /* val = buf[1] */ printf("%02d. [%08x] = %02x\n", i, buf[0], (unsigned char)buf[1]); buf[0] += 1; } } else if (strcmp(argv[1], "r16") == 0) { for ( i = 0; i < num; i++) { ioctl(fd, KER_RW_R16, buf); /* val = buf[1] */ printf("%02d. [%08x] = %02x\n", i, buf[0], (unsigned short)buf[1]); buf[0] += 2; } } else if (strcmp(argv[1], "r32") == 0) { for ( i = 0; i < num; i++) { ioctl(fd, KER_RW_R32, buf); /* val = buf[1] */ printf("%02d. [%08x] = %02x\n", i, buf[0], (unsigned int)buf[1]); buf[0] += 4; } } else if (strcmp(argv[1], "w8") == 0) { ioctl(fd, KER_RW_W8, buf); /* val = buf[1] */ } else if (strcmp(argv[1], "w16") == 0) { ioctl(fd, KER_RW_W16, buf); /* val = buf[1] */ } else if (strcmp(argv[1], "w32") == 0) { ioctl(fd, KER_RW_W32, buf); /* val = buf[1] */ } else { printf(argv[0]); return -1; } return 0; }
posted @   zongzi10010  阅读(1449)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示
CONTENTS