六、imx6ull驱动实现

一、硬件原理图阅读

二、GPIO相关寄存器介绍

1.管脚功能模式

2.管脚输入输出

3.管脚高低电平

三、寄存器操作

1.物理地址映射成虚拟地址

void __iomem *ioremap(phys_addr_t addr, size_t size);

参数:

@addr 物理地址

@size 物理地址大小

返回值:

成功返回虚拟地址,失败返回NULL

2.寄存器读写函数

#include <linux/io.h>

unsigned int readl (volatile void __iomem *addr ) //读4字节

void writel (unsigned int data,volatile void __iomem *addr) //写4字节

四、驱动源码

cpp 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/io.h>
//LED 灯的寄存器设置
#define LED_MUXIO_REGPHY_ADDR 0x20E00B0
#define LED_MUXIO_REG_SIZE           0x4
#define LED_GPIO_BASE_ADDR          0x209C000
#define LED_GPIO_ADDR_SIZE            0x8
#define GPIO_DATREG_OFFSET           0x0
#define GPIO_DIRREG_OFFSET            0x4

#define LED_DEVICE_MAJOR 240
#define LED_DEVICE_MINOR 0

#define LED_DEVICE_ON _IO('L',0x01)
#define LED_DEVICE_OFF _IO('L',0x02)

MODULE_LICENSE("GPL v2");

struct led_device
{
    dev_t devid;
    void *gpio_muxio_reg;
    void *gpio_con_reg;
    struct device *dev;
    struct class *class;
    struct cdev led_cdev;
};
struct led_device *pled;

void led_init(void)
{
    int regval = readl(pled->gpio_muxio_reg);
    regval &= ~(0xf << 0);
    regval |= (0x5 << 0);
    writel(regval,pled->gpio_muxio_reg  );

    regval = readl(pled->gpio_con_reg + GPIO_DIRREG_OFFSET);
    regval |= (1 << 27);//第27位设1
    writel(regval,pled->gpio_con_reg + GPIO_DIRREG_OFFSET);
    return;
}

void led_on(void)
{
     int regval = readl(pled->gpio_con_reg + GPIO_DATREG_OFFSET);
     regval |= (1 << 27);
     writel(regval,pled->gpio_con_reg + GPIO_DATREG_OFFSET);
     return;
}

void led_off(void)
{
     int regval = readl(pled->gpio_con_reg + GPIO_DATREG_OFFSET);
     regval &=  ~(1 << 27);
     writel(regval,pled->gpio_con_reg + GPIO_DATREG_OFFSET);
    return;
}

static int led_device_open(struct inode *inode,struct file *file)
{
    printk("led device open\n");
    pled->gpio_muxio_reg = ioremap(LED_MUXIO_REGPHY_ADDR,LED_MUXIO_REG_SIZE);
    if(!pled->gpio_muxio_reg)
    {
        printk("Fail to ioremap LED_MUXIO_REGPHY_ADDR\n");
        return -ENOMEM;
    }
    pled->gpio_con_reg = ioremap(LED_GPIO_BASE_ADDR,LED_GPIO_ADDR_SIZE);
    if(!pled->gpio_con_reg)
    {
        printk("Fail to ioremap LED_GPIO_BASE_ADDR\n");
        return -ENOMEM;
    }
    led_init();
    return 0;
}
static int led_device_release(struct inode *inode,struct file *file)
{
printk("led device release\n");
led_off();
    iounmap(pled->gpio_muxio_reg);
    iounmap(pled->gpio_con_reg);
    return 0;
}

static long led_device_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
    switch (cmd)
    {
    case LED_DEVICE_ON:
        printk("led device on\n");
        led_on();
        break;
    case LED_DEVICE_OFF:
        printk("led device off\n");
        led_off();
        break;
    }
    return 0;
}

struct file_operations led_device_ops = {
    .owner = THIS_MODULE,
    .open = led_device_open,
    .release = led_device_release,
    .unlocked_ioctl = led_device_ioctl,
};

static int __init  led_driver_init(void)
{
    int err;
    
    pled = kmalloc(sizeof(*pled),GFP_KERNEL);
    if(pled == NULL)
    {
        printk("Fail to kmalloc\n");
        err = -ENOMEM;
        goto err_kmalloc;
    }
    //pled->led_cdev.ops = &led_device_ops;
    cdev_init(&pled->led_cdev,&led_device_ops);
#if 0
    pled->devid = MKDEV(LED_DEVICE_MAJOR,LED_DEVICE_MINOR);
    err = register_chrdev_region(pled->devid,1,"led-device");
    if(err)
    {
        printk("Fail to register_chrdev_region\n");
        kfree(pled);
    }
#endif
    err = alloc_chrdev_region(&pled->devid,0,1,"led-device");
    if(err)
    {
        printk("Fail to alloc_chrdev_region\n");
        goto err_alloc_chrdev_region;
      
    }
    printk("led device MAJOR:%d MINOR:%d\n",MAJOR(pled->devid),MINOR(pled->devid));

    err = cdev_add(&pled->led_cdev,pled->devid,1);
    if(err)
    {
        printk("Fail to cdev_add\n");
        goto err_cdev_add;
        
    }

    pled->class = class_create(THIS_MODULE,"imx6ull-leds");
    if (IS_ERR(pled->class))
    {
        err = PTR_ERR(pled->class);
        printk("Fail to class_create\n");
        goto err_class_create;
        
    }
    //
    pled->dev = device_create(pled->class,NULL,pled->devid,NULL,"led-device");
    if(IS_ERR(pled->dev))
    {
        printk("Fail to device_create\n");
        err = PTR_ERR(pled->dev);
        goto err_device_create;
        
    }
    
    return 0;
err_device_create:
    class_destroy(pled->class);
err_class_create:
    cdev_del(&pled->led_cdev);
err_cdev_add:
    unregister_chrdev_region(pled->devid,1);
err_alloc_chrdev_region:
    kfree(pled);
err_kmalloc:
    return err;
}

static void __exit  led_driver_exit(void)
{
    device_destroy(pled->class,pled->devid);
    class_destroy(pled->class);
    cdev_del(&pled->led_cdev);
    unregister_chrdev_region(pled->devid,1);
    kfree(pled);
    
}
module_init(led_driver_init);
module_exit(led_driver_exit);

五、应用程序源码

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define LED_DEVICE_ON _IO('L',0x01)
#define LED_DEVICE_OFF _IO('L',0x02)
int main(int argc,const char *argv[])
{
    int ret;
    int fd;
    fd = open("/dev/led-device",O_RDWR);
    if(fd < 0)
    {
        perror("Fail to open");
        return -1;
    }
    printf("open /dev/led-device success,fd:%d\n",fd);
    while (1)
    {
        ret = ioctl(fd,LED_DEVICE_ON);
        if(ret < 0)
        {
            perror("Fail to ioctl LED_DEVICE_ON\n");
            return -1;
        }
        sleep(1);
        ret = ioctl(fd,LED_DEVICE_OFF);
        if(ret < 0)
        {
            perror("Fail to ioctl LED_DEVICE_OFF\n");
            return -1;
        }
        sleep(1);
    }
    

    close(fd);
    return 0;
}
相关推荐
_F_y1 小时前
Linux中项目自动化构建工具-make/Makefile
linux
chao1031 小时前
ubuntu下业务运行环境搭建
linux·运维·ubuntu
weixin_46681 小时前
Docker Dockerfile文件
linux·运维·服务器
white-persist1 小时前
【攻防世界】reverse | Mysterious 详细题解 WP
c语言·开发语言·网络·汇编·c++·python·安全
赖small强1 小时前
【Linux C/C++ 开发】 GCC 编译过程深度解析指南
linux·c语言·c++·预处理·链接·编译·编译过程
做人不要太理性1 小时前
【Linux系统】ext2文件系统
大数据·linux·操作系统·文件系统
保持低旋律节奏1 小时前
linux——软件包、yum 安装和卸载
linux·运维·服务器
莫道桑榆晚丶1 小时前
Linux系统编程--------MP3项目实战
linux·学习
小oo呆2 小时前
【学习心得】Python好库推荐——pipx
linux·开发语言·python