#include "drv_mcp2515i.h"
#define LOW_LEVEL_DEVICE_NAME "spi6"
/******************************* Bit Timing *******************************
Fosc = 8MHz
TQ = 2 * (BRP + 1) / Fosc
**************************************************************************/
static const struct mcp2515_baud_rate_tab can_baud_rate_tab[] =
{
{CAN1MBaud , MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_1TQ , MCP2515_BS2_2TQ , MCP2515_BRP_2},
{CAN500kBaud, MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_4TQ , MCP2515_BS2_2TQ , MCP2515_BRP_2},
{CAN250kBaud, MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_8TQ , MCP2515_BS2_7TQ , MCP2515_BRP_2},
{CAN125kBaud, MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_8TQ , MCP2515_BS2_7TQ , MCP2515_BRP_4},
{CAN100kBaud, MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_5TQ , MCP2515_BS2_4TQ , MCP2515_BRP_8},
{CAN50kBaud , MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_8TQ , MCP2515_BS2_7TQ , MCP2515_BRP_10},
{CAN20kBaud , MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_5TQ , MCP2515_BS2_4TQ , MCP2515_BRP_40},
{CAN10kBaud , MCP2515_SJW_1TQ , MCP2515_PRO_1TQ , MCP2515_BS1_8TQ , MCP2515_BS2_7TQ , MCP2515_BRP_50}
};
/*
这个还需要完善
*/
static FILTER_MAP filter_map[6]={0};
static struct mcp2515_can mcp2515 =
{
.name = "mcp2515",
.low_level_name = "mcp_spi",
.CanHandle.Instance = &mcp2515,
};
static int mcp_command(struct mcp2515_can *can, uint8_t command)
{
MCP2515_COMMAND reg;
reg.command = command;
return rt_spi_send_then_send(can->low_level_device,®,sizeof(reg),RT_NULL,0);
}
static int mcp_modify(struct mcp2515_can *can, uint8_t addr, uint8_t mask, uint8_t data)
{
MCP2515_MODIFY_BYTE reg;
reg.command = MODIFY;
reg.addr = addr;
reg.mask = mask;
reg.value = data;
return rt_spi_send_then_send(can->low_level_device,®,sizeof(reg),RT_NULL,0);
}
static int mcp_status(struct mcp2515_can *can, uint8_t status)
{
rt_err_t err = RT_EOK;
MCP2515_BYTE reg;
if(IS_STATUS_INSTRUCTION(status))
{
reg.command = status;
err = rt_spi_send_then_recv(can->low_level_device,®.command,1,®.data,1);
if(err == RT_EOK)
return (uint32_t)reg.data;
}
return -RT_ERROR;
}
static int mcp_write_bytes(struct mcp2515_can *can, MCP2515_BYTE *regs, uint8_t len)
{
rt_err_t err = RT_EOK;
if(len)
{
RT_ASSERT(regs);
}
else
{
return -RT_EINVAL;
}
for(uint8_t i=0;i<len;i++)
{
regs[i].command = WRITE;
}
for(uint8_t i=0; i<len; i++)
{
err = rt_spi_send_then_send(can->low_level_device,®s[i].command,2,®s[i].data,1);
if(err != RT_EOK)
{
MCP_DEBUG_LOG(("spi send failed!\r\n"));
return -RT_ERROR;
}
}
return RT_EOK;
}
static int mcp_read_bytes(struct mcp2515_can *can, MCP2515_BYTE *regs, uint8_t len)
{
rt_err_t err = RT_EOK;
if(len)
{
RT_ASSERT(regs);
}
else
{
return -RT_EINVAL;
}
for(uint8_t i=0;i<len;i++)
{
regs[i].command = READ;
}
for(uint8_t i=0; i<len; i++)
{
err = rt_spi_send_then_recv(can->low_level_device,®s[i].command,2,®s[i].data,1);
if(err != RT_EOK)
{
MCP_ERROR_LOG(("spi read failed!\r\n"));
return -RT_ERROR;
}
}
return RT_EOK;
}
static int mcp_write_sequential(struct mcp2515_can *can, MCP2515_SEQUENCE *regs)
{
RT_ASSERT(regs);
if(regs->len)
{
RT_ASSERT(regs->data);
}
else
{
return -RT_EINVAL;
}
regs->command = WRITE;
return rt_spi_send_then_send(can->low_level_device,®s->command,2,regs->data,regs->len);
}
static int mcp_read_sequential(struct mcp2515_can *can, MCP2515_SEQUENCE *regs)
{
rt_err_t err = RT_EOK;
RT_ASSERT(IS_READ_BUFFER_COMMAND(regs->command));
switch(regs->command)
{
case READ_RX_BUFFER:
{
/* read rx buffer0 or buffer1 */
if(regs->addr & 0x10)
{
/* read rx buffer1 */
regs->command |= 0x04;
}
/* start at RXBnSIDH or RXBnD0 */
if(regs->addr & 0x06)
{
/* start at RXBnD0 */
regs->command |= 0x02;
regs->len = 8;
}
else
{
/* start at RXBnSIDH */
regs->len = 13;
}
break;
}
case LOAD_TX_BUFFER:
{
/* load from rx buffer 0 、1 or 2 */
if(!(regs->addr & 0x20))
{
/* nothing need to do if load from buffer 0 */
if(!(regs->addr & 0x10))
{
/* load from rx buffer 1 */
regs->command |= 0x02;
}
else
{
/* load from rx buffer 2 */
regs->command |= 0x04;
}
}
/* start at TXBnSIDH or TXBnD0 */
if(regs->addr & 0x06)
{
/* start at TXBnD0 */
regs->command |= 0x01;
regs->len = 8;
}
else
{
/* start at TXBnSIDH */
regs->len = 13;
}
break;
}
}
err = rt_spi_send_then_recv(can->low_level_device,®s->command,1,regs->data,regs->len);
if(err != RT_EOK)
return -RT_ERROR;
for(uint8_t i=13; i>0;i--)
{
regs->data[i] = regs->data[i-1];
}
return RT_EOK;
}
static int mcp_init(struct mcp2515_can *can, MCP2515_InitTypeDef *cfg)
{
MCP2515_BYTE regs[17];
MCP2515_SEQUENCE tx_sequence_regs;
RT_ASSERT(IS_MCP2515_MODE(cfg->Mode));
RT_ASSERT(IS_MCP2515_PRO(cfg->PropSeg));
RT_ASSERT(IS_MCP2515_SJW(cfg->SyncJumpWidth));
RT_ASSERT(IS_MCP2515_BS1(cfg->TimeSeg1));
RT_ASSERT(IS_MCP2515_BS2(cfg->TimeSeg2));
for(uint32_t i=0; i<10000; i++);
mcp_command(can,RESET);
for(uint32_t i=0; i<10000; i++);
mcp_command(can,RESET);
for(uint32_t i=0; i<10000; i++);
mcp_modify(can,CANCTRL,MCP2515_MODE_MSK,(MCP2515_MODE_CONFIG << MCP2515_MODE_POS));
mcp_modify(can,CANCTRL,(0xFF^(MCP2515_MODE_MSK)),0x00);
tx_sequence_regs.addr = BFPCTRL;
tx_sequence_regs.command = WRITE;
tx_sequence_regs.len = 2;
tx_sequence_regs.data[0] = 0x00;
tx_sequence_regs.data[1] = 0x00;
mcp_write_sequential(can,&tx_sequence_regs);
rt_memset(regs,0,sizeof(regs));
regs[0].addr = CNF1;
regs[0].data = (cfg->SyncJumpWidth << MCP2515_SJW_POS) & MCP2515_SJW_MSK; /* Synchronization Jump Width Length bits */
regs[0].data|= (cfg->Prescaler & MCP2515_BRP_MSK); /* Baud Rate Prescaler bits */
regs[1].addr = CNF2;
regs[1].data|= 0x80; /* Length of PS2 determined by PHSEG22:PHSEG20 bits of CNF3 */
regs[1].data|= 0x40; /* Bus line is sampled three times at the sample point */
regs[1].data|= (cfg->TimeSeg1 << MCP2515_BS1_POS) & MCP2515_BS1_MSK; /* PS1 Length bits */
regs[1].data|= (cfg->PropSeg << MCP2515_PRO_POS) & MCP2515_PRO_MSK; /* Propagation Segment Length bits */
regs[2].addr = CNF3;
regs[2].data = 0X00;
regs[2].data|= (cfg->TimeSeg2 << MCP2515_BS2_POS) & MCP2515_BS2_MSK; /* PS2 Length bits */
regs[3].addr = CANINTF;
regs[3].data = 0;
regs[4].addr = CANINTE;
{
uint8_t interrupt_bits = 0;
if(cfg->message_err_int_en == ENABLE)
interrupt_bits |= MESSAGE_ERROR_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~MESSAGE_ERROR_INT_ENABLE;
if(cfg->wake_up_int_en == ENABLE)
interrupt_bits |= WAKE_UP_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~WAKE_UP_INT_ENABLE;
if(cfg->error_int_en == ENABLE)
interrupt_bits |= ERROR_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~ERROR_INT_ENABLE;
if(cfg->receive0_full_int_en == ENABLE)
interrupt_bits |= RECEIVE0_FULL_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~RECEIVE0_FULL_INT_ENABLE;
if(cfg->receive1_full_int_en == ENABLE)
interrupt_bits |= RECEIVE1_FULL_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~RECEIVE1_FULL_INT_ENABLE;
if(cfg->transmit0_empty_int_en == ENABLE)
interrupt_bits |= TRANSMIT0_EMPTY_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~TRANSMIT0_EMPTY_INT_ENABLE;
if(cfg->transmit1_empty_int_en == ENABLE)
interrupt_bits |= TRANSMIT1_EMPTY_INT_ENABLE;
else
interrupt_bits &= (uint8_t)~TRANSMIT1_EMPTY_INT_ENABLE;