X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/45b3ad9101e4e75af54e2d3bc25be419d3df7224..a9296605ae899d82c9e8f682eafe63d999c4a57b:/embedded/app/usbcan/lpc17xx_can.c diff --git a/embedded/app/usbcan/lpc17xx_can.c b/embedded/app/usbcan/lpc17xx_can.c index 5565d8c..8b3a773 100644 --- a/embedded/app/usbcan/lpc17xx_can.c +++ b/embedded/app/usbcan/lpc17xx_can.c @@ -3,52 +3,6 @@ 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); - - -} - //--------------------------------------------------------------------------------- //--------------------------------------------------------------------------------- @@ -64,6 +18,7 @@ int can_lmc1_register(struct hwspecops_t *hwspecops){ 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; } @@ -74,20 +29,18 @@ int can_lmc1_init_hw_data(struct candevice_t *candev){ 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; @@ -101,15 +54,11 @@ int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){ } void can_lmc1_write_register(unsigned data, unsigned long address){ - - printf("UNSUPPORTED NOW\n"); + (*(volatile uint32_t*)(address)) = data; } unsigned can_lmc1_read_register(unsigned long address){ - - printf("UNSUPPORTED NOW\n"); - return 0; - + return (*(volatile uint32_t*)(address)); } int can_lmc1_request_io(struct candevice_t *candev) @@ -122,6 +71,10 @@ int can_lmc1_reset(struct candevice_t *candev) return 0; } +int can_lmc1_program_irq(struct candevice_t *candev) +{ + return 0; +} //--------------------------------------------------------------------------------- //--------------------------------------------------------------------------------- @@ -151,7 +104,7 @@ int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj, { // 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); return 0; } @@ -167,7 +120,7 @@ int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) 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); } @@ -185,34 +138,44 @@ int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *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_reg(chip, CAN_SR_o) & CAN_SR_TBS1){ + obj->tx_retry_cnt=0; + lpc17xx_irq_write_handler(chip, obj); + } - if (can_read_register(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; @@ -271,13 +234,14 @@ void lpc17xx_read(struct canchip_t *chip, struct msgobj_t *obj) { 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); @@ -363,31 +327,31 @@ void CAN_recv(struct canchip_t *chip, canmsg_t* msg){ 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; @@ -400,9 +364,9 @@ void CAN_send(struct canchip_t *chip, canmsg_t* msg){ uint32_t i; // 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)){} - 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; @@ -419,11 +383,11 @@ void CAN_send(struct canchip_t *chip, canmsg_t* msg){ 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 @@ -431,14 +395,14 @@ void CAN_send(struct canchip_t *chip, canmsg_t* msg){ 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); } @@ -454,6 +418,8 @@ 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; @@ -507,7 +473,7 @@ void CAN_setBusTiming(struct canchip_t *chip){ } } - 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); } @@ -518,7 +484,7 @@ void CAN_init(struct canchip_t *chip){ 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(); @@ -539,25 +505,25 @@ void CAN_init(struct canchip_t *chip){ 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); //-------------------------- @@ -585,12 +551,8 @@ void CAN_init(struct canchip_t *chip){ // 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); - - }