1 #include "can/lpc17xx_can.h"
3 static void CAN_configPin();
4 static void CAN_setBusTiming(uint32_t baudrate);
6 extern struct canhardware_t *hardware_p;
8 extern volatile uint32_t cnt;
9 //---------------------------------------------------------------------------------
10 //---------------------------------------------------------------------------------
13 // for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
14 // for receiving - irq when message was received and is available in Receive buffer
16 void CAN_IRQHandler(){
23 if(i & (CAN_ICR_TI1 | CAN_ICR_RI)){
25 struct canchip_t *chip;
26 chip = hardware_p->candevice[0]->chip[0];
28 lpc17xx_irq_handler(0, chip);
32 printf("Data overrun\n");
33 CAN1CMR = CAN_CMR_CDO;
40 //---------------------------------------------------------------------------------
41 //---------------------------------------------------------------------------------
44 // board can-lmc1 specific functions:
46 int can_lmc1_register(struct hwspecops_t *hwspecops){
48 hwspecops->request_io = can_lmc1_request_io;
49 hwspecops->reset = can_lmc1_reset;
50 hwspecops->init_hw_data = can_lmc1_init_hw_data;
51 hwspecops->init_chip_data = can_lmc1_init_chip_data;
52 hwspecops->init_obj_data = can_lmc1_init_obj_data;
53 hwspecops->write_register = can_lmc1_write_register;
54 hwspecops->read_register = can_lmc1_read_register;
59 int can_lmc1_init_hw_data(struct candevice_t *candev){
62 candev->nr_82527_chips=0;
63 candev->nr_sja1000_chips=0;
64 candev->nr_all_chips=1;
70 int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
72 lpc17xx_fill_chipspecops(candev->chip[chipnr]);
74 candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
76 candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
77 if (candev->chip[chipnr]->chip_data==NULL)
83 int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){
85 //chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
90 void can_lmc1_write_register(unsigned data, unsigned long address){
92 printf("UNSUPPORTED NOW\n");
96 unsigned can_lmc1_read_register(unsigned long address){
98 printf("UNSUPPORTED NOW\n");
102 int can_lmc1_request_io(struct candevice_t *candev)
107 int can_lmc1_reset(struct candevice_t *candev)
113 //---------------------------------------------------------------------------------
114 //---------------------------------------------------------------------------------
117 // lpc17xx can chip specific functions:
120 int lpc17xx_chip_config(struct canchip_t *chip){
122 CAN_init( (uint32_t) chip->baudrate);
127 int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
128 struct canmsg_t *msg)
136 int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
137 struct canmsg_t *msg)
140 // write transmission request
141 CAN1CMR = (CAN_CMR_TR | CAN_CMR_STB1);
146 int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
149 can_preempt_disable();
151 can_msgobj_set_fl(obj,TX_PENDING);
152 can_msgobj_set_fl(obj,TX_REQUEST);
154 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
155 can_msgobj_clear_fl(obj,TX_REQUEST);
158 if (CAN1SR & CAN_SR_TBS1){
160 lpc17xx_irq_write_handler(chip, obj);
163 can_msgobj_clear_fl(obj,TX_LOCK);
164 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
168 can_preempt_enable();
173 int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
176 struct msgobj_t *obj;
177 obj = chip->msgobj[0];
180 if(CAN1SR & CAN_SR_RBS) {
181 lpc17xx_read(chip,obj);
186 if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
188 can_msgobj_set_fl(obj,TX_REQUEST);
190 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
193 can_msgobj_clear_fl(obj,TX_REQUEST);
195 if (CAN1SR & CAN_SR_TBS1){
197 lpc17xx_irq_write_handler(chip, obj);
200 can_msgobj_clear_fl(obj,TX_LOCK);
201 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
207 return CANCHIP_IRQ_HANDLED;
211 void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
216 /* Do local transmitted message distribution if enabled */
218 /* fill CAN message timestamp */
219 can_filltimestamp(&obj->tx_slot->msg.timestamp);
221 obj->tx_slot->msg.flags |= MSG_LOCAL;
222 canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
224 /* Free transmitted slot */
225 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
229 can_msgobj_clear_fl(obj,TX_PENDING);
230 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
233 can_msgobj_set_fl(obj,TX_PENDING);
235 if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
237 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
238 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
242 if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
244 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
245 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
252 void lpc17xx_read(struct canchip_t *chip, struct msgobj_t *obj) {
255 CAN_recv(&obj->rx_msg);
257 // fill CAN message timestamp
258 can_filltimestamp(&obj->rx_msg.timestamp);
260 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
262 // release Receive buffer
263 CAN1CMR = CAN_CMR_RRB;
267 int lpc17xx_fill_chipspecops(struct canchip_t *chip){
270 chip->baudrate=1000000;
272 lpc17xx_register(chip->chipspecops);
276 int lpc17xx_register(struct chipspecops_t *chipspecops){
278 CANMSG("initializing lpc17xx can chip operations\n");
280 chipspecops->attach_to_chip = lpc17xx_attach_to_chip;
281 chipspecops->pre_read_config = lpc17xx_pre_read_config;
282 chipspecops->chip_config = lpc17xx_chip_config;
283 chipspecops->pre_write_config = lpc17xx_pre_write_config;
284 chipspecops->send_msg = lpc17xx_send_msg;
285 chipspecops->wakeup_tx = lpc17xx_wakeup_tx;
286 chipspecops->irq_handler = lpc17xx_irq_handler;
293 int lpc17xx_attach_to_chip(struct canchip_t *chip){
298 int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){
305 //---------------------------------------------------------------------------------
306 //---------------------------------------------------------------------------------
309 static void CAN_configPin(){
311 // CAN1 - select P0.0 as RD1. P0.1 as TD1
315 uint32_t pinmode_od0;
316 uint8_t pinsel0_val = 1;
317 uint8_t pinmode0_val = 0;
318 uint8_t pinmode_od0_val = 0;
322 pinsel0 &= ~CAN1_RX_MASK;
323 pinsel0 &= ~CAN1_TX_MASK;
324 pinsel0 |= __val2mfld(CAN1_RX_MASK, pinsel0_val);
325 pinsel0 |= __val2mfld(CAN1_TX_MASK, pinsel0_val);
329 pinmode0 &= ~CAN1_RX_MASK;
330 pinmode0 &= ~CAN1_TX_MASK;
331 pinmode0 |= __val2mfld(CAN1_RX_MASK, pinmode0_val);
332 pinmode0 |= __val2mfld(CAN1_TX_MASK, pinmode0_val);
335 pinmode_od0 = PINMODE_OD0;
336 if (pinmode_od0_val){
337 pinmode_od0 |= CAN1_RX_BIT;
338 pinmode_od0 |= CAN1_TX_BIT;
341 pinmode_od0 &= ~CAN1_RX_BIT;
342 pinmode_od0 &= ~CAN1_TX_BIT;
344 PINMODE_OD0 = pinmode_od0;
349 void CAN_recv(canmsg_t* msg){
366 msg->length = ((CAN1RFS)>>16) & 0xF;
372 if(CAN1RFS & CAN_RFS_EXT)
373 msg->flags |= MSG_EXT;
375 msg->flags &= ~MSG_EXT;
379 if(CAN1RFS & CAN_RFS_RTR)
380 msg->flags |= MSG_RTR;
382 msg->flags &= ~MSG_RTR;
388 msg->data[i] = (data>>(i*8)) & 0xFF;
392 msg->data[i] = (data>>((i-4)*8)) & 0xFF;
396 void CAN_send(canmsg_t* msg){
401 // check status of TB1
402 while (!(CAN1SR & CAN_SR_TBS1)){}
404 CAN1TFI1 &= ~0x000F0000;
405 CAN1TFI1 |= (msg->length)<<16;
408 if(msg->flags & MSG_EXT)
409 CAN1TFI1 |= CAN_TFI1_EXT;
411 CAN1TFI1 &= ~CAN_TFI1_EXT;
414 if(msg->flags & MSG_RTR)
415 CAN1TFI1 |= CAN_TFI1_RTR;
417 CAN1TFI1 &= ~CAN_TFI1_RTR;
422 // write first 4 data bytes
426 data |= (msg->data[i])<<(i*8);
430 // write second 4 data bytes
434 data |= (msg->data[i])<<((i-4)*8);
437 // write transmission request
442 void CAN_setBusTiming(uint32_t baudrate){
447 uint8_t tq_numb; // number of time quantum
448 uint8_t TSEG1, TSEG2;
454 // 0 = the bus is sampled once
457 // the Synchronization Jump Width (this value plus one)
460 // get clock divide for CAN1
461 div = __mfld2val(PCLK_CAN1_MASK, PCLKSEL0);
473 // only for CAN, for other peripherials '11' value means div=8
479 PCLK_CAN = system_frequency / div;
481 res = PCLK_CAN / baudrate;
484 // calculation of tq_numb - number of time quantum (must be in <8,25>)
485 // tq_numb = TSEG1 + TSEG2 + 3
487 for(tq_numb=25; tq_numb>=8; tq_numb--){
489 if ((res%tq_numb)==0){
491 // Baud Rate Prescaler. The PCLK clock is divided by (this value plus one) to produce the CAN clock.
492 BRP = (res / tq_numb) - 1;
494 // sync. segment allways 1 tq
497 // number of tq from the sample point to the next nominal Sync. point (this value plus one)
498 TSEG2 = (tq_numb/3) - 1;
500 // number of tq from Sync. point to the sample point (this value plus one)
501 TSEG1 = tq_numb - (tq_numb/3) - 1;
507 CAN1BTR = ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0));
511 void CAN_init(uint32_t baudrate)
518 printf("CAN INIT, baudrate: %d\n", baudrate);
520 // configure CAN1 pins
523 // turn on power and clock for CAN1
526 // set clock divide for CAN1
528 val = 0x00; // 00 PCLK_peripheral = CCLK/4
530 pclksel0 &= ~PCLK_CAN1_MASK;
531 pclksel0 &= ~PCLK_CAN2_MASK;
532 pclksel0 &= ~PCLK_ACF_MASK;
533 pclksel0 |= __val2mfld(PCLK_CAN1_MASK, val);
534 pclksel0 |= __val2mfld(PCLK_CAN2_MASK, val);
535 pclksel0 |= __val2mfld(PCLK_ACF_MASK, val);
541 // disable all CAN interrupts
544 // reset value of Global Status Register (global controller status and error counters)
547 // request command to release Rx, Tx buffer and clear data overrun
548 CAN1CMR = (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO);
550 // read to clear interrupt pending in Interrupt Capture Register
554 CAN_setBusTiming(baudrate);
556 // return to normal operating
559 //--------------------------
561 // Acceptance Filter Off Mode
565 for (i = 0; i < 512; i++) {
566 CANAF_RAM->mask[i] = 0x00;
570 CANAF_SFF_GRP_sa = 0x00;
572 CANAF_EFF_GRP_sa = 0x00;
573 CANAF_ENDofTable = 0x00;
576 // Acceptance Filter Bypass Mode - all messages accepted
579 //--------------------------
581 // enable interrupt after transmit
582 CAN1IER |= CAN_IER_TIE1;
583 // enable receive interrupt
584 CAN1IER |= CAN_IER_RIE;
585 // enable data overrun interrupt
586 CAN1IER |= CAN_IER_DOIE;
588 // enable CAN interrupt
589 NVIC_EnableIRQ(CAN_IRQn);