栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux驱动编程【直接操作寄存器控制LED】

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux驱动编程【直接操作寄存器控制LED】

一、内存映射

        1、裸机LED灯实验就是操作6ULL的寄存器

        2、Linux驱动开发也可以操作寄存器。Linux下不能直接对寄存器的物理地址进行读写操作,比如寄存器A物理地址为0x01010101。裸机可以直接对0x01010101的物理地址进行操作,但是在Linux下不行。因为linux会使能MMU。

        在Linux里面操作的都是虚拟地址,所以需要先得到0x01010101这个物理地址所对应的虚拟地址

        MMU:       

         ①、完成虚拟内存到物理内存的映射

         ②、内存保护,设置存储器的访问权限

Ⅰ、ioremap函数

        用于获取指定物理地址空间对应的虚拟地址

        #define ioremap (cookie,size)

                cookie:物理地址的起始地址

                size :要转换的字节数量

        例如:0x01010101开始10个地址进行转换

                va = ioremap(0x01010101, 10)

Ⅱ、iounmap函数

        卸载驱动时,获取的虚拟地址进行释放

        #define iounmap (va)

二、LED灯字符设备驱动框架搭建
#include 
#include 
#include 
#include 
#include 
#include 

#define LED_MAJOR 200
#define LED_NAME "led"


#define CCM_CCGR1_BASE          (0x020C406C)
#define SW_MUX_GPIO1_IO03_BASE  (0x020E0068)
#define SW_PAD_GPIO1_IO03_BASE  (0x020E02F4)
#define GPIO1_GDIR_BASE         (0x0209C004)
#define GPIO1_DR_BASE           (0x0209C000)


static void __iomem *IMX6ULL_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_GDIR;
static void __iomem *GPIO1_DR;

#define LEDOFF  0
#define LEDON   1

void led_switch(u8 sta)
{
    u32 val = 0;
    if(sta == LEDOFF) {
        val = readl(GPIO1_DR);
        val |= (1 << 3); 
        writel(val, GPIO1_DR);
    } else if(sta == LEDON) {
        val = readl(GPIO1_DR);
        val &= ~(1 << 3); 
        writel(val, GPIO1_DR);
    }
}
static int led_open(struct inode *inode, struct file *filp)
{
    return 0;
}

static int led_release(struct inode *inode, struct file *filp)
{

    return 0;
}

static ssize_t led_write(struct file *filp, const char __user *buf,
                        size_t count, loff_t *ppos)
{
    int ret;
    unsigned char databuf[1];

    ret = copy_from_user(databuf, buf, count);
    if(ret < 0) {
        printk("kernel wirte failed");
        return -EFAULT;
    }

    
    led_switch(databuf[0]);

    return 0;
}


static const struct file_operations led_fops = {
    .owner  = THIS_MODULE,
    .write  = led_write,
    .open   = led_open,
    .release= led_release,
};

static int __init led_init(void)
{
    int ret = 0;
    int val = 0;
    
    IMX6ULL_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
    SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
    SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
    GPIO1_GDIR        = ioremap(GPIO1_GDIR_BASE, 4);
    GPIO1_DR          = ioremap(GPIO1_DR_BASE, 4);
    
    val = readl(IMX6ULL_CCM_CCGR1);
    val &= ~(3 << 26);
    val |= 3 << 26; 
    writel(val, IMX6ULL_CCM_CCGR1);

    writel(0x5, SW_MUX_GPIO1_IO03);
    writel(0x10B0, SW_PAD_GPIO1_IO03);
    
    val = readl(GPIO1_GDIR);
    val |= 1 << 3; 
    writel(val, GPIO1_GDIR);
    

    val = readl(GPIO1_DR);
    val &= ~(1 << 3); 
    writel(val, GPIO1_DR);

    
    ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
    if(ret < 0) {
        printk("register chrdev failedrn");
        return -EIO;
    }

    printk("len_init rn");
    return 0;
}

static void __exit led_exit(void)
{   
    
    int val = 0;
    val = readl(GPIO1_DR);
    val |= (1 << 3); 
    writel(val, GPIO1_DR);
    

    iounmap(IMX6ULL_CCM_CCGR1);
    iounmap(SW_MUX_GPIO1_IO03);
    iounmap(SW_PAD_GPIO1_IO03);
    iounmap(GPIO1_GDIR);
    iounmap(GPIO1_DR);

    unregister_chrdev(LED_MAJOR, LED_NAME);
    printk("led_exit rn");
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhang");



三、应用APP搭建
#include 
#include 
#include 
#include 
#include 
#include 


#define LEDOFF 0
#define LEDON  1
int main(int argc, char *argv[])
{
    int fd, ret;
    char *filename;
    filename = argv[1];
    unsigned char databuf[1];
    if(argc != 3) {
        printf("Error Usage!rn");
        return -1;
    }
    
    fd = open(filename, O_RDWR);
    if(fd < 0) {
        printf("open failedrn");
        return -1;
    }
    databuf[0] = atoi(argv[2]);
    ret = write(fd, databuf, sizeof(databuf));
    
    close(fd);
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/825588.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号