⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switch.c

📁 读取frv实验系统上的按键值 并以此来控制frv实验板上的led 基于嵌入式linux
💻 C
字号:
/* FJ:SupportForTARBO-20020617-V01L01 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/irq.h>
#include <asm/frvirq.h>
#include <asm/uaccess.h>
#include <asm/smplock.h>

#include "switch.h"

int __init fpga_sw_init(void);
static void fpga_sw_inthdr(int irq, void *dev_id, struct pt_regs *regs);
static int fpga_sw_open(struct inode *inode, struct file *file);
static int fpga_sw_release(struct inode *inode, struct file *file);
static int fpga_sw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static void fpga_sw_task(unsigned long data);

static inline u16 read_tarboio_register(volatile unsigned short *x);
static inline void write_tarboio_register(volatile unsigned short *x, unsigned short v);


DECLARE_TASKLET(fpga_sw_tasklet, fpga_sw_task, 0);
DECLARE_WAIT_QUEUE_HEAD(wake_fpga_sw_que);

static spinlock_t fr400_sw_lock = SPIN_LOCK_UNLOCKED;
static	volatile unsigned short fpga_sw_buff;

static	struct	file_operations fpga_sw_fops = {
	ioctl:		fpga_sw_ioctl,	// ioctl entry
	open:		fpga_sw_open,	// open entry
	release:	fpga_sw_release,// release entry
};

/*
 * FPGA SW driver user interface
 */
/* Open a FPGA SW device. */
static int fpga_sw_open(struct inode *inode, struct file *file)
{
	return 0;
}


/* Last close of a FPGA SW for Linux device */
static int fpga_sw_release(struct inode *inode, struct file *file)
{
	return 0;
}


static int fpga_sw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int data;
	unsigned long flags;
	unsigned short irq;

	switch (cmd) { /* If SW flag is ON, read sw register and return */
	case FPGA_PUSW_READ :
		data = SW_PUSW_READ();
		if (data) {
			/* push SW is ON */
			*(int *)arg = data;
			return 0;
		}
		irq = FPGA_PUSW_IRQ;
		break;
	case FPGA_RSW8_READ :
		data = SW_RSW8_READ();
		if (data) {
			/* Rocker SW8 is ON */
			*(int *)arg = data;
			return 0;
		}
		irq = FPGA_RSW8_IRQ;
		break;
	case FPGA_RSW9_READ :
		data = SW_RSW9_READ();
		if (data) {
			/* Rocker SW9 is ON */
			*(int *)arg = data;
			return 0;
		}
		irq = FPGA_RSW9_IRQ;
		break;
	case FPGA_SW_READ :
		data = SW_READ();
		if (data) {
			/* SW is ON */
			*(int *)arg = data;
			return 0;
		}
		irq = FPGA_SW_IRQ;
		break;
	default :
		printk("FPGA SW: invalid command.\n");
		return -EINVAL;
	}

	/*
	 * SW is OFF
	 */
	/* Enable SW interrupt */
	spin_lock_irqsave(&fr400_sw_lock, flags);
	{
		fpga_sw_buff = 0xFFFF;
		enable_irq(FRV_K_IRQ_SW2_6);
		enable_irq(FRV_K_IRQ_SW9);
		enable_irq(FRV_K_IRQ_SW8);
	}
	spin_unlock_irqrestore(&fr400_sw_lock, flags);

	/* Wait SW interrupt */
	current->state = TASK_INTERRUPTIBLE;
	schedule_timeout(5);

	/* Disable SW interrupt */
	spin_lock_irqsave(&fr400_sw_lock, flags);
	{
		data = fpga_sw_buff;
	}
	spin_unlock_irqrestore(&mbfr400_sw_lock, flags);

	if (data == 0xFFFF) {
		disable_irq(FRV_K_IRQ_SW2_6);
		disable_irq(FRV_K_IRQ_SW9);
		disable_irq(FRV_K_IRQ_SW8);
		*(int *)arg = data;
	} 
	else if (cmd == FPGA_PUSW_READ)
		*(int *)arg = ((data>>10) & 0x001F);
	else if (cmd == FPGA_RSW8_READ)
		*(int *)arg = ((data>> 5) & 0x001F);
	else if (cmd == FPGA_RSW9_READ)
		*(int *)arg = ((data    ) & 0x001F);
	else if (cmd == FPGA_SW_READ)
		*(int *)arg = ((data    ) & 0x7FFF);

	return 0;
}


/*
 * FPGA SW driver initilaize routie
 */

int __init fpga_sw_init(void)
{
	unsigned long flags;

	printk(KERN_INFO "PDK 2.0 FPGA SW interface: v1.00\n");
	if(devfs_register_chrdev(FPGA_SW_MAJOR,"fpga_sw", &fpga_sw_fops)) {
		printk("PDK 2.0 FPGA SW interface: unable to get major %d\n", FPGA_SW_MAJOR);
		return -EIO;
	}

	spin_lock_irqsave(&fr400_sw_lock, flags);
	request_irq(FRV_K_IRQ_SW2_6, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw2_6", NULL);
	request_irq(FRV_K_IRQ_SW9, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw9", NULL);
	request_irq(FRV_K_IRQ_SW8, fpga_sw_inthdr, SA_INTERRUPT, "fr400_sw8", NULL);
	disable_irq(FRV_K_IRQ_SW2_6);
	disable_irq(FRV_K_IRQ_SW9);
	disable_irq(FRV_K_IRQ_SW8);
	spin_unlock_irqrestore(&fr400_sw_lock, flags);
	return 0;
}

/*
 * FPGA SW driver interrupt handler
 */
static void fpga_sw_inthdr(int irq, void *dev_id, struct pt_regs *regs)
{
	disable_irq(FRV_K_IRQ_SW2_6);
	disable_irq(FRV_K_IRQ_SW9);
	disable_irq(FRV_K_IRQ_SW8);

	tasklet_schedule(&fpga_sw_tasklet);

	return;
}

/*
 * FPGA SW driver task
 */
static void fpga_sw_task(unsigned long data)
{
	unsigned long flags, i;

	spin_lock_irqsave(&fr400_sw_lock, flags);
	{
		for(i=0;i<1000;i++){
			fpga_sw_buff = SW_READ();
			if(fpga_sw_buff!=0x7FFF) break;
		}
	}
	spin_unlock_irqrestore(&mbfr400_sw_lock, flags);

	return;
}

static inline u16 read_tarboio_register(volatile unsigned short *x)
{
	unsigned short v;
	v = *((volatile unsigned short *)(x));
	__asm__ __volatile__("membar");
	return v;
}

static inline void write_tarboio_register(volatile unsigned short *x, unsigned short v)
{
	*((volatile unsigned short *)(x)) = (v);
	__asm__ __volatile__("membar");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -