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

📄 uart.c

📁 Linux device driver sample code
💻 C
字号:
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <linux/interrupt.h>#include <linux/module.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/mach/irq.h>#include <asm-arm/io.h>#define AIC_BASE ((0xFFFFF000 - 0xFFF78000) + AT91_IO_VIRT_BASE)#define AIC_IRQ30_SMR (volatile unsigned int *) (AIC_BASE + 0x78)#define AIC_ICCR (volatile unsigned int *) (AIC_BASE + 0x128)int device_open(struct inode *inode, struct file *file);int device_release(struct inode *inode, struct file *file);ssize_t device_read(struct file *filep, char *buffer, size_t length, loff_t *offset);ssize_t device_write(struct file *filep, const char *buffer, size_t len, loff_t *offset);int flag = 0;volatile unsigned int *U0_BASE;void do_irq30_tasklet(unsigned long param){    printk(KERN_INFO "IRQ30 Tasklet \n");}void do_irq30_wq(void *data){    printk(KERN_INFO "workqueue scheduled\n");}DECLARE_WORK(wq, do_irq30_wq);DECLARE_WAIT_QUEUE_HEAD(waitq);int uartdata;irqreturn_t myIRQ(int irq, void *devid){    printk(KERN_INFO "IRQ test");	uartdata = *(U0_BASE + (0x18 >> 2));//  tasklet_schedule(&irq30_tasklet);    schedule_work(&wq);    *AIC_ICCR = (1 << 6);	flag = 1;	wake_up_interruptible(&waitq);	    return IRQ_HANDLED;}struct file_operations fops ={	.read = device_read,	.write = device_write,	.open = device_open,	.release = device_release};int major_no;char *msg_ptr;int init_module(void){	//Disable PIOA 	*((volatile unsigned int *) (0x87800 + AT91_IO_VIRT_BASE+ 0x04)) = 0x30;	//Enable Peripheral A registers, i.e U0TX and U0RX	*((volatile unsigned int *) (0x87800 + AT91_IO_VIRT_BASE+ 0x70)) = 0x30;	//Enable Peripheral clock for USART0 	*((volatile unsigned int *) (0x87C00 + AT91_IO_VIRT_BASE+ 0x10)) = *(((volatile unsigned int *) (0x87C00 + AT91_IO_VIRT_BASE + 0x10))) | 0x40;	//Turn ON the LED to test if we reached here	*((volatile unsigned int *) (0x87400 + AT91_IO_VIRT_BASE+ 0x30)) = 0xFC0;	//Remap the USART0 base address to IOREMAP page	U0_BASE = ioremap((0xFFF78000 + 0x38000), 1000);	*((U0_BASE + (0x00 >> 2))) = 0x10C;//Write CR for resetting TX, RX & STATUS	*((U0_BASE + (0x04 >> 2))) = 0x8C0;//Write MR for the UART mode	*((U0_BASE + (0x20 >> 2))) = 54; //Write BRGR for baud rate configuration	*((U0_BASE + (0x00 >> 2))) = 0x50;//Write CR to enable TX and RX	printk(KERN_INFO "U0_FIDI = 0x%x \n", *(U0_BASE + (0x40 >> 2)));	printk(KERN_INFO "U0_BRGR = 0x%x \n", *(U0_BASE + (0x20 >> 2)));	printk(KERN_INFO "hello \n");	if((major_no = register_chrdev(0, "Oasis", &fops)) < 0)	{		printk(KERN_INFO "Error \n");	}	*((U0_BASE + (0x08 >> 2))) = 0x01;//Enable RX interrupt	request_irq(6, myIRQ, 0, "MYIRQ", 0);	return 0;}void cleanup_module(void){	int ret;	printk(KERN_INFO "bye \n");	*((volatile unsigned int *) (0x87400 + AT91_IO_VIRT_BASE+ 0x34)) = 0xFC0;	if((ret = unregister_chrdev(major_no, "Oasis")) < 0)	{		printk(KERN_INFO "Error\n");	}	*((U0_BASE + (0x0C >> 2))) = 0x01;//Disable RX interrupt	free_irq(6, 0);}int device_open(struct inode *inode, struct file *file){	printk(KERN_INFO "Open called\n");	return 0;}int device_release(struct inode *inode, struct file *file){	printk(KERN_INFO "Close called\n");	return 0;}ssize_t device_read(struct file *filep, char *buffer, size_t length, loff_t *offset){	int count = 0;	printk(KERN_INFO "process going to sleep... \n");	wait_event_interruptible(waitq, flag != 0);	flag = 0;		printk(KERN_INFO "process out of sleep... \n");	printk(KERN_INFO "%c", uartdata);	buffer[0] = uartdata;	return length;}ssize_t device_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){	int err = 0;	*((U0_BASE + (0x1C >> 2))) = buffer[0];	printk(KERN_INFO "write called\n");	if((msg_ptr = (char *) kmalloc((len+1), GFP_KERNEL)) == NULL)	{		printk(KERN_INFO "kmalloc problem \n");		return -1;	}	err = access_ok(VERIFY_WRITE, buffer, len);		if(err)	{#if 0		if(__copy_from_user(msg_ptr, buffer, len) > 0)		{			printk(KERN_INFO "fail\n");		}		else		{			printk(KERN_INFO "success %s\n", msg_ptr);		}#else		memcpy(msg_ptr, buffer, (len));		msg_ptr[len] = 0;		printk(KERN_INFO "user ptr %s\n", msg_ptr);#endif	}	else	{		printk(KERN_INFO "user space pointer not good \n");		kfree(msg_ptr);		return -1;	}	printk(KERN_INFO "write done\n");	kfree(msg_ptr);	return len;}

⌨️ 快捷键说明

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