驱动开发之LED驱动(2)

2、在虚拟机的shell终端下,编写和编译驱动程序和测试程序,步骤如下图;

源码如下:

led.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<linux/device.h>
#include<linux/types.h>
#include<linux/ioctl.h>
#include<linux/cdev.h>
#include<linux/errno.h>

#include<asm/io.h>
#include<asm/hardware.h>
#include<asm/arch/regs-gpio.h>
#include<asm/arch-s3c2410/hardware.h>

#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)
#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)

#define GPFCON *(volatile unsigned int *)S3C2410_GPFCON
#define GPFDAT *(volatile unsigned int *)S3C2410_GPFDAT
#define GPFUP *(volatile unsigned int *)S3C2410_GPFUP

void delay_1(void)
{
 int i,j;
 for(i=0;i<1000;i++)
  for(j=0;j<10000;j++);
}

#define LED1_ON() (GPFDAT &=~0x8f)
#define LED2_ON() (GPFDAT &=~0x4f)
#define LED3_ON() (GPFDAT &=~0x2f)
#define LED4_ON() (GPFDAT &=~0x1f)
#define LED1_OFF() (GPFDAT |=0x80)
#define LED2_OFF() (GPFDAT |=0x40)
#define LED3_OFF() (GPFDAT |=0x20)
#define LED4_OFF() (GPFDAT |=0x10)

static int LedStatus;
void LedSet(int led)
{
 LedStatus = led;
 if(LedStatus&1)
  LED1_ON();
 else
  LED1_OFF();
 if(LedStatus&2)
  LED2_ON();
 else
  LED2_OFF();
 if(LedStatus&4)
  LED3_ON();
 else
  LED3_OFF();
 if(LedStatus&8)
  LED4_ON();
 else
  LED4_OFF();
}

void LedDisp(void)
{
 LedSet(0x08);
 delay_1();
 LedSet(0x04);
 delay_1();
 LedSet(0x02);
 delay_1();
 LedSet(0x01);
 delay_1();
 LedSet(0x02);
 delay_1();
 LedSet(0x04);
 delay_1();
 LedSet(0x08);
 delay_1();
}

#define DEVICE_NAME "led"
#define LED_MAJOR 220

static int led_open(struct inode *inode,struct file *file)
{
 GPFCON=0x5500;
 GPFUP=0xff;
 printk("LED Driver Open Called!\n");
 return 0;
}

static int led_release(struct inode *inode,struct file *file)
{
 printk("LED Driver Release Called\n");
 return 0;
}

static int led_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
 int err=0;
 if(cmd==1){
  while(arg--)
  {
   LedDisp();
   printk("....");
  }
  printk("\n");
  return 0;
 }
 return err;
}

static struct file_operations led_fops =
{
 .owner  = THIS_MODULE,
 .open    = led_open,
 .release = led_release,
 .ioctl  = led_ioctl,
};

static int __init led_init(void)
{
 int result=0;
 result=register_chrdev(LED_MAJOR,DEVICE_NAME,&led_fops);
 if(result < 0)
 {
  printk("failed to register!\n");
  return result;
 }
 printk("success to register\n");
 return 0;
}

static void __exit led_exit(void)
{
 printk("Led Driver Module Exit\n");
 unregister_chrdev(LED_MAJOR,DEVICE_NAME);
}

module_init(led_init);
module_exit(led_exit);

MODULE_AUTHOR("njust_sxy");
MODULE_DESCRIPTION("Led Driver");
MODULE_LICENSE("GPL");

Makefile

obj-m :=led.o
KDIR := /home/sxy/linux-2.6.8.1-zzm
PWD :=$(shell pwd)
CC=arm-linux-gcc
default:
 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
 rm -rf .*.cmd *.o *.mod.c *.ko</span>

test.c

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<linux/delay.h>
#include<sys/ioctl.h>

int main(int argc, char *argv[])
{
 int fd;
 int val=-1;
 fd=open("/dev/led",0);
 if(fd<0)
 {
  perror("can not open device");
  exit(1);
 }
 while(1){
  printf("please select number to run program\n");
  printf("1:led on \n2:quit ");
  scanf("%d",&val);
  if(val==1)
   ioctl(fd,1,10);
  else
   if(val==2){
    close(fd);
   }
  }
 return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/7add1726bcbb67f035b28abc591f6d6c.html