-
应用层通过C代码访问
除了前面所述通过shell命令访问寄存器外, 还支持通过C代码访问.
驱动层通过注册miscdevice设备, 实现了对应用层open/write/read等标准api的支持.
static DEVICE_ATTR(dump, 0644, misc_dump_show, misc_dump_store); static DEVICE_ATTR(compare, 0644, misc_compare_show, misc_compare_store); static DEVICE_ATTR(write, 0644, misc_write_show, misc_write_store); static struct attribute *misc_attributes[] = { &dev_attr_dump.attr, &dev_attr_compare.attr, &dev_attr_write.attr, NULL }; static struct attribute_group misc_attribute_group = { .name = "rw", .attrs = misc_attributes }; static struct miscdevice sunxi_reg_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "sunxi-reg", }; |
模块初始化时,通过sunxi_reg_init注册misc设备到内核, 并将属性组设为misc_attribute_group.
static int __init sunxi_reg_init(void) { int err; printk(KERN_INFO "sunxi_reg_init enter\n"); err = misc_register(&sunxi_reg_dev); if(err) { printk(KERN_ERR "%s register sunxi debug register driver as misc device error\n", __func__); goto exit; } err = sysfs_create_group(&sunxi_reg_dev.this_device->kobj, &misc_attribute_group); if(err) printk("%s err: sysfs_create_group failed\n", __func__); exit: return err; } static void __exit sunxi_reg_exit(void) { printk("sunxi_reg_exit enter\n"); WARN_ON(0 != misc_deregister(&sunxi_reg_dev)); sysfs_remove_group(&sunxi_reg_dev.this_device->kobj, &misc_attribute_group); } module_init(sunxi_reg_init); module_exit(sunxi_reg_exit); |
-
获取单个寄存器值
按以下步骤:
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0xf1c20000\n", sizeof("0xf1c20000\n")); |
注意字符串请以换行符'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 读取寄存器值字符串. 保存到buff.
char buf[20]; read(fd, buf, sizeof(buf)); |
- 将字符串转化成整型值
value = strtoul(buf, NULL, 16); |
示例代码:
#define DUMP_TEST_STRING "0xf1c20000\n" int test_dump_reg(void) { unsigned long value = 0; int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, DUMP_TEST_STRING); ret = write(fd, in_buf, strlen(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write %s success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } value = strtoul(out_buf, NULL, 16); printf("%s(%d): read success! out string \"%s\", value 0x%08x\n", __func__, __LINE__, out_buf, value); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |
运行时打印:
test_dump_reg(56): write 0xf1c20000 success! test_dump_reg(62): seek to begin success! test_dump_reg(70): read success! out string "0x90001410 ", value 0x90001410 |
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0xf1c20000,0xf1c20020\n", sizeof("0xf1c20000,0xf1c20020\n")); |
0xf1c20000为起始寄存器, 0xf1c20020为末尾寄存器.
注意字符串请以换行符'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 读取寄存器值字符串. 保存到buf.
char buf[20]; read(fd, buf, sizeof(buf)); |
- 从buf中解析出需要的寄存器值
此步和"获取单个寄存器值"不同, 需要自行解析buf内容, 提取出寄存器值. buf内容格式如下:
0xf1c20000: 0x90001410 0x00000000 0x90035514 0x00000000 0xf1c20010: 0x93001300 0x00000000 0x93001801 0x00000000 0xf1c20020: 0x90000911 |
注意: 上述最后一行(0xf1c20020所在行)末尾为若干个补齐的空格.
示例代码:
#define DUMP_TEST_STRING "0xf1c20000,0xf1c20020\n" int test_dump_reg(void) { unsigned long value = 0; int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, DUMP_TEST_STRING); ret = write(fd, in_buf, strlen(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write %s success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf); /* 这里需自行从buf中解析出需要的寄存器值 */ ... //value = strtoul(out_buf, NULL, 16); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0x01f01018 0x000000a0\n", sizeof("0x01f01018 0x000000a0\n")); |
0x01f01018为寄存器地址, 0x000000a0为待写入的值, 之间有且仅有一个空格.
注意字符串请以换行符'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 通过read发起sysfs的xxx_show调用, 执行写操作. 返回信息保存到buf.
char buf[20]; read(fd, buf, sizeof(buf)); |
- 由于写操作已完成, buf内容可以不处理:
reg to_write after_write 0x01f01018 0x000000a1 0x000000a1 |
示例代码:
#define WRITE_TEST_STRING "0x01f01018 0x000000a0\n" int test_write_reg(void) { int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, WRITE_TEST_STRING); ret = write(fd, in_buf, sizeof(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0xf1c20800 0x00000031,0xf1c20818 0x55555555\n", sizeof("0xf1c20800 0x00000031,0xf1c20818 0x55555555\n")); |
格式请参考3.1.6"写一组寄存器值"章节, 注意字符串以'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 通过read发起sysfs的xxx_show调用, 执行写操作. 返回信息保存到buf.
char buf[20]; read(fd, buf, sizeof(buf)); |
- 由于写操作已完成, buf内容可以不处理. Buf内容如下:
reg to_write after_write 0xf1c20800 0x00000031 0x00000031 0xf1c20818 0x55555555 0x00555555 |
示例代码:
#define WRITE_TEST_STRING "0xf1c20800 0x00000031,0xf1c20818 0x55555555\n" int test_write_reg(void) { int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, WRITE_TEST_STRING); ret = write(fd, in_buf, sizeof(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/compare", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0x01f01018 0x000000a0 0x000000a0\n", sizeof("0x01f01018 0x000000a0 0x000000a0\n")); |
格式请参考3.1.3"比较单个寄存器值"章节, 注意字符串以'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 通过read发起sysfs的xxx_show调用, 执行比较操作. 返回信息保存到buf.
char buf[20]; read(fd, buf, sizeof(buf)); |
- buf内容为比较结果:
reg expect actual mask result 0x01f01018 0x000000a0 0x000000a0 0x000000a0 OK |
结果分析请参考3.1.3章节.
示例代码:
#define COMPARE_TEST_STRING "0x01f01018 0x000000a0 0x000000a0\n" int test_compare_reg(void) { int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/compare", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, COMPARE_TEST_STRING); ret = write(fd, in_buf, strlen(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |
- 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/compare", O_RDWR); |
- 传递寄存器地址给内核.
write(fd, "0xf1c20010 0x03006207 0x03006207,0xf1c20020 0x00001000 0x00001000,0xf1c20028 0x80000000 0x80000000\n", sizeof("0xf1c20010 0x03006207 0x03006207,0xf1c20020 0x00001000 0x00001000,0xf1c20028 0x80000000 0x80000000\n")); |
格式请参考3.1.4"比较一组寄存器值"章节, 注意字符串以'\n'结尾.
- 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET); |
- 通过read发起sysfs的xxx_show调用, 执行比较操作. 返回信息保存到buf.
char buf[20]; read(fd, buf, sizeof(buf)); |
- buf内容为比较结果:
reg expect actual mask result 0xf1c20010 0x03006207 0x93001300 0x03006207 ERR 0xf1c20020 0x00001000 0x90000911 0x00001000 ERR 0xf1c20028 0x80000000 0x90041811 0x80000000 OK |
结果分析请参考3.1.4章节.
示例代码:
#define COMPARE_TEST_STRING "0xf1c20010 0x03006207 0x03006207,0xf1c20020 0x00001000 0x00001000,0xf1c20028 0x80000000 0x80000000\n" int test_compare_reg(void) { int fd = 0, ret = -1; char in_buf[250] = {0}, out_buf[250] = {0}; fd = open("/sys/class/misc/sunxi-reg/rw/compare", O_RDWR); if(0 == fd) { printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__); goto end; } /* store para */ strcpy(in_buf, COMPARE_TEST_STRING); ret = write(fd, in_buf, strlen(in_buf)); if(ret < 0) { printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf); goto end; } printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf); /* seek to begin */ if(lseek(fd, 0, SEEK_SET) < 0) { printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): seek to begin success!\n", __func__, __LINE__); /* show output value */ ret = read(fd, out_buf, sizeof(out_buf)); if(ret < 0) { printf("%s(%d): read failed, err!\n", __func__, __LINE__); goto end; } printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf); /* return success */ ret = 0; end: if(fd) close(fd); return ret; } |