led设备驱动

Led设备驱动基于字符设备框架,并且用到硬件知识比如EXYNOS中的控制led寄存器地址。还有几个重要函数比如ioremap、ioctl函数会在其他博客中贴出。这里直接贴出代码。

Led.c文件内容

/*6- 包含内核头文件*/

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/cdev.h>

#include <linux/device.h>

#include <asm/io.h>

 

/*7-根据芯片手册 确定物理地址*/

#define FS4412_GPX2CON  0x11000C40

#define FS4412_GPX2DAT   0x11000C44

 

void *gpx2con;

void *gpx2dat;

 

#define FS4412_GPX1CON  0x11000C20

#define FS4412_GPX1DAT   0x11000C24

 

void *gpx1con;

void *gpx1dat;

 

#define FS4412_GPF3CON  0x114001E0

#define FS4412_GPF3DAT   0x114001E4

 

void *gpf3con;

void *gpf3dat;

 

dev_t devno;

int major = 0;/*在/proc/devices查看系统中已经分配的设备号*/

int minor = 0;

 

/*8-内核中不能直接访问物理地址,需要先映射成虚拟地址*/

int fs4412_led_ioremap(void)

{

        gpx2con = ioremap(FS4412_GPX2CON, 4);

        gpx2dat = ioremap(FS4412_GPX2DAT, 4);

        gpx1con = ioremap(FS4412_GPX1CON, 4);

        gpx1dat = ioremap(FS4412_GPX1DAT, 4);

        gpf3con = ioremap(FS4412_GPF3CON, 4);

        gpf3dat = ioremap(FS4412_GPF3DAT, 4);

 

        return 0;

}

 

int fs4412_led_iounmap(void)

{

        iounmap(gpx2con);

        iounmap(gpx2dat);

        iounmap(gpx1con);

        iounmap(gpx1dat);

        iounmap(gpf3con);

        iounmap(gpf3dat);

 

        return 0;

}

 

/*9-初始化goio为输出模式*/

int fs4412_led_init(void)

{

       /*配置gpx2_7 bit28-31为输出模式*/

       writel((readl(gpx2con)& (~(0xf << 28))) | 0x1 << 28, gpx2con);

       /*配置gpx1_0 bit0-3为输出模式*/

       writel((readl(gpx1con)& (~(0xf << 0))) | 0x1 << 0, gpx1con);

       /*配置gpx3_4/5 bit16-23为输出模式*/

       writel((readl(gpf3con)& (~(0xff << 16))) | 0x11 << 16, gpf3con);

      

       return0;

}

 

int fs4412_led_on(int ledno)

{

       switch(ledno)

       {

              case1:

                     writel(readl(gpx2dat)|(0x1 << 7), gpx2dat);

                     break;

              case2:

                     writel(readl(gpx1dat)|(0x1 << 0), gpx1dat);

                     break;

              case3:

                     writel(readl(gpf3dat)|(0x1 << 4), gpf3dat);

                     break;

              case4:

                     writel(readl(gpf3dat)|(0x1 << 5), gpf3dat);

                     break;

       }

 

       return0;

}

 

int fs4412_led_off(int ledno)

{

       switch(ledno)

       {

              case1:

                     writel(readl(gpx2dat)& (~(0x1 << 7)), gpx2dat);

                     break;

              case2:

                     writel(readl(gpx1dat)& (~(0x1 << 0)), gpx1dat);

                     break;

              case3:

                     writel(readl(gpf3dat)& (~(0x1 << 4)), gpf3dat);

                     break;

              case4:

                     writel(readl(gpf3dat)& (~(0x1 << 5)), gpf3dat);

                     break;

       }

 

       return0;

}

 

int fs4412_led_open (struct inode *inode,struct file *file)

{

       printk("fs4412led open\n");

       fs4412_led_on(1);

       fs4412_led_on(2);

       fs4412_led_on(3);

       fs4412_led_on(4);

 

       return0;

}

int fs4412_led_close (struct inode *inode,struct file *file)

{

       printk("fs4412led close\n");

       fs4412_led_off(1);

       fs4412_led_off(2);

       fs4412_led_off(3);

       fs4412_led_off(4);

 

       return0;

}

 

 

#define LED_OFF 0

#define LED_ON 1

 

long fs4412_led_ioctl (struct file * file,unsigned int cmd, unsigned long ledno)

{

       printk("cmd= %d, ledno = %ld\n",cmd,ledno);

       switch(cmd)

       {

              caseLED_OFF:

                     fs4412_led_off(ledno);

                     break;

              caseLED_ON:

                     fs4412_led_on(ledno);

                     break;

              default:

                     break;           

                    

       }

 

       return0;

}

 

/*2-1 初始化驱动的操作函数接口*/

struct file_operations fops = {

       .open= fs4412_led_open,

       .release= fs4412_led_close,

       .unlocked_ioctl= fs4412_led_ioctl,

      

};/*赋值语句加;*/

 

struct class *pcls;

struct device *pledv;

 

static int __init led_module_init(void)

{

       printk("fs4412module init\n");

       /*2-字符设备框架初始化

              0自动分配设备号

       */

       major= register_chrdev(0, "fs4412-led", &fops);

       devno= MKDEV(major,minor);

       /*

              3-自动生成设备节点 /dev/auto-led 给应用程序访问硬件的节点

       */

       pcls= class_create(THIS_MODULE,"led-pcs");

       pledv= device_create(pcls, NULL, devno, NULL, "auto-led");

 

       fs4412_led_ioremap();

       fs4412_led_init();

      

       return0;

}

 

static void __exit led_module_exit(void)

{

       printk("fs4412led module exit\n");

       /*进行释放资源的操作*/

       unregister_chrdev(major,"fs4412-led");

 

       device_destroy(pcls,devno);

       class_destroy(pcls);

 

       fs4412_led_iounmap();

}

 

MODULE_LICENSE("GPL"); /*5-声明GPL,如果不加内核接口调用不了*/

module_init(led_module_init);/*1-模块入口函数,insmod led.ko会执行fs4412_led_init*/

module_exit(led_module_exit);/*4-模块出口函数 sudo rmmod led 会执行到 fs4412_led_exit*/

 

app.c文件内容

/*************************************************************************

 @Author: wanghao

 @Created Time : Tue 26 Jun 2018 06:26:39 PM PDT

 @File Name: test.c

 @Description:

 ************************************************************************/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

 

int main(int argc, const char *argv[])

{

       intfd = 0;

 

       printf("leddevice test!\n");

       fd= open("/dev/auto-led",O_RDWR);

       if(fd< 0)

       {

              perror("openfail!");

              returnfd;

       }

 

       sleep(1);

 

       close(fd);

       return0;

}

 

Makefile内容:

 

ifeq ($(KERNELRELEASE),)

#KDIR:= /lib/modules/$(shell uname-r)/build

KDIR:= /home/wanghao/linux-3.14-fs4412

 

all:

       make-C $(KDIR) M=$(shell pwd)

       arm-none-linux-gnueabi-gccapp.c -o app

       sudocp app /source/rootfs

       sudocp led.ko /source/rootfs

 

clean:

       rm*.o *.ko *.mod.c modules.order ledapp

else

obj-m:=led.o

endif

 

 

 

 

 

 

 

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值