[国嵌攻略][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:\n\t%s <state>\n", 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;
}
复制代码

 

posted @   盛夏夜  阅读(352)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示