📄 uart.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 + -