http://bbs.ednchina.com/BLOG_ARTICLE_297038.HTM
本实验的基于sep4020EVB 1.5开发板的一个小实验,实现流水灯的功能。
利用的端口是GPB0-GPB4 这5个端口
底层的驱动程序:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
//#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/hardware.h>
#define KEY_MAJOR 211
#define flowled_cmd0 1
unsigned int i="0";
unsigned int j="0";
struct flowled_dev
{
struct cdev cdev;
unsigned char value;
};
struct flowled_dev *flowleddev;
int sep4020_flowled_open(struct inode *inode, struct file *filp)
{
return 0;
}
int sep4020_flowled_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t sep4020_flowled_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
static ssize_t sep4020_flowled_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
int sep4020_flowled_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case flowled_cmd0:
{
for(i=0;i<5;i++)
{*(volatile unsigned long*)GPIO_PORTB_DATA_V=((*(volatile unsigned long*)GPIO_PORTB_DATA_V) & (0xffe0)) | i;
for(j=0;j<4000;j++);
}
break;
}
default:
return -ENOTTY;
}
return 0;
}
static const struct file_operations sep4020_flowled_fops =
{
.owner = THIS_MODULE,
.read = sep4020_flowled_read,
.write = sep4020_flowled_write,
.ioctl = sep4020_flowled_ioctl,
.open = sep4020_flowled_open,
.release = sep4020_flowled_release,
};
static void sep4020_flowled_setup(void)
{
*(volatile unsigned long*)GPIO_PORTB_SEL_V |= (0x001f); //作为通用用途
*(volatile unsigned long*)GPIO_PORTB_DIR_V &= (0xffe0);//输出
}
static int __init sep4020_flowled_init(void)
{
int err,result;
dev_t devno = MKDEV(KEY_MAJOR, 0);
if(KEY_MAJOR)
result = register_chrdev_region(devno, 1, "sep4020_flowled");
else
{
result = alloc_chrdev_region(&devno, 0, 1, "sep4020_flowled");
}
if(result < 0)
return result;
/*动态申请设备结构体的内存*/
flowleddev = kmalloc(sizeof(struct flowled_dev),GFP_KERNEL);
if (!flowleddev)
{
result = -ENOMEM;
goto fail_malloc;
}
memset(flowleddev,0,sizeof(struct flowled_dev));
/*注册中断函数*/
/*对键盘进行初始化*/
sep4020_flowled_setup();
cdev_init(&(flowleddev->cdev), &sep4020_flowled_fops);
flowleddev->cdev.owner = THIS_MODULE;
err = cdev_add(&flowleddev->cdev, devno, 1);
if(err)
printk("adding err\r\n");
return 0;
fail_malloc: unregister_chrdev_region(devno,1);
return result;
}
static void __exit sep4020_flowled_exit(void)
{
printk("sep4020_flowled_exit\n");
unregister_chrdev_region(KEY_MAJOR,1);
}
module_init(sep4020_flowled_init);
module_exit(sep4020_flowled_exit);
MODULE_AUTHOR("scx");
MODULE_LICENSE("GPL");
上层的应用程序如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DEVICE_NAME "/dev/sep4020_flowled"
#define flowled_cmd0 1
int main(void)
{
int fd;
printf("\n start sep4020_flowled test\n\n");
fd=open("/dev/sep4020_flowled",O_RDONLY);
printf("fd=%d\n",fd);
if(fd==-1)
{
printf("wrong\r\n");
exit(-1);
}
else
{
while(1)
{
ioctl(fd,flowled_cmd0);
}
}
close(fd);
printf("\n close sep4020_flowled test!!!\n\n");
return 0;
}