static void CAN_configPin();
static void CAN_setBusTiming(struct canchip_t *chip);
-extern struct canhardware_t *hardware_p;
-
-//---------------------------------------------------------------------------------
-//---------------------------------------------------------------------------------
-
-
-static inline void can_write_register(struct canchip_t *chip, uint32_t data, uint32_t reg_offs){
-
- uint32_t address = chip->chip_base_addr + reg_offs;
- (*(volatile uint32_t*)(address)) = data;
-
-}
-
-static inline uint32_t can_read_register(struct canchip_t *chip, uint32_t reg_offs){
-
- uint32_t address = chip->chip_base_addr + reg_offs;
- return (*(volatile uint32_t*)(address));
-
-}
-
-//---------------------------------------------------------------------------------
-//---------------------------------------------------------------------------------
-
-
-// interrupt handler
-// for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
-// for receiving - irq when message was received and is available in Receive buffer
-
-void CAN_IRQHandler(){
-
- uint32_t i;
-
- struct canchip_t *chip;
- chip = hardware_p->candevice[0]->chip[0];
-
- i = can_read_register(chip, CAN_ICR_o);
-
- if(i & (CAN_ICR_TI1 | CAN_ICR_RI))
- lpc17xx_irq_handler(0, chip);
-
- if(i & CAN_ICR_DOI)
- can_write_register(chip, CAN_CMR_CDO, CAN_CMR_o);
-
-
-}
+#define MAX_TRANSMIT_WAIT_LOOPS 20
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
hwspecops->init_obj_data = can_lmc1_init_obj_data;
hwspecops->write_register = can_lmc1_write_register;
hwspecops->read_register = can_lmc1_read_register;
+ hwspecops->program_irq = can_lmc1_program_irq;
return 0;
}
candev->nr_82527_chips=0;
candev->nr_sja1000_chips=0;
candev->nr_all_chips=1;
- candev->flags |= 0;
+ candev->flags = 0;
return 0;
}
int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
-
- lpc17xx_fill_chipspecops(candev->chip[chipnr]);
- candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
-
- //debug
+ // used CAN1 peripherial -> CAN1 registers base
candev->chip[chipnr]->chip_base_addr = CAN1_REGS_BASE;
+ lpc17xx_fill_chipspecops(candev->chip[chipnr]);
+
candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
if (candev->chip[chipnr]->chip_data==NULL)
return -ENOMEM;
return 0;
}
+int can_lmc1_program_irq(struct candevice_t *candev)
+{
+ return 0;
+}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
struct canmsg_t *msg)
{
-
+ uint32_t i=0;
+
// write transmission request
- can_write_register(chip, (CAN_CMR_TR | CAN_CMR_STB1), CAN_CMR_o);
+ can_write_reg(chip, (CAN_CMR_TR | CAN_CMR_STB1), CAN_CMR_o);
+
+ while (!(can_read_reg(chip, CAN_SR_o) & (1<<3))){
+ if(i++<MAX_TRANSMIT_WAIT_LOOPS)
+ continue;
+
+ // request command to abort transmission request
+ can_write_reg(chip, CAN_CMR_AT, CAN_CMR_o);
+ break;
+ }
return 0;
}
while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
can_msgobj_clear_fl(obj,TX_REQUEST);
- if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
+ if (can_read_reg(chip, CAN_SR_o) & CAN_SR_TBS1){
obj->tx_retry_cnt=0;
lpc17xx_irq_write_handler(chip, obj);
}
int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
{
+ uint32_t i;
struct msgobj_t *obj;
obj = chip->msgobj[0];
- if(can_read_register(chip, CAN_SR_o) & CAN_SR_RBS) {
- lpc17xx_read(chip,obj);
- obj->ret = 0;
- }
+ i = can_read_reg(chip, CAN_ICR_o);
+
+ if(i & (CAN_ICR_TI1 | CAN_ICR_RI)){
+
+ if(can_read_reg(chip, CAN_SR_o) & CAN_SR_RBS) {
+ lpc17xx_read(chip,obj);
+ obj->ret = 0;
+ }
- if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
+
+ if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
- can_msgobj_set_fl(obj,TX_REQUEST);
+ can_msgobj_set_fl(obj,TX_REQUEST);
- while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
+ while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
- obj->ret=0;
- can_msgobj_clear_fl(obj,TX_REQUEST);
+ obj->ret=0;
+ can_msgobj_clear_fl(obj,TX_REQUEST);
- if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
- obj->tx_retry_cnt=0;
- lpc17xx_irq_write_handler(chip, obj);
- }
+ if (can_read_reg(chip, CAN_SR_o) & CAN_SR_TBS1){
+ obj->tx_retry_cnt=0;
+ lpc17xx_irq_write_handler(chip, obj);
+ }
- can_msgobj_clear_fl(obj,TX_LOCK);
- if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+ can_msgobj_clear_fl(obj,TX_LOCK);
+ if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+
+ }
+ }
- }
}
+ if(i & CAN_ICR_DOI)
+ can_write_reg(chip, CAN_CMR_CDO, CAN_CMR_o); // clear data overrun
return CANCHIP_IRQ_HANDLED;
{
int cmd;
+
if(obj->tx_slot){
/* Do local transmitted message distribution if enabled */
if (processlocal){
canque_filter_msg2edges(obj->qends, &obj->rx_msg);
// release Receive buffer
- can_write_register(chip, CAN_CMR_RRB, CAN_CMR_o);
+ can_write_reg(chip, CAN_CMR_RRB, CAN_CMR_o);
}
int lpc17xx_fill_chipspecops(struct canchip_t *chip){
chip->max_objects=1;
+ chip->chip_irq = CAN_IRQn;
lpc17xx_register(chip->chipspecops);
uint32_t i;
// read data lenght
- msg->length = (can_read_register(chip, CAN_RFS_o)>>16) & 0xF;
+ msg->length = (can_read_reg(chip, CAN_RFS_o)>>16) & 0xF;
// read identifier
- msg->id = can_read_register(chip, CAN_RID_o);
+ msg->id = can_read_reg(chip, CAN_RID_o);
// EXT frame
- if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_EXT)
+ if(can_read_reg(chip, CAN_RFS_o) & CAN_RFS_EXT)
msg->flags |= MSG_EXT;
else
msg->flags &= ~MSG_EXT;
// RTR frame
- if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_RTR)
+ if(can_read_reg(chip, CAN_RFS_o) & CAN_RFS_RTR)
msg->flags |= MSG_RTR;
else
msg->flags &= ~MSG_RTR;
// read data
- data = can_read_register(chip, CAN_RDA_o);
+ data = can_read_reg(chip, CAN_RDA_o);
for(i=0; i<4; i++)
msg->data[i] = (data>>(i*8)) & 0xFF;
- data = can_read_register(chip, CAN_RDB_o);
+ data = can_read_reg(chip, CAN_RDB_o);
for(i=4; i<8; i++)
msg->data[i] = (data>>((i-4)*8)) & 0xFF;
}
+
void CAN_send(struct canchip_t *chip, canmsg_t* msg){
volatile uint32_t data;
volatile uint32_t can_tfi1;
- uint32_t i;
+ uint32_t i=0;
// check status of TB1
- while (!(can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1)){}
+ while (!(can_read_reg(chip, CAN_SR_o) & CAN_SR_TBS1)){
+ if(i++<MAX_TRANSMIT_WAIT_LOOPS)
+ continue;
+
+ // request command to abort transmission request
+ can_write_reg(chip, CAN_CMR_AT, CAN_CMR_o);
+ return;
+ }
- can_tfi1 = can_read_register(chip, CAN_TFI1_o);
+ can_tfi1 = can_read_reg(chip, CAN_TFI1_o);
can_tfi1 &= ~0x000F0000;
can_tfi1 |= (msg->length)<<16;
else
can_tfi1 &= ~CAN_TFI1_RTR;
- can_write_register(chip, can_tfi1, CAN_TFI1_o);
+ can_write_reg(chip, can_tfi1, CAN_TFI1_o);
// write CAN ID
- can_write_register(chip, msg->id, CAN_TID1_o);
+ can_write_reg(chip, msg->id, CAN_TID1_o);
// write first 4 data bytes
for(i=0; i<4; i++)
data |= (msg->data[i])<<(i*8);
- can_write_register(chip, data, CAN_TDA1_o);
+ can_write_reg(chip, data, CAN_TDA1_o);
// write second 4 data bytes
data=0;
for(i=4; i<8; i++)
data |= (msg->data[i])<<((i-4)*8);
- can_write_register(chip, data, CAN_TDB1_o);
+ can_write_reg(chip, data, CAN_TDB1_o);
+
+}
+
+void CAN_set_bittiming(struct canchip_t *chip, uint32_t brp, uint32_t sjw, uint32_t tseg1, uint32_t tseg2){
+
+ uint8_t SAM = 0; // 0 = the bus is sampled once
+
+ brp--;
+ sjw--;
+ tseg1--;
+ tseg2--;
+
+ can_disable_irq(chip->chip_irq);
+ // enter reset mode
+ can_write_reg(chip, 1, CAN_MOD_o);
+
+
+ can_write_reg(chip, ((SAM<<23)|(tseg2<<20)|(tseg1<<16)|(sjw<<14)|(brp<<0)), CAN_BTR_o);
+
+ // return to normal operating
+ can_write_reg(chip, 0, CAN_MOD_o);
+
+ can_enable_irq(chip->chip_irq);
}
void CAN_setBusTiming(struct canchip_t *chip){
uint8_t SAM;
uint8_t div;
+ TSEG1 = TSEG2 = BRP = 0;
+
// 0 = the bus is sampled once
SAM = 0;
}
}
- can_write_register(chip, ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0)), CAN_BTR_o);
+ can_write_reg(chip, ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0)), CAN_BTR_o);
}
uint32_t val;
uint32_t i;
- printf("CAN INIT, baudrate: %d\n", chip->baudrate);
+ printf("CAN INIT, baudrate: %d\n", (int) chip->baudrate);
// configure CAN1 pins
CAN_configPin();
SC->PCLKSEL0 = pclksel0;
// enter reset mode
- can_write_register(chip, 1, CAN_MOD_o);
+ can_write_reg(chip, 1, CAN_MOD_o);
// disable all CAN interrupts
- can_write_register(chip, 0, CAN_IER_o);
+ can_write_reg(chip, 0, CAN_IER_o);
// reset value of Global Status Register (global controller status and error counters)
- can_write_register(chip, 0x3C, CAN_GSR_o);
+ can_write_reg(chip, 0x3C, CAN_GSR_o);
// request command to release Rx, Tx buffer and clear data overrun
- can_write_register(chip, (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO), CAN_CMR_o);
+ can_write_reg(chip, (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO), CAN_CMR_o);
// read to clear interrupt pending in Interrupt Capture Register
- tmp = can_read_register(chip, CAN_ICR_o);
+ tmp = can_read_reg(chip, CAN_ICR_o);
// set bus timing
CAN_setBusTiming(chip);
// return to normal operating
- can_write_register(chip, 0, CAN_MOD_o);
+ can_write_reg(chip, 0, CAN_MOD_o);
//--------------------------
// enable interrupt after transmit
// enable receive interrupt
// enable data overrun interrupt
- can_write_register(chip, (CAN_IER_TIE1 | CAN_IER_RIE | CAN_IER_DOIE), CAN_IER_o);
+ can_write_reg(chip, (CAN_IER_TIE1 | CAN_IER_RIE | CAN_IER_DOIE), CAN_IER_o);
- // enable CAN interrupt
- NVIC_EnableIRQ(CAN_IRQn);
-
-
}