• 寄存器调试 (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
    ");
        err = misc_register(&sunxi_reg_dev);
        if(err) {
            printk(KERN_ERR "%s register sunxi debug register driver as misc device error
    ", __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
    ", __func__);
    exit:
        return err;
    }
    
    static void __exit sunxi_reg_exit(void) {
        printk("sunxi_reg_exit enter
    ");
        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 ", sizeof("0xf1c20000 "));

    注意字符串请以换行符' '结尾.

    (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
    "
    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!
    ", __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!
    ", __func__, __LINE__, in_buf);
            goto end;
        }
        printf("%s(%d): write %s success!
    ", __func__, __LINE__, in_buf);
        /* seek to begin */
        if(lseek(fd, 0, SEEK_SET) < 0) {
            printf("%s(%d): seek to begin failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): seek to begin success!
    ", __func__, __LINE__);
        /* show output value */
        ret = read(fd, out_buf, sizeof(out_buf));
        if(ret < 0) {
            printf("%s(%d): read failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        value = strtoul(out_buf, NULL, 16);
        printf("%s(%d): read success! out string "%s", value 0x%08x
    ", __func__, __LINE__, out_buf, value);
        /* return success */
        ret = 0;
    end:
        if(fd)
            close(fd);
        return ret;
    }

    运行结果打印:

     

     

    2. 获取一组寄存器值

     

    示例代码:

    #define DUMP_TEST_STRING    "0xf1c20000,0xf1c20020
    "
    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!
    ", __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!
    ", __func__, __LINE__, in_buf);
            goto end;
        }
        printf("%s(%d): write %s success!
    ", __func__, __LINE__, in_buf);
        /* seek to begin */
        if(lseek(fd, 0, SEEK_SET) < 0) {
            printf("%s(%d): seek to begin failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): seek to begin success!
    ", __func__, __LINE__);
        /* show output value */
        ret = read(fd, out_buf, sizeof(out_buf));
        if(ret < 0) {
            printf("%s(%d): read failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): read success! out string "%s"
    ", __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
    "
    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!
    ", __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!
    ", __func__, __LINE__, in_buf);
            goto end;
        }
        printf("%s(%d): write "%s" success!
    ", __func__, __LINE__, in_buf);
        /* seek to begin */
        if(lseek(fd, 0, SEEK_SET) < 0) {
            printf("%s(%d): seek to begin failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): seek to begin success!
    ", __func__, __LINE__);
        /* show output value */
        ret = read(fd, out_buf, sizeof(out_buf));
        if(ret < 0) {
            printf("%s(%d): read failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): read success! out string "%s"
    ", __func__, __LINE__, out_buf);
        /* return success */
        ret = 0;
    end:
        if(fd)
            close(fd);
        return ret;
    }

     

    4. 写一组寄存器值

    示例代码:

    #define WRITE_TEST_STRING    "0xf1c20800 0x00000031,0xf1c20818 0x55555555
    "
    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!
    ", __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!
    ", __func__, __LINE__, in_buf);
            goto end;
        }
        printf("%s(%d): write "%s" success!
    ", __func__, __LINE__, in_buf);
        /* seek to begin */
        if(lseek(fd, 0, SEEK_SET) < 0) {
            printf("%s(%d): seek to begin failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): seek to begin success!
    ", __func__, __LINE__);
        /* show output value */
        ret = read(fd, out_buf, sizeof(out_buf));
        if(ret < 0) {
            printf("%s(%d): read failed, err!
    ", __func__, __LINE__);
            goto end;
        }
        printf("%s(%d): read success! out string "%s"
    ", __func__, __LINE__, out_buf);
        /* return success */
        ret = 0;
    end:
        if(fd)
            close(fd);
        return ret;
    }

     

  • 相关阅读:
    JavaWeb与JSP初识
    doT.js灵活运用之嵌入使用
    避免数据二次提交的处理方式
    Intellij Idea创建的第一个JavaWeb程序
    JavaWeb简单介绍
    Java网络编程初探
    windows下如何安装和启动MySQL
    PhpStorm配置svn时提示需要证书:authentication required的解决方法,总是弹出
    正则神器,RegexBuddy
    2-3 tree使用
  • 原文地址:https://www.cnblogs.com/zhangyin-ethan/p/7487352.html
Copyright © 2020-2023  润新知