寄存器调试 (2):应用层通过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);
1. 获取单个寄存器的的值
按以下步骤:
(1) 打开sysfs设备节点.
fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR);
(2) 传递寄存器地址给内核.
write(fd, "0xf1c20000\n", sizeof("0xf1c20000\n"));
注意字符串请以换行符'\n'结尾.
(3) 将读写指针移植文件首.
lseek(fd, 0, SEEK_SET);
(4) 读取寄存器值字符串. 保存到buff.
char buf[20];
read(fd, buf, sizeof(buf));
(5) 将字符串转化成整型值
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;
}
运行结果打印:
2. 获取一组寄存器值
示例代码:
#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;
}
3. 写单个寄存器值
示例代码:
#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;
}
4. 写一组寄存器值
示例代码:
#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;
}