X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/ad1d46af5c8562e90a3f8564cf511213ff1f1745..060d6f042deb8d82aaeb9de8701cd3405bb4c066:/embedded/app/usbcan/lpc17xx_can.c diff --git a/embedded/app/usbcan/lpc17xx_can.c b/embedded/app/usbcan/lpc17xx_can.c index eee3718..ec82757 100644 --- a/embedded/app/usbcan/lpc17xx_can.c +++ b/embedded/app/usbcan/lpc17xx_can.c @@ -3,7 +3,277 @@ static void CAN_configPin(); static void CAN_setBusTiming(uint32_t baudrate); -//------------------------------------------ +extern struct canhardware_t *hardware_p; + +//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- + +// interrupt handler +// now only for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue) + +void CAN_IRQHandler(){ + + uint32_t i; + + i = CAN1ICR; + if(!(i & CAN_ICR_TI1)) + return; + + + struct canchip_t *chip; + chip = hardware_p->candevice[0]->chip[0]; + + lpc17xx_irq_handler(0, chip); + +} + + +//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- + + +// board can-lmc1 specific functions: + +int can_lmc1_register(struct hwspecops_t *hwspecops){ + + hwspecops->request_io = can_lmc1_request_io; + hwspecops->reset = can_lmc1_reset; + hwspecops->init_hw_data = can_lmc1_init_hw_data; + hwspecops->init_chip_data = can_lmc1_init_chip_data; + hwspecops->init_obj_data = can_lmc1_init_obj_data; + hwspecops->write_register = can_lmc1_write_register; + hwspecops->read_register = can_lmc1_read_register; + + return 0; +} + +int can_lmc1_init_hw_data(struct candevice_t *candev){ + + candev->res_addr=0; + candev->nr_82527_chips=0; + candev->nr_sja1000_chips=0; + candev->nr_all_chips=1; + 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; + + 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_init_obj_data(struct canchip_t *chip, int objnr){ + + //chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10; + + return 0; +} + +void can_lmc1_write_register(unsigned data, unsigned long address){ + + printf("UNSUPPORTED NOW\n"); + +} + +unsigned can_lmc1_read_register(unsigned long address){ + + printf("UNSUPPORTED NOW\n"); + +} + +int can_lmc1_request_io(struct candevice_t *candev) +{ + return 0; +} + +int can_lmc1_reset(struct candevice_t *candev) +{ + return 0; +} + + +//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- + + +// lpc17xx can chip specific functions: + + +int lpc17xx_chip_config(struct canchip_t *chip){ + + CAN_init( (uint32_t) chip->baudrate); + + return 0; +} + +int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, + struct canmsg_t *msg) +{ + + CAN_send(msg); + + return 0; +} + +int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj, + struct canmsg_t *msg) +{ + + // write transmission request + CAN1CMR = (CAN_CMR_TR | CAN_CMR_STB1); + + return 0; +} + +int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) +{ + + can_preempt_disable(); + + can_msgobj_set_fl(obj,TX_PENDING); + can_msgobj_set_fl(obj,TX_REQUEST); + + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); + + + if (CAN1SR & 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_preempt_enable(); + + return 0; +} + +int lpc17xx_irq_handler(int irq, struct canchip_t *chip) +{ + + struct msgobj_t *obj; + obj = chip->msgobj[0]; + + + if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) { + + can_msgobj_set_fl(obj,TX_REQUEST); + + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + + obj->ret=0; + can_msgobj_clear_fl(obj,TX_REQUEST); + + if (CAN1SR & 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; + + } + } + + return CANCHIP_IRQ_HANDLED; + +} + +void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj) +{ + int cmd; + + if(obj->tx_slot){ + /* Do local transmitted message distribution if enabled */ + if (processlocal){ + /* fill CAN message timestamp */ + can_filltimestamp(&obj->tx_slot->msg.timestamp); + + obj->tx_slot->msg.flags |= MSG_LOCAL; + canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg); + } + /* Free transmitted slot */ + canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); + obj->tx_slot=NULL; + } + + can_msgobj_clear_fl(obj,TX_PENDING); + cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); + if(cmd<0) + return; + can_msgobj_set_fl(obj,TX_PENDING); + + if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) { + obj->ret = -1; + canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP); + canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); + obj->tx_slot=NULL; + return; + } + if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) { + obj->ret = -1; + canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND); + canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); + obj->tx_slot=NULL; + return; + } + +} + +int lpc17xx_fill_chipspecops(struct canchip_t *chip){ + + chip->max_objects=1; + chip->baudrate=1000000; + + lpc17xx_register(chip->chipspecops); + return 0; +} + +int lpc17xx_register(struct chipspecops_t *chipspecops){ + + CANMSG("initializing lpc17xx can chip operations\n"); + + chipspecops->attach_to_chip = lpc17xx_attach_to_chip; + chipspecops->pre_read_config = lpc17xx_pre_read_config; + chipspecops->chip_config = lpc17xx_chip_config; + chipspecops->pre_write_config = lpc17xx_pre_write_config; + chipspecops->send_msg = lpc17xx_send_msg; + chipspecops->wakeup_tx = lpc17xx_wakeup_tx; + chipspecops->irq_handler = lpc17xx_irq_handler; + + return 0; + +} + + +int lpc17xx_attach_to_chip(struct canchip_t *chip){ + + return 0; +} + +int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){ + + return 1; +} + + + +//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- + static void CAN_configPin(){ @@ -51,22 +321,22 @@ void CAN_send(canmsg_t* msg){ uint32_t i; // check status of TB1 - while (!(CAN1SR & (1<<2))){} + while (!(CAN1SR & CAN_SR_TBS1)){} CAN1TFI1 &= ~0x000F0000; CAN1TFI1 |= (msg->length)<<16; // EXT frame if(msg->flags & MSG_EXT) - CAN1TFI1 |= (1<<31); + CAN1TFI1 |= CAN_TFI1_EXT; else - CAN1TFI1 &= ~(1<<31); + CAN1TFI1 &= ~CAN_TFI1_EXT; // RTR frame if(msg->flags & MSG_RTR) - CAN1TFI1 |= (1<<30); + CAN1TFI1 |= CAN_TFI1_RTR; else - CAN1TFI1 &= ~(1<<30); + CAN1TFI1 &= ~CAN_TFI1_RTR; // write CAN ID CAN1TID1 = msg->id; @@ -87,7 +357,7 @@ void CAN_send(canmsg_t* msg){ CAN1TDB1 = data; // write transmission request - CAN1CMR = 0x21; + //CAN1CMR = 0x21; } @@ -166,6 +436,7 @@ void CAN_init(uint32_t baudrate) uint32_t pclksel0; uint32_t val; + printf("CAN INIT, baudrate: %d\n", baudrate); // configure CAN1 pins CAN_configPin(); @@ -195,7 +466,7 @@ void CAN_init(uint32_t baudrate) CAN1GSR = 0x3C; // request command to release Rx, Tx buffer and clear data overrun - CAN1CMR = (1<<1)|(1<<2)|(1<<3); + CAN1CMR = (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO); // read to clear interrupt pending in Interrupt Capture Register tmp = CAN1ICR; @@ -206,6 +477,11 @@ void CAN_init(uint32_t baudrate) // return to normal operating CAN1MOD = 0; + // enable interrupt after transmit + CAN1IER |= CAN_IER_TIE1; + // enable CAN interrupt + NVIC_EnableIRQ(CAN_IRQn); + }