📄 xup_spartan3e_led.c
字号:
#include <linux/module.h>
#include <asm/io.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <asm/semaphore.h>//struct semaphore
#include <linux/timer.h>//timer_list
//#include <linux/wait.h>//wait_event_interruptible_timeout
//#include <linux/sched.h>//schedule_timeout
#define XUP_SPARTAN3E_LED_MAJOR 222#define XUP_SPARTAN3E_PLAY_MAJOR 223
#define DATA_REG_ADDR 0x40000000
#define DIRC_REG_ADDR 0x40000004
#define OutMem(OutAddr, Value) (*(volatile u32 *)((OutAddr)) = (Value))
#define InMem(InputAddr) (*(volatile u32 *)(InputAddr))
#define DELAY (HZ>>3)#define INITIAL_COUNT 40
#define XUP_SPARTAN3E_LED_IOC_MAGIC 'x'
#define XUP_SPARTAN3E_LED_MAX_NUM 4
#define XUP_SPARTAN3E_LED_SET_DIR _IOWR(XUP_SPARTAN3E_LED_IOC_MAGIC, 0, u32) //ioctl
#define XUP_SPARTAN3E_LED_SET_REV _IOWR(XUP_SPARTAN3E_LED_IOC_MAGIC, 1, u32) //ioctl
static int initial_count;
static unsigned char led_state;
static struct semaphore sem; /* mutual exclusion semaphore */
static struct timer_list refresh_timer;
static void refresh(unsigned long ptr)
{ if (refresh_timer.data == 1)
{
if (initial_count < INITIAL_COUNT) { if (led_state|0x0)
led_state <<= 1;
else
led_state = 1; initial_count = initial_count + 1; } else if (initial_count < INITIAL_COUNT*2 && initial_count >= INITIAL_COUNT) { if (led_state != 0x01)
led_state >>= 1;
else
led_state = 0x80; initial_count = initial_count + 1; } else { if (led_state == 0x0)
led_state = 0xff;
else if (led_state == 0xff)
led_state = 0x0; else led_state=0x0; } OutMem(DATA_REG_ADDR, led_state);
refresh_timer.expires = jiffies + DELAY;
add_timer(&refresh_timer);
} else if (refresh_timer.data == 2) { OutMem(DATA_REG_ADDR, led_state);
refresh_timer.expires = jiffies + DELAY>>2;
add_timer(&refresh_timer); } else {}
}static int xled_open(struct inode * inode, struct file * file)
{
MOD_INC_USE_COUNT;
//printk("XUP_SPARTAN3E_LED open: Usage = %d\n", MOD_IN_USE);
return 0;
}
static int xled_release(struct inode * inode, struct file * file)
{
MOD_DEC_USE_COUNT;
//printk("XUP_SPARTAN3E_LED release: Usage = %d\n", MOD_IN_USE);
return 0;
}
static ssize_t xled_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
down(&sem);
//led_state = inb(INPORT);
//OutMem(DIRC_REG_ADDR, 0xFFFFFFFF);//set direction
//barrier();
//led_state = InMem(DATA_REG_ADDR);
//printk("data = %x hex\n", led_state); // for debugging only
if(copy_to_user( buffer, &led_state, 1))
{
printk("Read Data to user error\n");
up(&sem);
return -EFAULT;
}
up(&sem);
return 1;
}
static ssize_t xled_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{ down(&sem); refresh_timer.data = 0;
if (copy_from_user(&led_state, __user (u8 *)buf, 1))
//int ret = get_user(led_state,buf);
//if (ret != 0)
{
printk("Write Data from user error\n");
up(&sem);
return -EFAULT;
}
printk("Write Data from user %x\n", led_state); up(&sem);
//outb(data, OUTPORT); if (led_state == 0xAA) { refresh_timer.data = 1; refresh(0); } else
{ refresh_timer.data = 2; refresh(0); }
return 1;
}
static int xled_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if (MINOR(inode->i_rdev) >= XUP_SPARTAN3E_LED_MAX_NUM)
return -ENODEV;
if (_IOC_TYPE(cmd) != XUP_SPARTAN3E_LED_IOC_MAGIC)
return -ENOTTY;
switch (cmd)
{
case XUP_SPARTAN3E_LED_SET_DIR:
OutMem(DIRC_REG_ADDR, arg);
printk("Set XUP_SPARTAN3E_LED direct %ld\n", arg);
break;
case XUP_SPARTAN3E_LED_SET_REV:
;
break;
default:
return -ENOTTY;
}
return 0;
}static ssize_t play_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
down(&sem);
//led_state = inb(INPORT);
//OutMem(DIRC_REG_ADDR, 0xFFFFFFFF);//set direction
//barrier();
//led_state = InMem(DATA_REG_ADDR);
//printk("data = %x hex\n", led_state); // for debugging only
if(copy_to_user( buffer, &led_state, 1))
{
printk("Read Data to user error\n");
up(&sem);
return -EFAULT;
}
up(&sem);
return 1;
}
static ssize_t play_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
down(&sem);
refresh_timer.data = 0; if (copy_from_user(&led_state, __user (u8 *)buf, 1))
//int ret = get_user(led_state,buf);
//if (ret != 0) //if (copy_from_user(&led_state, __user (u8 *)buf, count))
{
printk("Write Data from user error\n");
up(&sem);
return -EFAULT;
}
printk("Write Data from user %x\n", led_state);
//outb(data, OUTPORT);
OutMem(DATA_REG_ADDR, led_state); up(&sem);
return 1;
}
struct file_operations play_fops = {
owner: THIS_MODULE,
open: xled_open,
release: xled_release,
read: play_read,
write: play_write,
ioctl: xled_ioctl,
};struct file_operations xled_fops = {
owner: THIS_MODULE,
open: xled_open,
release: xled_release,
read: xled_read,
write: xled_write,
ioctl: xled_ioctl,
};
int __init xled_init (void)
{
if (register_chrdev(XUP_SPARTAN3E_LED_MAJOR,"XUP_SPARTAN3E_LED",&xled_fops))
{
printk("XUP_SPARTAN3E_LED: Failed to get major %d\n", XUP_SPARTAN3E_LED_MAJOR);
return -EIO;
}
if (register_chrdev(XUP_SPARTAN3E_PLAY_MAJOR,"XUP_SPARTAN3E_PLAY",&play_fops))
{
printk("XUP_SPARTAN3E_PLAY: Failed to get major %d\n", XUP_SPARTAN3E_PLAY_MAJOR);
return -EIO;
} initial_count = 0;
init_MUTEX(&sem);
init_timer(&refresh_timer);
refresh_timer.function = refresh;
refresh_timer.data = 1;
refresh_timer.expires = jiffies + DELAY;
add_timer(&refresh_timer);
printk("Registered device XUP_SPARTAN3E_LED: major %d\n",XUP_SPARTAN3E_LED_MAJOR); printk("Registered device XUP_SPARTAN3E_PLAY: major %d\n",XUP_SPARTAN3E_PLAY_MAJOR);
return 0;
}
static void __exit xled_cleanup (void)
{
printk("Freed resources: MOD_IN_USE = %d\n", MOD_IN_USE);
unregister_chrdev(XUP_SPARTAN3E_LED_MAJOR,"XUP_SPARTAN3E_LED"); unregister_chrdev(XUP_SPARTAN3E_PLAY_MAJOR,"XUP_SPARTAN3E_PLAY");
del_timer(&refresh_timer);
printk("Unregistered device XUP_SPARTAN3E_LED: major %d\n",XUP_SPARTAN3E_LED_MAJOR); printk("Unregistered device XUP_SPARTAN3E_PLAY: major %d\n",XUP_SPARTAN3E_PLAY_MAJOR);
}
module_init(xled_init);
module_exit(xled_cleanup);
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -