• 全智V5+AXP233电源管理芯片调试


    AXP233驱动调试记录

    问题描述

    遇到的最关键的问题就是:

    AXP233是挂在了I2C-0的设备节点上,因为现在的V5的限制,I2C-0这个设备节点,无法在应用层直接操作。

    解决办法:

    只能开发一个内核驱动,在驱动中抛出应用层可以操作的接口,应用层调用这个接口,这样就可以曲线救国进行控制AXP233了。

    具体修改方案

    linux-4.4内核的power相关的驱动位置:linux-4.4\drivers\power

    power目录下有个axp目录,可见axpXXX系列的电源驱动都放在了这个目录下面,

    打开之后,可以看到axp目录中有axp22x的目录,

    位置:linux-4.4\drivers\power\axp\axp22x

    这个axp22x的目录就是存放axp22x所有的源代码。

    axp22x.h和axp22x.c就是首先要看的源代码。

    目前为止axp22x中实现了axp221s、axp227、axp223三个电源管理芯片的驱动。是一个大合集。

    然后就可以在这个基础上做些工作了:

    1、使用misc_register来注册一个特殊的字符设备,给应用层抛出可操作的接口。

    misc_device是特殊字符设备。注册驱动程序时采用misc_register函数注册,此函数中会自动创建设备节点,即设备文件。无需mknod指令创建设备文件。因为misc_register()会调用class_device_creat或者device_creat().

    https://www.cnblogs.com/ggzhangxiaochao/p/12894883.html 这个解释的挺好的

    我主要添加的代码:

    
    
    /*********************************************************
     * 20230920 zh add 
     * 控制AXP233电源管理芯片,为应用层程序提供控制接口
     **********************************************************/ 
    
    static ssize_t axp233_ctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
    {
        char my_data[] = "Hello from Kernel!\n";
        size_t len = strlen(my_data);
        
        if (*ppos >= len)
            return 0;
    
        if (count > len - *ppos)
            count = len - *ppos;
    
        if (copy_to_user(buf, my_data + *ppos, count)) {
            return -EFAULT;
        }
    
        *ppos += count;
        return count;
    }
    
    static ssize_t axp233_ctrl_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
    {
        char user_data[256];
        
        if (count >= sizeof(user_data)) {
            return -EINVAL;
        }
    
        if (copy_from_user(user_data, buf, count)) {
            return -EFAULT;
        }
    
        user_data[count] = '\0';
        printk("[zh] recv from User user_data: %s\n", user_data);
        printk("[zh] recv from User count: %d\n", count);
    
        if(strcasecmp(user_data, "power_off") == 0){
            printk("[zh] 关机 \n");
            // axp22x_power_off();
    
    		pr_info("[axp] off zhenghui ############!\n");
    		axp_regmap_set_bits(axp22x_pm_power->regmap, AXP22X_OFF_CTL, 0x80);
        }
    
        return count;
    }
    
    static const struct file_operations axp233_ctrl_fops = {
        .owner = THIS_MODULE,
        .read = axp233_ctrl_read,
        .write = axp233_ctrl_write,
    };
    
    static struct miscdevice axp233_misc_device = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "axp233_misc_device",
        .fops = &axp233_ctrl_fops,
    };
    
    static int axp233_ctrl_init(void)
    {
        int ret = misc_register(&axp233_misc_device);
        if (ret) {
            pr_err("[zh]Failed to register misc device\n");
            return ret;
        }
        
        pr_info("[zh]Misc device registered: %s\n", axp233_misc_device.name);
        return 0;
    }
    
    static void axp233_ctrl_exit(void)
    {
        misc_deregister(&axp233_misc_device);
        pr_info("[zh]Misc device unregistered\n");
    }
    
    
    // end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    根据AXP233手册里描述,关机调用需要给寄存器REG32H[7]写入1,即可操作AXP233关机

    根据axp22x.c代码的风格,里面写使用的是axp_regmap_set_bits函数,读数据使用的是axp_regmap_read函数

    而且在axp22x.h头文件中定义了:

    #define AXP22X_OFF_CTL             (0x32)
    
    • 1

    所以可以模仿着写,即可:

    axp_regmap_set_bits(axp22x_pm_power->regmap, AXP22X_OFF_CTL, 0x80);
    
    • 1

    ===== 应用层 =====

    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main() {
        int fd;
        char buffer[256];
        ssize_t bytes_read;
    
        fd = open("/dev/axp233_misc_device", O_RDWR);
        if (fd == -1) {
            perror("打开 axp233_misc_device 失败 \n");
            return 1;
        }
    
        printf("######## #### #### #### ####  \n");
        printf("正在读数据:\n");
        bytes_read = read(fd, buffer, sizeof(buffer));
        if (bytes_read == -1) {
            perror("读数据失败 \n");
            close(fd);
            return 1;
        }
    
        buffer[bytes_read] = '\0';
        printf("读取到的数据: %s\n", buffer);
        printf("######## #### #### #### ####  \n");
    
        printf("######## #### #### #### ####  \n");
    
        printf("正在写数据:\n");
        const char *data_to_send = "power_off";
        ssize_t bytes_written = write(fd, data_to_send, strlen(data_to_send));
        if (bytes_written == -1) {
            perror("写数据失败 \n");
        } else {
            printf("写数据: %s \n", data_to_send);
        }
    
        close(fd);
        printf("######## #### #### #### ####  \n");
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    ===== 然后就可以进行交互了 =====

    root@xxx:/mnt/appslog# 
    root@xxxx:/mnt/appslog# ./my_app 
    ######## #### #### #### ####  
    
    正在读数据:
    读取到的数据: Hello from Kernel!
    
    ######## #### #### #### ####  
    ######## #### #### #### ####  87.297512] [zh] recv from User user_data: power_off
    [   87.316995] [zh] recv from User count: 9
    据:
    [   87.321409] sunxi_i2s_preapre,SNDRV_PCM_STATE_XRUN:playback xrun.
    [   87.321409] [zh] 关机 
    [   87.332323] [axp] off zhenghui ############!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    dds:subscribe
    educoder:实验十一 函数
    数据特征选择 | Lasso特征选择(Python)
    嵌入式软件架构设计-程序分层
    Nginx网站服务
    2019银川icpc F 数论分块,技巧
    脆而不倒谷草兼用脆秆水稻被发掘 国稻种芯百团计划行动
    vue3的设计思路(3)组件的本质
    学Java对一个专科生,对一个穷人来说,是一条好的出路吗?
    【java学习】一维数组(9)
  • 原文地址:https://blog.csdn.net/qq_17623363/article/details/133088629