实验描述:Led每一秒跑马一次
注意事项:注意msleep()毫秒级的使用,视觉停留之清屏,主设备名冲突,软延时
内核版本:Linux 2.6.38
开发板: Mini 6410
驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
/*
Kernel Version: Linux 2.6.38
Arm Version: Mini 6410
*/
#define MyPrintk printk
static dev_t Leds_Major ;
static char * DEVICE_NAME = "MarqueeLeds";
static struct class *leds_class;
volatile unsigned long *gpkcon0 = NULL;
volatile unsigned long *gpkdat = NULL;
static int leds_init (struct inode *inode, struct file *file)
{
*gpkcon0 &= ~( (0xF<<4*4) | (0xF<<5*4) | (0xF<<6*4) | (0xF<<7*4));
*gpkcon0 |= ( (0x1<<4*4) |(0x1<<5*4) | (0x1<<6*4) | (0x1<<7*4));
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
MyPrintk ("Leds Open %lu\n",*gpkcon0);
MyPrintk ("Leds Open %lu\n",*gpkdat);
return 0;
}
static ssize_t leds_write (struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
{
int val;
unsigned long ret = copy_from_user(&val,buffer,count);
if (ret != 0){
MyPrintk ("value %lu\n", ret);
}
MyPrintk ("value %d\n", val);
unsigned int marqueevalue[4]= {
~ ((1<<4) | (0<<5) | (0<<6) | (0<<7)) ,
~ ((0<<4) | (1<<5) | (0<<6) | (0<<7)),
~ ((0<<4) | (0<<5) | (1<<6) | (0<<7)),
~ ((0<<4) | (0<<5) | (0<<6) | (1<<7))
};
MyPrintk ("value0 %u, %x\n", marqueevalue[0], marqueevalue[0]);
MyPrintk ("value0 %u, %x\n", marqueevalue[1], marqueevalue[1]);
MyPrintk ("value0 %u, %x\n", marqueevalue[2], marqueevalue[2]);
MyPrintk ("value0 %u, %x\n", marqueevalue[3], marqueevalue[3]);
msleep(1000);
if(val == 1){
int count=0;
while(val==1){
int temp = count % 4;
*gpkdat &= marqueevalue[temp];
msleep(1000);
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
count++;
if (count == 80){
break;
}
}
}else if(val == 0){
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
MyPrintk ("Leds all Off\n");
}
return 0;
}
static struct file_operations s3c64XX_leds_fops = {
.owner = THIS_MODULE,
.write = leds_write,
.open = leds_init,
};
static int myleds_init(void)
{
Leds_Major = register_chrdev(Leds_Major,DEVICE_NAME , &s3c64XX_leds_fops);
if(Leds_Major < 0){
MyPrintk (KERN_EMERG "Sorry, Can not register the leds device!\n");
}
MyPrintk (KERN_EMERG " Register the leds device\n");
leds_class = class_create(THIS_MODULE, "MarqueeLeds");
device_create(leds_class, NULL , MKDEV(Leds_Major, 0), NULL, "MarqueeLeds");
gpkcon0 = (volatile unsigned long *)ioremap(0x7F008800,16);
gpkdat = gpkcon0 + 2;
return 0;
}
static int myleds_exit(void)
{
unregister_chrdev(Leds_Major, DEVICE_NAME);
device_destroy(leds_class, MKDEV(Leds_Major, 0));
class_destroy(leds_class);
MyPrintk (KERN_EMERG "Marquee Leds Linux Byebye\n");
return 0;
}
module_init(myleds_init);
module_exit(myleds_exit);
MODULE_LICENSE("GPL");
#include<stdio.h>
#include<fcntl.h>
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/MarqueeLeds", O_RDWR);
if (fd < 0){
printf("Sorry, can't open!\n");
}
if (argc != 2){
printf("Marquee Usage :\n");
printf("%s <start |off>\n", argv[0]);
return 0;
}
if (strcmp(argv[1], "start") == 0){
val = 1;
}else{
val = 0;
}
write(fd, &val, 4);
return 0;
}