led驱动

ubuntu10.04下led驱动的测试,虚拟机是vmware8.0.1,使用的是友善提供的Linux2.6.29.4内核

led_driver.c:

#include <linux/kernel.h> 

#include <linux/module.h> 

#include <linux/device.h>  

#include <linux/types.h> 

#include <linux/ioctl.h> 

#include <linux/errno.h> 

#include <linux/init.h>

#include <linux/cdev.h> 

#include <asm/uaccess.h> 

#include <linux/fs.h> 

#include <asm/io.h> 

#include <mach/regs-gpio.h> 

//***********************  定义设备结构体及相关宏  ********************** 

#define DEVICE_NAME   "led"       //定义设备名 

#define DEVICE_MAJOR    212       //手动定义 LED 设备的主设备号为 212 

static int led_major = DEVICE_MAJOR ;  

 

#define LED1  S3C2410_GPB5        //定义LED1 对应 S3C2410 的 GPB5 端口 ,这个地方要注意,mini2440使用的是GPB5端口

#define LED1_OUTP  S3C2410_GPB5_OUTP 

 

#define LED_ON    0      //给端口低电平(0)时,LED 亮 

#define LED_OFF   1    //给端口高电平(1)时,LED 灭 

 

//定义 LED 设备结构体 

struct s3c2410_led_dev 

struct cdev cdev;    //LED 设备对应一个字符设备结构体 

int status;          //LED 状态标识,0 代表灭,1 代表亮 

}; 

static struct s3c2410_led_dev dev; 

 

//*****************************  函数声明  ******************************** 

void s3c2410_led_InitIO(void);    //初始化 IO 端口的函数

//*****************************  函数定义  ******************************** 

void s3c2410_led_InitIO(void) 

int i; 

       //配置 LED 对应的端口为输出 

s3c2410_gpio_cfgpin(LED1, LED1_OUTP);  

       //配置 LED 初始为熄灭状态 

  s3c2410_gpio_setpin(LED1, LED_OFF);  

 

static int s3c2410_led_open(struct inode *inode,struct file *filp) 

{  

return 0; 

 

static int s3c2410_led_release(struct inode *inode,struct file *filp) 

return 0; 

 

//IO控制函数

static int s3c2410_led_ioctl(struct inode *inode,struct file *filp, unsigned int cmd,unsigned long arg) 

switch(cmd) { 

          case LED_ON: 

s3c2410_gpio_setpin(LED1, LED_ON); 

                dev.status = 1; 

break; 

               case LED_OFF: 

s3c2410_gpio_setpin(LED1, LED_OFF); 

dev.status = 0; 

break; 

           default: 

                return -EINVAL; 

return 0; 

}

 

//读LED

static ssize_t s3c2410_led_read(struct file *filp,char *buffer, size_t count,loff_t *ppos) 

put_user(dev.status,(int *)buffer);    //读取 LED 状态 

   return 1; 

 

//写LED

static ssize_t s3c2410_led_write(struct file *filp,char *buffer, size_t count,loff_t *ppos) 

get_user(dev.status,(int *)buffer); 

if(dev.status == 0) //灭 

     s3c2410_gpio_setpin(LED1, LED_OFF); 

else if(dev.status == 1)//亮 

     s3c2410_gpio_setpin(LED1, LED_ON); 

return 1; 

 

//设备文件操作结构

static struct file_operations s3c2410_led_fops = { 

       .owner    = THIS_MODULE, 

.open      = s3c2410_led_open, 

.release   = s3c2410_led_release, 

.ioctl       = s3c2410_led_ioctl,

.read       = s3c2410_led_read, 

.write     = s3c2410_led_write, 

}; 

 

//安装LED

static void led_setup_cdev(void) 

int err ,devno = MKDEV (led_major , 0);  

cdev_init(&dev.cdev,&s3c2410_led_fops); 

dev.cdev.owner = THIS_MODULE;    

dev.cdev.ops = &s3c2410_led_fops;    //建立设备文件操作与系统调用之间的连接 

err = cdev_add(&dev.cdev,devno,1);   //向系统添加该设备 

if(err) 

printk("Error %d adding LED %d",err); 

 

//LED初始化

static int s3c2410_led_init(void) 

int result; 

dev_t devno = MKDEV(led_major,0);//根据主设备号得到dev_t类型的设备号 devno 

if(led_major)     //如果手动分配了主设备号 

result = register_chrdev_region(devno,1,"DEVICE_NAME"); //向系统申请该设备号  

else 

{     //否则动态获取设备号 

result = alloc_chrdev_region(&devno ,0 ,1,"DEVICE_NAME"); 

led_major = MAJOR(devno); 

if(result < 0) 

return result; 

led_setup_cdev();         //  注册 LED 设备 

s3c2410_led_InitIO();  // 初始化 IO 端口 

// initialize the vals; 

dev.status = 0;      //LED 的初始状态是灭

printk(DEVICE_NAME " initialized\n"); 

return 0; 

 

//LED卸载

static void  s3c2410_led_exit(void) 

cdev_del(&dev.cdev);    //注销设备 

unregister_chrdev_region(MKDEV(led_major,0),1);   //释放设备号 

 

module_init(s3c2410_led_init); 

module_exit(s3c2410_led_exit); 

MODULE_LICENSE("GPL");   //设备许可 

 

Makefile:

KERNELDIR = /opt/mini2440/linux-2.6.29

PWD := $(shell pwd)

INSTALLDIR = $PWD

 

CROSS_COMPILE = /usr/local/arm/4.3.2/bin/arm-linux-

CC = $(CROSS_COMPILE)gcc

 

obj-m := led_driver.o

 

modules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

 

modules_install:

cp led_driver.ko $(INSTALLDIR)

 

clean:

rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

 

.PHONY:modules modules_install clean

 

led_test.c:

#include <stdio.h> 

#include <stdlib.h> 

#include <unistd.h> 

#include "sys/types.h" 

#include "sys/ioctl.h" 

#include "stdlib.h" 

#include "termios.h" 

#include "sys/stat.h" 

#include "fcntl.h" 

#include "sys/time.h" 

 

#define LED_ON  0 

#define LED_OFF 1

 

int main() 

int fd,i=0,j=0; 

int led_status = 0;    //初始状态为熄灭 

  fd = open("/dev/led", O_RDWR);   //打开设备 

   if (fd < 0) {    //如果打开设备失败,退出 

perror("open device led failed !"); 

  exit(1); 

printf("led test show. press ctrl+c to exit \n"); 

ioctl(fd,LED_OFF); 

       

while(1){//主循环 

read (fd,&led_status,1);    //读取 LED1 的当前状态到 led_status 

if(led_status ==0) //如果是灭的 

         ioctl(fd,LED_ON);    //点亮 

else if(led_status ==1) //如果是亮的 

         ioctl(fd,LED_OFF); //熄灭 

printf("led: on and off\n");  

for(i=0;i<300;i++)

         for(j=0;j<10000;j++); 

   close(fd);      //关闭设备 

   return 0; 

使用4.3.2版本的交叉编译器交叉编译,然后移植到板子上运行即可看到运行效果。
在移植Linux2.6.29内核时,注意不要将内核里drivers/char/下的mini2440_leds.c文件编译进内核,否则会与我们编译的led模块产生冲突
删除模块前需要存在一个目录,/lib/modules/2.6.29.4,根据自己需要修改,安装模块:insmod module.ko,卸载模块:rmmod module

你可能感兴趣的:(led驱动)