[国嵌攻略][117][LED驱动程序设计]

LED程序设计

1.编写内核模块

2.搭建字符驱动框架

3.实现设备方法

头文件

<linux/io.h>

writel()

1.编译/安装驱动

make

cp leddev.ko .../rootfs

insmod leddev.ko

2.创建设备文件

mknod /dev/myled0 c 253 0

3.编译/运行应用程序

arm-linux-gcc -static ledapp.c -o ledapp

cp ledapp .../rootfs

./ledadd 0

./ledadd 1

leddev.h

/********************************************************************
*设备命令
*********************************************************************/
#define LED_MAGIC 'L'               //LED幻数
#define LED_ON  _IO(LED_MAGIC, 0)   //LED打开
#define LED_OFF _IO(LED_MAGIC, 1)   //LED关闭

leddev.c

/********************************************************************
*头文件
*********************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "leddev.h"

/********************************************************************
*宏定义
*********************************************************************/
#define GPBCON 0x56000010   //控制寄存器物理地址
#define GPBDAT 0x56000014   //数据寄存器物理地址

/********************************************************************
*全局变量
*********************************************************************/
struct cdev chrdev;   //字符设备
dev_t devnum;         //主设备号

unsigned int *ledCon;   //控制寄存器指针
unsigned int *ledDat;   //数据寄存器指针

/********************************************************************
*设备方法
*********************************************************************/
//控制设备
long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    //处理命令
    switch(cmd){
        case LED_ON:    //打开LED
            writel(0x00000000, ledDat);   //GPBDAT[8:5]:0000
            break;
            
        case LED_OFF:   //关闭LED
            writel(0x000001E0, ledDat);   //GPBDAT[8:5]:1111
            break;
            
        default:
            return -EINVAL;
    }
    
    return 0;
}

//打开设备
int led_open(struct inode *node, struct file *filp){
    //配置LED引脚
    ledCon = ioremap(GPBCON, 4);   //虚拟地址转换
    writel(0x00015400, ledCon);    //GPBCON[17:10]:01010101
    
    //设置LED状态
    ledDat = ioremap(GPBDAT, 4);   //虚拟地址转换
    writel(0x00000140, ledDat);    //GPBDAT[8:5]:1010
    
    return 0;
}

//关闭设备
int led_close(struct inode *node, struct file *filp){
    return 0;
}

//设备方法
struct file_operations led_fops = {
    .unlocked_ioctl = led_ioctl,
    .open           = led_open,
    .release        = led_close
};

/********************************************************************
*模块安装
*********************************************************************/
//安装模块
static int led_init(){
    //注册设备标识
    cdev_init(&chrdev, &led_fops);
    
    //注册主设备号
    alloc_chrdev_region(&devnum, 0, 1, "myled");
    
    //添加设备标识
    cdev_add(&chrdev, devnum, 1);
    
    return 0;
}

//卸载模块
static void led_exit(){
    //注销设备标识
    cdev_del(&chrdev);
    
    //注销主设备号
    unregister_chrdev_region(devnum, 1);
}

/********************************************************************
*模块声明
*********************************************************************/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("D");
MODULE_DESCRIPTION("");
MODULE_VERSION("v1.0");

module_init(led_init);
module_exit(led_exit);

ledapp.c

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

int main(int argc, char **argv){
    //参数检测
    if(argc != 2){
        printf("Usage:
	%s <state>
", argv[0]);
        return -1;
    }
    
    //打开设备
    int fd;
    
    fd = open("/dev/myled0", O_RDWR);
    
    //控制设备
    int state;
    
    state = atoi(argv[1]);
    if(state){   //打开LED
        ioctl(fd, LED_ON);
    }else{       //关闭LED
        ioctl(fd, LED_OFF);
    }
    
    //关闭设备
    close(fd);
    
    return 0;
}
原文地址:https://www.cnblogs.com/d442130165/p/5251917.html