自学笔记 如何写一个完整的驱动程序

1、用户需求:需求写一个led的驱动,实现led2闪烁

2、驱动需求:设备led2 功能:亮 灭

3、寄存器操作:

1)原理图 :设备 → pin → 设备控制芯片

 驱动需求(led2 亮/灭) → 设备需求(gpx1_1 高低电平)

2)芯片手册:设备控制芯片 → 寄存器

人 → 二进制代码 → CPU芯片 → 设备控制芯片→ 寄存器 → 设备

4.编写代码

搭好框架

1)头文件

2)函数实现

{

        向上内核

        向下硬件

}

3)函数注册

4)信息描述

完整代码

//1.header
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>

#define LEN_ON _IOW('L',0,int)


#define GPX1CON 0x114000c0
#define GPX1DAT 0x114000c4


static  struct cdev mydev;
static int* gpx1con = NULL;
static int* gpx1dat = NULL;


int myopen(struct inode *pi, struct file *pf)
{
     printk("kernel open\n");
    return 0;
}

int myrelease(struct inode *pi, struct file *pf)
{
     printk("kernel release\n");
    return 0;
}

ssize_t mywrite (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{
    memcpy(kbuf,ubuf,len);
    return len;
}

ssize_t myread (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{
    memcpy(ubuf,kbuf,len);
    return len;
}

void addr_map(void)
{
    gpx1con = ioremap(GPX1CON,4);
    gpx1dat = ioremap(GPX1DAT,4);
}


//long (*unlocked_ioctl) (struct file *, unsigned int,unsigned long);
long myioctl (struct file *pf, unsigned int cmd,unsigned long arg)
{
    switch (cmd)
    {
    case LED_ON:
        led_on();
        break;
    case LED_OFF:
        led_off();
        break;  
    default:
        break;
    }
    return 0;
}

void dev_init()
{
    write1((read1(gpx1con)&~(0xf<<4))|(0x1<<4),gpx1con);
    write1(read1(gpx1dat)&~(0x1<<1),gpx1dat);
}

void led_on(void)
{
     write1(read1(gpx1dat)|(0x1<<1),gpx1dat);
}


void led_off(void)
{
     write1(read1(gpx1dat)&~(0x1<<1),gpx1dat);
}


static const struct file_operations myfops ={
    .open = myopen,
    .release = myrelease,
    .write = mywrite,
    .read = myread
    .unlocked_ioctl = myioctl;
};

//2.函数实现
static int myinit(void)
{
    //向上:和内核相关
    //1)reg
    ret = register_chrdev_region(no,count,name);
    //2)init
    cdev_init(&mydev,&myfops);
    //3)add
    ret = cdev_add(&mydev, no, count);

    //向下:和硬件相关
    //1)地址映射
    addr_map();
    //2)设备初始化
    dev_init();
    return 0;
}

static int myexit(void)
{
    //向上:和内核相关

    //1)del
    cdev_del(&mydev);
    //2)unreg
    unregister_chrdev_region(no,count);

    //向下:和硬件相关
    //1)取消映射
    addr_unmap();

    return;
    
}

//3、函数注册
module_init(myinit);
module_exit(myexit);


//4、信息描述
MODULE_LICENSE("GPL");

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值