📄 mcpcan.c
字号:
}
/* * Atomicly increment an index into shortp_in_buffer */static inline void incr_buffer_pointer(volatile unsigned long*index, int delta, int i){ unsigned long newvalue = *index + delta; barrier (); /* Don't optimize these two together */ *index = (newvalue >= (Device[i]->RecvBuf + BUF_SIZE)) ? Device[i]->RecvBuf : newvalue;}static void mcpcan0_handler(int irq, void *dev_id, struct pt_regs *regs){ struct MCP_device *dev = dev_id; struct mcpcan_data datagram; int written; char regvalue, regvalue2; //struct mcpcan_data *datagramptr; printk("\rextern irq 5 handled\n"); regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTE)), ARG_UNUSED, ARG_UNUSED ); printk("CANINTE = 0x%02x\n",regvalue); regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED ); printk("CANINTF = 0x%02x\n",regvalue); if(regvalue & 0x01){ datagram.BufNo = RXBUF0; MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data ); printk("RXBUF0\n"); //printk("datagram.BufNo = %d\n",datagram.BufNo); //printk("datagram.IdType = %d\n",datagram.IdType); //printk("datagram.id = %d\n",datagram.id); //printk("datagram.DataLen = %d\n",datagram.DataLen); //printk("datagram.data = %s\n",datagram.data); /* Write a 16 byte record. Assume BUF_SIZE is a multiple of 16 */ memcpy((void *)dev->RecvHead, &datagram, sizeof(struct mcpcan_data)); //datagramptr = (struct mcpcan_data *)dev->RecvHead; //printk("RecvHead->BufNo = %d\n",datagramptr->BufNo); //printk("RecvHead->IdType = %d\n",datagramptr->IdType); //printk("RecvHead->id = %d\n",datagramptr->id); //printk("RecvHead->DataLen = %d\n",datagramptr->DataLen); //printk("RecvHead->data = %s\n",datagramptr->data); incr_buffer_pointer(&(dev->RecvHead), sizeof(struct mcpcan_data), dev->MinorNum); wake_up_interruptible(&(dev->inq)); /* awake any reading process */ CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x01, 0x00 ); //in fact already clear interrupt bit in RX } if(regvalue & 0x02){ datagram.BufNo = RXBUF1; //this function should be rewritten to receive datagram from RXB1?????????????????? MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data ); printk("RXBUF1\n"); /* Write a 16 byte record. Assume BUF_SIZE is a multiple of 16 */ memcpy((void *)dev->RecvHead, &datagram, sizeof(struct mcpcan_data)); incr_buffer_pointer(&(dev->RecvHead), sizeof(struct mcpcan_data), dev->MinorNum); wake_up_interruptible(&dev->inq); /* awake any reading process */ CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x02, 0x00 ); //in fact already clear interrupt bit in RX } if(regvalue & 0xe0){ printk("CAN error with CANINTF = 0x%02x.\n", regvalue); if(regvalue & 0x80)printk("MERRF:message error.\n"); if(regvalue & 0x40)printk("WAKIF:wake up interrupt.\n"); if(regvalue & 0x20)printk("ERRIF:CAN bus error interrupt.\n"); regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->EFLG)), ARG_UNUSED, ARG_UNUSED ); printk("EFLG = 0x%02x.\n", regvalue2); regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->TEC)), ARG_UNUSED, ARG_UNUSED ); printk("TEC = 0x%02x.\n", regvalue2); regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->REC)), ARG_UNUSED, ARG_UNUSED ); printk("REC = 0x%02x.\n", regvalue2); CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0xe0, 0x00 ); } if(CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED ) & 0x1c){ //didn't open the 3 send interrupts CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x1c, 0x00 ); //clear TX bits directly(it will set 1,but no int) } regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED ); printk("after interrupt processing, CANINTF = 0x%02x\n",regvalue);}static void mcpcan1_handler(int irq, void *dev_id, struct pt_regs *regs){ //printk("\rextern irq ? handled");}/*****************************MCPCAN open**********************************/static int device_open(struct inode *inode,struct file *filp){ int MinorNum; int eint_irq; int ret_val; struct MCP_device *dev; static int irqcount0=0, irqcount1=0; MinorNum = MINOR(inode->i_rdev); if(MinorNum >= MCP_NUM) return(-ENODEV); dev = Device[MinorNum]; filp->private_data = dev; //save to private_data request_region(0x59000000,0x38,"MCPCAN"); //SPI interface request_region(0x56000000,0x94,"MCPCAN"); //I/O port request_region(0x4c00000c,4,"MCPCAN"); //clock /* register the eint5 irq */ if(irqcount0 == 0){ eint_irq = IRQ_EINT5; set_external_irq(eint_irq, EXT_FALLING_EDGE, GPIO_PULLUP_DIS); ret_val = request_irq(eint_irq, mcpcan0_handler, SA_INTERRUPT | SA_SHIRQ, MCP_name[dev->MinorNum], dev); if (ret_val < 0) { return ret_val; } irqcount0++; } MCP2510_Init(MinorNum); MOD_INC_USE_COUNT; return 0;}/*****************************Functin MCP_release**************************/static int device_release(struct inode *inode,struct file *filp){ struct MCP_device *dev = filp->private_data; release_region(0x59000000,0x38); release_region(0x56000000,0x94); release_region(0x4c00000c,4); free_irq(dev->IrqNum,dev); //shared irq MOD_DEC_USE_COUNT; return 0;}ssize_t device_read (struct file *filp, char *buf, size_t count, loff_t *f_pos){ int count0; struct MCP_device *dev = filp->private_data; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; while (dev->RecvHead == dev->RecvTail) { /* nothing to read */ up(&dev->sem); /* release the lock */ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(dev->inq, (dev->RecvHead != dev->RecvTail))) return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ /* otherwise loop, but first reacquire the lock */ if (down_interruptible(&dev->sem)) return -ERESTARTSYS; } /* ok, data is there, return something */ /* count0 is the number of readable data bytes */ count0 = dev->RecvHead - dev->RecvTail; if (count0 < 0) /* wrapped */ count0 = dev->RecvBuf + BUF_SIZE - dev->RecvTail; if (count0 < count) count = count0; if (copy_to_user(buf, (char *)dev->RecvTail, count)){ up (&dev->sem); return -EFAULT; } incr_buffer_pointer(&(dev->RecvTail), count, dev->MinorNum); up (&dev->sem); return count;}ssize_t device_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos){ mcpcan_data temp; struct MCP_device *dev = filp->private_data; if(down_interruptible(&dev->sem)) return -ERESTARTSYS; copy_from_user(&temp, buf, sizeof(struct mcpcan_data)); MCP2510_TX(temp.BufNo,temp.IdType,temp.id,temp.DataLen,temp.data ); up(&dev->sem); return count;}/* This function is called whenever a process tries to * do an ioctl on our device file. We get two extra * parameters (additional to the inode and file * structures, which all device functions get): the number * of the ioctl called and the parameter given to the * ioctl function. * * If the ioctl is write or read/write (meaning output * is returned to the calling process), the ioctl call * returns the output of this function. *//*int device_ioctl( struct inode *inode, struct file *file, unsigned int ioctl_num,// The number of the ioctl unsigned long ioctl_param) // The parameter to it {}*//*****************************File operations define************************/struct file_operations Fops = { .open = device_open, //open .release = device_release, //release .read = device_read, .write = device_write};
/****************************Module initialize******************************/static int __init mcpcan_init_module(void){ int res; //EXPORT_NO_SYMBOLS; /* Register the character device (atleast try) */ res = register_chrdev(MCP_major,"MCPCAN",&Fops); if(res < 0) { printk("device register failed with %d.\n",res); return res; } if(MCP_major == 0) MCP_major = res; MCP_device_init(); printk ("%s The major device number is %d.\n", "Registeration is a success", MCP_major); printk ("If you want to talk to the device driver,\n"); printk ("you'll have to create a device file. \n"); printk ("We suggest you use:\n"); printk ("mknod /dev/%s c %d 0\n", "can",MCP_major); printk ("The device file name is important, because\n"); printk ("the ioctl program assumes that's the\n"); printk ("file you'll use.\n"); return 0;}/****************************Module release********************************/static void __exit mcpcan_cleanup_module(void){ int i; unregister_chrdev(MCP_major,"MCPCAN"); for(i=0; i<2; i++){ kfree((void *)Device[i]->RecvBuf); kfree(Device[i]->SendBuf); kfree(Device[i]); } printk("MCPCAN release success.\n");}module_init(mcpcan_init_module);module_exit(mcpcan_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -