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;
}