代码
感觉错误可能在初始化和中断处理的部分,所以先贴出这两个函数的代码。
#define BFPCTRL_INIT_VAL (0x00)
//(0x3c)
/// Transmitter Request to Send pin : Digital Input
#define TXRTSCTRL_INIT_VAL (0x00)
/// Configure the bit timing : 125kHZ
#define CNF1_INIT_VAL (0x03)
#define CNF2_INIT_VAL (0x9e)
#define CNF3_INIT_VAL (0x03)
// Configure the interrupt : disable all interrupts
#define CANINTE_INIT_VAL (0x63)
//(0xe3)
#define CANINTF_INIT_VAL (0x00)
// Reset Error Flag Register
#define EFLG_INIT_VAL (0x00)
// Transmitter Buffer Control
#define TXB0CTRL_INIT_VAL (0x00)
#define TXB1CTRL_INIT_VAL (0x00)
#define TXB2CTRL_INIT_VAL (0x00)
// Receiver Buffer 0 Control Register : Turn remote frame off, turn filter RXF0 on, turn rollover on
#define RXB0CTRL_INIT_VAL (0x24)
//#define RXB0CTRL_INIT_VAL (0x64)
// Receiver Buffer 1 Control Register : Turn remote frame off, turn filter RXF0 on
#define RXB1CTRL_INIT_VAL (0X40)
//(0x20)
// Receiver Buffer n Fliter : set the fliter SID = 20
#define RXFnSIDH_INIT_VAL (0x02)
#define RXFnSIDL_INIT_VAL (0x80)
#define RXMnSIDH_INIT_VAL (0xff)
#define RXMnSIDL_INIT_VAL (0xff)
void
MCP2510_Init(int MinorNum)
{
printk("This is MCP2510_Init!\n");
printk("Configure the SPI Interface in MX1\n");
/// Configure the SPI Interface in MX1
SPI_Init();
printk("Configure the mcp2510 through spi interface\n");
printk("in test, leave them alone\n");
/// Configure the mcp2510 through spi interface
/// Reset controller
CAN_SPI_CMD( SPI_CMD_RESET, ARG_UNUSED, ARG_UNUSED, ARG_UNUSED );
/// CONFIG MODE
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x80 );
printk("%x\n", CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED ));
/// Make sure we are in configuration mode
while( (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5)!=0x04 );
/// Start configuration
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->BFPCTRL)), BFPCTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXRTSCTRL)), TXRTSCTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF3)), CNF3_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF2)), CNF2_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF1)), CNF1_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTE)), CANINTE_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTF)), CANINTF_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->EFLG)), EFLG_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0CTRL)), TXB0CTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB1CTRL)), TXB1CTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB2CTRL)), TXB2CTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0CTRL)), RXB0CTRL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1CTRL)), RXB1CTRL_INIT_VAL, ARG_UNUSED);
// CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0SIDH)), RXBnSIDH_INIT_VAL, ARG_UNUSED);
// CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1SIDH)), RXBnSIDH_INIT_VAL, ARG_UNUSED);
// CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0SIDL)), RXBnSIDL_INIT_VAL, ARG_UNUSED);
// CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1SIDL)), RXBnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXM0SIDH)), RXMnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXM0SIDL)), RXMnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF0SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF0SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF1SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF1SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF2SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF2SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF3SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF3SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF4SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF4SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF5SIDH)), RXFnSIDH_INIT_VAL, ARG_UNUSED);
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF5SIDL)), RXFnSIDL_INIT_VAL, ARG_UNUSED);
/// Switch to normal mode or loopback mode ( for testing)
#if 0
/// LOOP BACK MODE
printk("config loop back!%x\n", TOLONG(&MCP2510_MAP->CANCTRL));
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x40 );
#endif
/// NORMAL OPERATION MODE
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );
/// Flush the MX1 SPI receive buffer
CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED );
}
static void
mcpcan0_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct MCP_device *dev = dev_id;
struct mcpcan_data datagram;
char regvalue, regvalue2;
int i;
regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
// printk("CANINTF = 0x%02x\n",regvalue);
//printk("recv is %d\n", recvCount);
//while (regvalue & 0xe3) {
while (regvalue & 0x63) {
if (regvalue & 0x60) {
/*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");
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );
break;
}
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);
if (regvalue2) {
overFlow++;
CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->EFLG)), 0x00, ARG_UNUSED);
}
}*/
/*
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);
*/
err++;
//printk("err is %d, recv is %d, overflow is %d\n", err, recvCount, overFlow);
/*memcpy(&datagram, (void *)(dev->recvBuf + dev->recvHead - 28), 28);
for (i = 0; i < 8; i++) {
printk("%d ", datagram.data[i]);
}
printk("\n");*/
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x40, 0x00 );
}
if (regvalue & 0x01) {
datagram.BufNo = RXBUF0;
MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );
//printk("RXBUF0\n");
/// Write a 16 byte record. Assume BUF_SIZE is a multiple of 16
memcpy((void *)(dev->recvBuf + dev->recvHead), &datagram, sizeof(struct mcpcan_data));
/*
if (regvalue & 0x20) {
for (i = 0; i < datagram.DataLen; i++) {
printk("%d ", datagram.data[i]);
}
printk("\n");
}*/
//incr_buffer_pointer(&(dev->recvHead), sizeof(struct mcpcan_data), dev->MinorNum);
/**
* process the recvBuf
* 0. normally move recvHead
* 1. if recvFlag is 1, meaning that the buffer has full
* then throw away the earliest frame
* by keeping recvTail equal with recvHead
* 2. otherwise, the buffer has not been full
*
* after receive the most recent frame, check the buffer
* if the buffer has been full, set recvFlag
*/
dev->recvHead += sizeof (struct mcpcan_data);
if (dev->recvHead >= BUF_SIZE) {
dev->recvHead = 0;
}
if (dev->recvFlag == 1) {
dev->recvTail = dev->recvHead;
lost++;
} else if (dev->recvTail == dev->recvHead) {
dev->recvFlag = 1;
}
/// Awake any reading process
//wake_up_interruptible(&(dev->inq));
/// In fact already clear interrupt bit in RX
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x01, 0x00 );
recvCount++;
}
if (regvalue & 0x02) {
datagram.BufNo = RXBUF1;
MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );
//printk("RXBUF1, %d\n", recvCount);
/// Write a 16 byte record. Assume BUF_SIZE is a multiple of 16
memcpy((void *)(dev->recvBuf + dev->recvHead), &datagram, sizeof(struct mcpcan_data));
/*if (regvalue & 0x20) {
for (i = 0; i < datagram.DataLen; i++) {
printk("%d ", datagram.data[i]);
}
printk("\n");
}*/
//incr_buffer_pointer(&(dev->recvHead), sizeof(struct mcpcan_data), dev->MinorNum);
dev->recvHead += sizeof (struct mcpcan_data);
if (dev->recvHead == BUF_SIZE) {
dev->recvHead = 0;
}
if (dev->recvFlag == 1) {
dev->recvTail = dev->recvHead;
lost++;
} else if (dev->recvTail == dev->recvHead) {
dev->recvFlag = 1;
}
/// Awake any reading process
//wake_up_interruptible(&dev->inq);
/// In fact already clear interrupt bit in RX
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x02, 0x00 );
recvCount++;
}
/// Didn't open the 3 send interrupts
if (regvalue & 0x1c) {
/// Clear TX bits directly(it will set 1,but no int)
CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x1c, 0x00 );
}
regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
}
/*regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
printk("after interrupt processing, CANINTF = 0x%02x\n",regvalue);*/
}