ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux driver --- platform框架应用完整实例

2022-09-04 23:01:17  阅读:204  来源: 互联网

标签:__ button driver --- platform static device include


平台设备文件

button_device.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>

static void button_release(struct device *dev)
{
    printk("%s\n", __FUNCTION__);
    return;
}

struct resource    button_resource[] = {
    {
        .start = 0x20c406c,
        .end = 0x20c406c+3,        // IORESOURCE_MEM必须要加上end,不然会报错
        .name = "CCGR",
        .flags = IORESOURCE_MEM,
    },
    {
        .start = 0x229000c,
        .end = 0x229000c+3,
        .name = "SW_MUX_CTL",
        .flags = IORESOURCE_MEM,
    },
    {
        .start = 0x2290050,
        .end = 0x2290050+3,
        .name = "SW_PAD_CTL",
        .flags = IORESOURCE_MEM,
    },
    {
        .start = 0x20ac004,
        .end = 0x20ac004+3,
        .name = "GDIR",
        .flags = IORESOURCE_MEM,
    },
    {
        .start = 0x20ac008,
        .end = 0x20ac008+3,
        .name = "PSR",
        .flags = IORESOURCE_MEM,
    },
    {
        .start = 1,
        .end = 0,
        .name = "pin",
        .flags = IORESOURCE_IRQ,
    },
    {
        .start = 30,
        .end = 0,
        .name = "clock_offset",
        .flags = IORESOURCE_IRQ,
    },
};

struct platform_device button_device = {
    .name = "my_button",     // 这个名字必须要和设备资源结构体里面的name一致,不然这两个模块匹配不了
    .id = -1,
    .num_resources = ARRAY_SIZE(button_resource),
    .resource = button_resource,
    .dev = {
        .release = button_release,
    },
};

// 入口函数
static int button_platform_device_init(void)
{
    int ret = 0;
    printk("%s\n", __FUNCTION__);
    ret = platform_device_register(&button_device);  // 注册设备信息
    return ret;
}

// 出口函数
static void button_platform_device_exit(void)
{
    printk("%s\n", __FUNCTION__);

    platform_device_unregister(&button_device);
}

module_init(button_platform_device_init);
module_exit(button_platform_device_exit);
MODULE_LICENSE("GPL");

平台驱动文件

button_driver.c

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <asm/mach/map.h>
#include <linux/platform_device.h>
#include <asm/io.h>

static u32 *vi_ccgr;
static u32 *vi_mux_ctl;
static u32 *vi_pad_ctl;
static u32 *vi_gdir;
static u32 *vi_psr;
static u32 pin;
static u32 clock_offset;

static int major = 0;
static struct class *button_class;

static ssize_t button_drv_read(struct file * file, char __user * buf, size_t size, loff_t *offset)
{
    char status = 0;
    int ret;
    if (*vi_psr & (1<<pin)) {
        //printk("按键点击了\n");
        status = 1;
    } else {
        status = 0;
    }

    ret = copy_to_user(buf, &status, 1);
    return 1;
}

static ssize_t button_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{

    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}

static int button_drv_open(struct inode *node, struct file *file)
{
    
    // 初始化设备
    *(vi_ccgr) |= (3<<clock_offset);
    *(vi_mux_ctl) &= ~0xf;
    *(vi_mux_ctl) |= 0x5;
    *(vi_gdir) &= ~(1<<pin);
    
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}
static int button_drv_close(struct inode *node, struct file *file)
{
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    return 0;
}
static struct file_operations button_opr = {
    .open = button_drv_open,
    .release = button_drv_close,
    .read = button_drv_read,
    .write = button_drv_write,
};

static int button_probe(struct platform_device *pdev)
{
    int i = 0;
    struct resource *res;
    u32 ph_addr[5];
    int err;

    // 获取资源

    for (i=0;i<5;i++) {
        res = platform_get_resource(pdev, IORESOURCE_MEM, i);
        if (res == NULL) {
            printk("not get resource\n");
            return -1;
        }
        ph_addr[i] = res->start;
    }
    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    pin = res->start;
    res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
    clock_offset = res->start;

    // 内存映射
    vi_ccgr = ioremap(ph_addr[0], 4);
    vi_mux_ctl = ioremap(ph_addr[1], 4);
    vi_pad_ctl = ioremap(ph_addr[2], 4);
    vi_gdir = ioremap(ph_addr[3], 4);
    vi_psr = ioremap(ph_addr[4], 4);
    
    // 完成设备注册的操作
    // register_chrdev() class_create()  device_create()
    major = register_chrdev(0, "my_button", &button_opr);

    button_class = class_create(THIS_MODULE, "button_class");
    err = PTR_ERR(button_class);
    if (IS_ERR(button_class)) {
        unregister_chrdev(major, "my_button");
        return -1;
    }

    device_create(button_class, NULL, MKDEV(major, 0), NULL, "my_button");

    printk("%s\n", __FUNCTION__);
    return 0;
}

static int button_remove(struct platform_device *pdev)
{
    printk("%s\n", __FUNCTION__);

    // 释放虚拟内存
    iounmap(vi_ccgr);
    iounmap(vi_mux_ctl);
    iounmap(vi_pad_ctl);
    iounmap(vi_gdir);
    iounmap(vi_psr);
    
    // 完成设备取消注册的操作
    device_destroy(button_class, MKDEV(major,0));

    class_destroy(button_class);

    unregister_chrdev(major, "my_button");

    printk("%s\n", __FUNCTION__);
    return 0;
}

struct platform_driver button_driver = {
    .probe = button_probe,
    .remove = button_remove,
    .driver = {
        .name = "my_button",
    },
};

// 入口函数
static int button_platform_driver_init(void)
{
    int ret = 0;
    printk("%s\n", __FUNCTION__);
    ret = platform_driver_register(&button_driver);  // 注册设备信息
    return ret;
}

// 出口函数
static void button_platform_driver_exit(void)
{
    printk("%s\n", __FUNCTION__);
    platform_driver_unregister(&button_driver);  // 注册设备信息
}

module_init(button_platform_driver_init);
module_exit(button_platform_driver_exit);
MODULE_LICENSE("GPL");

应用层测试程序

button_test.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main(int argc, char **argv)
{
    int fd;
    char status = 0;
    int ret = 0;
    int bnt = 0;
    
    if (argc !=2 ) {
        printf("Usage: %s <dev-path>\n", argv[0]);
        return -1;
    }
    fd = open(argv[1], O_RDWR);
    if (fd < 0) {
        perror("open error");
        return -1;
    }

    while(1) {
        ret = read(fd, &status, 1);
        if (ret < 0) {
            perror("read error");
            return -1;
        } else if (ret == 1 && status == 1) {
            printf("button %d\n", bnt++);
        }
    }

    return 0;
}

 

Makefile文件

Makefile

ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-   // 该参数与你的交叉编译工具有关
export  ARCH  CROSS_COMPILE

KERN_DIR = /home/hxd/workdir/ebf_linux_kernel_6ull_depth1/build_image/build   // 该目录与你的编译好的内核目录有关

all:
    make -C $(KERN_DIR) M=`pwd` modules 
    $(CROSS_COMPILE)gcc -o button_test button_test.c 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order
    rm -f button_test

obj-m    += button_device.o button_driver.o

编译运行

编译好后将得到的button_device.ko,button_driver.ko和button_test拷贝到开发板上

 

标签:__,button,driver,---,platform,static,device,include
来源: https://www.cnblogs.com/god-of-death/p/16656420.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有