#include <board.h>
|
#include <board.h>
|
#include <support.h>
|
#include <support.h>
|
#include "can.h"
|
#include "can.h"
|
|
|
int can_rx_done, can_tx_done;
|
int can_rx_done, can_tx_done;
|
int can_rx_rd_ptr;
|
int can_rx_rd_ptr;
|
int can_rx_wr_ptr;
|
int can_rx_wr_ptr;
|
int can_rx_buf_overflow;
|
int can_rx_buf_overflow;
|
|
|
can_type can_rx_data[CAN_BUF_LEN], can_tx_data;
|
can_type can_rx_data[CAN_BUF_LEN], can_tx_data;
|
|
|
can_type * can_get(void)
|
can_type * can_get(void)
|
{
|
{
|
if ( !can_rx_done )
|
if ( !can_rx_done )
|
return NULL;
|
return NULL;
|
|
|
can_rx_done--;
|
can_rx_done--;
|
|
|
int tmp;
|
int tmp;
|
tmp = can_rx_rd_ptr;
|
tmp = can_rx_rd_ptr;
|
|
|
if (can_rx_rd_ptr < CAN_BUF_LEN-1)
|
if (can_rx_rd_ptr < CAN_BUF_LEN-1)
|
can_rx_rd_ptr++;
|
can_rx_rd_ptr++;
|
else
|
else
|
can_rx_rd_ptr = 0;
|
can_rx_rd_ptr = 0;
|
|
|
return &can_rx_data[tmp];
|
return &can_rx_data[tmp];
|
}
|
}
|
|
|
void can_init(void)
|
void can_init(void)
|
{
|
{
|
unsigned char sync_jmp, baudrate_presc, timing_seg1, timing_seg2, tripple_samp = 0;
|
unsigned char sync_jmp, baudrate_presc, timing_seg1, timing_seg2, tripple_samp = 0;
|
unsigned char acpt_code, acpt_mask = 0;
|
unsigned char acpt_code, acpt_mask = 0;
|
unsigned char clk_div = 0 & CAN_BUS_CLKDIV_MASK;
|
unsigned char clk_div = 0 & CAN_BUS_CLKDIV_MASK;
|
|
|
sync_jmp = 1;
|
sync_jmp = 1;
|
baudrate_presc = 1;
|
baudrate_presc = 1;
|
timing_seg1 = 11;
|
timing_seg1 = 11;
|
timing_seg2 = 2;
|
timing_seg2 = 2;
|
tripple_samp = 1;
|
tripple_samp = 1;
|
|
|
acpt_code = 0x81;
|
acpt_code = 0x81;
|
acpt_mask = 0xFF;
|
acpt_mask = 0xFF;
|
|
|
char timing0, timing1 = 0;
|
char timing0, timing1 = 0;
|
|
|
timing0 = (sync_jmp << CAN_BUS_TIMING_0_SYNC_JMP_SHIFT) & CAN_BUS_TIMING_0_SYNC_JMP;
|
timing0 = (sync_jmp << CAN_BUS_TIMING_0_SYNC_JMP_SHIFT) & CAN_BUS_TIMING_0_SYNC_JMP;
|
timing0 |= baudrate_presc & CAN_BUS_TIMING_0_BAUD_PRESC;
|
timing0 |= baudrate_presc & CAN_BUS_TIMING_0_BAUD_PRESC;
|
|
|
timing1 = (tripple_samp << CAN_BUS_TIMING_1_TRIPLE_SAMP_SHIFT) & CAN_BUS_TIMING_1_TRIPLE_SAMP;
|
timing1 = (tripple_samp << CAN_BUS_TIMING_1_TRIPLE_SAMP_SHIFT) & CAN_BUS_TIMING_1_TRIPLE_SAMP;
|
timing1 |= (timing_seg2 << CAN_BUS_TIMING_1_TIME_SEG2_SHIFT) & CAN_BUS_TIMING_1_TIME_SEG2;
|
timing1 |= (timing_seg2 << CAN_BUS_TIMING_1_TIME_SEG2_SHIFT) & CAN_BUS_TIMING_1_TIME_SEG2;
|
timing1 |= timing_seg1 & CAN_BUS_TIMING_1_TIME_SEG1;
|
timing1 |= timing_seg1 & CAN_BUS_TIMING_1_TIME_SEG1;
|
|
|
REG8(CAN_BASE+CAN_MODE) = CAN_MODE_RESET;
|
REG8(CAN_BASE+CAN_MODE) = CAN_MODE_RESET;
|
|
|
REG8(CAN_BASE+CAN_BUS_TIMING_0) = timing0;
|
REG8(CAN_BASE+CAN_BUS_TIMING_0) = timing0;
|
REG8(CAN_BASE+CAN_BUS_TIMING_1) = timing1;
|
REG8(CAN_BASE+CAN_BUS_TIMING_1) = timing1;
|
|
|
REG8(CAN_BASE+CAN_ACPT_CODE0) = acpt_code;
|
REG8(CAN_BASE+CAN_ACPT_CODE0) = acpt_code;
|
REG8(CAN_BASE+CAN_ACPT_MASK0) = acpt_mask;
|
REG8(CAN_BASE+CAN_ACPT_MASK0) = acpt_mask;
|
|
|
REG8(CAN_BASE+CAN_BUS_MODE) &= ~CAN_BUS_MODE_CLOCK_OFF & ~CAN_BUS_MODE_EXTENDED_MODE;
|
REG8(CAN_BASE+CAN_BUS_MODE) &= ~CAN_BUS_MODE_CLOCK_OFF & ~CAN_BUS_MODE_EXTENDED_MODE;
|
|
|
REG8(CAN_BASE+CAN_MODE) &= ~CAN_MODE_RESET;
|
REG8(CAN_BASE+CAN_MODE) &= ~CAN_MODE_RESET;
|
REG8(CAN_BASE+CAN_BUS_CLKDIV) = clk_div;
|
REG8(CAN_BASE+CAN_BUS_CLKDIV) = clk_div;
|
|
|
REG8(CAN_BASE+CAN_MODE) |= CAN_MODE_TX_IRQ_EN | CAN_MODE_RECV_IRQ_EN;
|
REG8(CAN_BASE+CAN_MODE) |= CAN_MODE_TX_IRQ_EN | CAN_MODE_RECV_IRQ_EN;
|
|
|
can_tx_done = 1;
|
can_tx_done = 1;
|
can_rx_done = 0;
|
can_rx_done = 0;
|
can_rx_rd_ptr = 0;
|
can_rx_rd_ptr = 0;
|
can_rx_wr_ptr = 0;
|
can_rx_wr_ptr = 0;
|
can_rx_buf_overflow = 0;
|
can_rx_buf_overflow = 0;
|
}
|
}
|
|
|
void can_recv_basic()
|
void can_recv_basic()
|
{
|
{
|
unsigned char byte0, byte1;
|
unsigned char byte0, byte1;
|
|
|
byte0 = REG8(CAN_BASE+CAN_RX_BUF);
|
byte0 = REG8(CAN_BASE+CAN_RX_BUF);
|
byte1 = REG8(CAN_BASE+CAN_RX_BUF+1);
|
byte1 = REG8(CAN_BASE+CAN_RX_BUF+1);
|
|
|
can_rx_data[can_rx_wr_ptr].data[0] = REG8(CAN_BASE+CAN_RX_BUF+2);
|
can_rx_data[can_rx_wr_ptr].data[0] = REG8(CAN_BASE+CAN_RX_BUF+2);
|
can_rx_data[can_rx_wr_ptr].data[1] = REG8(CAN_BASE+CAN_RX_BUF+3);
|
can_rx_data[can_rx_wr_ptr].data[1] = REG8(CAN_BASE+CAN_RX_BUF+3);
|
can_rx_data[can_rx_wr_ptr].data[2] = REG8(CAN_BASE+CAN_RX_BUF+4);
|
can_rx_data[can_rx_wr_ptr].data[2] = REG8(CAN_BASE+CAN_RX_BUF+4);
|
can_rx_data[can_rx_wr_ptr].data[3] = REG8(CAN_BASE+CAN_RX_BUF+5);
|
can_rx_data[can_rx_wr_ptr].data[3] = REG8(CAN_BASE+CAN_RX_BUF+5);
|
can_rx_data[can_rx_wr_ptr].data[4] = REG8(CAN_BASE+CAN_RX_BUF+6);
|
can_rx_data[can_rx_wr_ptr].data[4] = REG8(CAN_BASE+CAN_RX_BUF+6);
|
can_rx_data[can_rx_wr_ptr].data[5] = REG8(CAN_BASE+CAN_RX_BUF+7);
|
can_rx_data[can_rx_wr_ptr].data[5] = REG8(CAN_BASE+CAN_RX_BUF+7);
|
can_rx_data[can_rx_wr_ptr].data[6] = REG8(CAN_BASE+CAN_RX_BUF+8);
|
can_rx_data[can_rx_wr_ptr].data[6] = REG8(CAN_BASE+CAN_RX_BUF+8);
|
can_rx_data[can_rx_wr_ptr].data[7] = REG8(CAN_BASE+CAN_RX_BUF+9);
|
can_rx_data[can_rx_wr_ptr].data[7] = REG8(CAN_BASE+CAN_RX_BUF+9);
|
|
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_RELEASE_BUFFER;
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_RELEASE_BUFFER;
|
|
|
can_rx_data[can_rx_wr_ptr].identifier = (byte0 << 3) | (byte1 >> 5);
|
can_rx_data[can_rx_wr_ptr].identifier = (byte0 << 3) | (byte1 >> 5);
|
can_rx_data[can_rx_wr_ptr].rtr = byte1 & 0x10;
|
can_rx_data[can_rx_wr_ptr].rtr = byte1 & 0x10;
|
can_rx_data[can_rx_wr_ptr].len = byte1 & 0x0F;
|
can_rx_data[can_rx_wr_ptr].len = byte1 & 0x0F;
|
|
|
if (can_rx_wr_ptr < CAN_BUF_LEN-1)
|
if (can_rx_wr_ptr < CAN_BUF_LEN-1)
|
can_rx_wr_ptr++;
|
can_rx_wr_ptr++;
|
else
|
else
|
can_rx_wr_ptr = 0;
|
can_rx_wr_ptr = 0;
|
|
|
if (can_rx_wr_ptr == can_rx_rd_ptr+1) //buffer overflow
|
if (can_rx_wr_ptr == can_rx_rd_ptr+1) //buffer overflow
|
{
|
{
|
can_rx_done = 1;
|
can_rx_done = 1;
|
can_rx_buf_overflow++;
|
can_rx_buf_overflow++;
|
}
|
}
|
else
|
else
|
can_rx_done++;
|
can_rx_done++;
|
}
|
}
|
|
|
int can_send_basic()
|
int can_send_basic()
|
{
|
{
|
if (!can_tx_done) //if previous command not fully processed, bail out
|
if (!can_tx_done) //if previous command not fully processed, bail out
|
return -1;
|
return -1;
|
|
|
can_tx_done = 0;
|
can_tx_done = 0;
|
REG8(CAN_BASE+CAN_TX_BUF) = can_tx_data.identifier >> 3;
|
REG8(CAN_BASE+CAN_TX_BUF) = can_tx_data.identifier >> 3;
|
REG8(CAN_BASE+CAN_TX_BUF+1) = (can_tx_data.identifier << 5) | ((can_tx_data.rtr << 4) & 0x10) | (can_tx_data.len & 0x0F);
|
REG8(CAN_BASE+CAN_TX_BUF+1) = (can_tx_data.identifier << 5) | ((can_tx_data.rtr << 4) & 0x10) | (can_tx_data.len & 0x0F);
|
|
|
REG8(CAN_BASE+CAN_TX_BUF+2) = can_tx_data.data[0];
|
REG8(CAN_BASE+CAN_TX_BUF+2) = can_tx_data.data[0];
|
REG8(CAN_BASE+CAN_TX_BUF+3) = can_tx_data.data[1];
|
REG8(CAN_BASE+CAN_TX_BUF+3) = can_tx_data.data[1];
|
REG8(CAN_BASE+CAN_TX_BUF+4) = can_tx_data.data[2];
|
REG8(CAN_BASE+CAN_TX_BUF+4) = can_tx_data.data[2];
|
REG8(CAN_BASE+CAN_TX_BUF+5) = can_tx_data.data[3];
|
REG8(CAN_BASE+CAN_TX_BUF+5) = can_tx_data.data[3];
|
REG8(CAN_BASE+CAN_TX_BUF+6) = can_tx_data.data[4];
|
REG8(CAN_BASE+CAN_TX_BUF+6) = can_tx_data.data[4];
|
REG8(CAN_BASE+CAN_TX_BUF+7) = can_tx_data.data[5];
|
REG8(CAN_BASE+CAN_TX_BUF+7) = can_tx_data.data[5];
|
REG8(CAN_BASE+CAN_TX_BUF+8) = can_tx_data.data[6];
|
REG8(CAN_BASE+CAN_TX_BUF+8) = can_tx_data.data[6];
|
REG8(CAN_BASE+CAN_TX_BUF+9) = can_tx_data.data[7];
|
REG8(CAN_BASE+CAN_TX_BUF+9) = can_tx_data.data[7];
|
|
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_TX_REQ;
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_TX_REQ;
|
|
|
return can_tx_data.len;
|
return can_tx_data.len;
|
}
|
}
|
|
|
void can_irq(void)
|
void can_irq(void)
|
{
|
{
|
unsigned char irq_req, rx_done;
|
unsigned char irq_req, rx_done;
|
irq_req = REG8(CAN_BASE+IRQ_READ);
|
irq_req = REG8(CAN_BASE+IRQ_READ);
|
rx_done = irq_req & CAN_IRQ_READ_RX;
|
rx_done = irq_req & CAN_IRQ_READ_RX;
|
can_tx_done = irq_req & CAN_IRQ_READ_TX;
|
can_tx_done = irq_req & CAN_IRQ_READ_TX;
|
if (rx_done)
|
if (rx_done)
|
can_recv_basic();
|
can_recv_basic();
|
}
|
}
|
|
|
void can_abort(void)
|
void can_abort(void)
|
{
|
{
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_ABORT_TX;
|
REG8(CAN_BASE+CAN_CMD) = CAN_CMD_ABORT_TX;
|
}
|
}
|
|
|
|
|