1 #include "can/lpc17xx_can.h"
3 static void CAN_configPin();
4 static void CAN_setBusTiming(struct canchip_t *chip);
6 extern struct canhardware_t *hardware_p;
8 //---------------------------------------------------------------------------------
9 //---------------------------------------------------------------------------------
12 static inline void can_write_register(struct canchip_t *chip, uint32_t data, uint32_t reg_offs){
14 uint32_t address = chip->chip_base_addr + reg_offs;
15 (*(volatile uint32_t*)(address)) = data;
19 static inline uint32_t can_read_register(struct canchip_t *chip, uint32_t reg_offs){
21 uint32_t address = chip->chip_base_addr + reg_offs;
22 return (*(volatile uint32_t*)(address));
26 //---------------------------------------------------------------------------------
27 //---------------------------------------------------------------------------------
31 // for transmitting - irq when one message was transmitted (for check if another message is pending in can msg queue)
32 // for receiving - irq when message was received and is available in Receive buffer
34 void CAN_IRQHandler(){
38 struct canchip_t *chip;
39 chip = hardware_p->candevice[0]->chip[0];
41 i = can_read_register(chip, CAN_ICR_o);
43 if(i & (CAN_ICR_TI1 | CAN_ICR_RI))
44 lpc17xx_irq_handler(0, chip);
47 can_write_register(chip, CAN_CMR_CDO, CAN_CMR_o);
52 //---------------------------------------------------------------------------------
53 //---------------------------------------------------------------------------------
56 // board can-lmc1 specific functions:
58 int can_lmc1_register(struct hwspecops_t *hwspecops){
60 hwspecops->request_io = can_lmc1_request_io;
61 hwspecops->reset = can_lmc1_reset;
62 hwspecops->init_hw_data = can_lmc1_init_hw_data;
63 hwspecops->init_chip_data = can_lmc1_init_chip_data;
64 hwspecops->init_obj_data = can_lmc1_init_obj_data;
65 hwspecops->write_register = can_lmc1_write_register;
66 hwspecops->read_register = can_lmc1_read_register;
71 int can_lmc1_init_hw_data(struct candevice_t *candev){
74 candev->nr_82527_chips=0;
75 candev->nr_sja1000_chips=0;
76 candev->nr_all_chips=1;
82 int can_lmc1_init_chip_data(struct candevice_t *candev, int chipnr){
84 lpc17xx_fill_chipspecops(candev->chip[chipnr]);
86 candev->chip[chipnr]->flags|= CHIP_IRQ_CUSTOM;
89 candev->chip[chipnr]->chip_base_addr = CAN1_REGS_BASE;
91 candev->chip[chipnr]->chip_data=(void *)malloc(sizeof(struct can_lmc1_chip_data));
92 if (candev->chip[chipnr]->chip_data==NULL)
98 int can_lmc1_init_obj_data(struct canchip_t *chip, int objnr){
103 void can_lmc1_write_register(unsigned data, unsigned long address){
104 (*(volatile uint32_t*)(address)) = data;
107 unsigned can_lmc1_read_register(unsigned long address){
108 return (*(volatile uint32_t*)(address));
111 int can_lmc1_request_io(struct candevice_t *candev)
116 int can_lmc1_reset(struct candevice_t *candev)
122 //---------------------------------------------------------------------------------
123 //---------------------------------------------------------------------------------
126 // lpc17xx can chip specific functions:
129 int lpc17xx_chip_config(struct canchip_t *chip){
136 int lpc17xx_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
137 struct canmsg_t *msg)
145 int lpc17xx_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
146 struct canmsg_t *msg)
149 // write transmission request
150 can_write_register(chip, (CAN_CMR_TR | CAN_CMR_STB1), CAN_CMR_o);
155 int lpc17xx_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
158 can_preempt_disable();
160 can_msgobj_set_fl(obj,TX_PENDING);
161 can_msgobj_set_fl(obj,TX_REQUEST);
163 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
164 can_msgobj_clear_fl(obj,TX_REQUEST);
166 if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
168 lpc17xx_irq_write_handler(chip, obj);
171 can_msgobj_clear_fl(obj,TX_LOCK);
172 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
176 can_preempt_enable();
181 int lpc17xx_irq_handler(int irq, struct canchip_t *chip)
184 struct msgobj_t *obj;
185 obj = chip->msgobj[0];
187 if(can_read_register(chip, CAN_SR_o) & CAN_SR_RBS) {
188 lpc17xx_read(chip,obj);
193 if ((can_msgobj_test_fl(obj,TX_PENDING)) || (can_msgobj_test_fl(obj,TX_REQUEST))) {
195 can_msgobj_set_fl(obj,TX_REQUEST);
197 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
200 can_msgobj_clear_fl(obj,TX_REQUEST);
202 if (can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1){
204 lpc17xx_irq_write_handler(chip, obj);
207 can_msgobj_clear_fl(obj,TX_LOCK);
208 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
214 return CANCHIP_IRQ_HANDLED;
218 void lpc17xx_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
223 /* Do local transmitted message distribution if enabled */
225 /* fill CAN message timestamp */
226 can_filltimestamp(&obj->tx_slot->msg.timestamp);
228 obj->tx_slot->msg.flags |= MSG_LOCAL;
229 canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
231 /* Free transmitted slot */
232 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
236 can_msgobj_clear_fl(obj,TX_PENDING);
237 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
240 can_msgobj_set_fl(obj,TX_PENDING);
242 if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
244 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
245 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
249 if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
251 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
252 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
259 void lpc17xx_read(struct canchip_t *chip, struct msgobj_t *obj) {
262 CAN_recv(chip, &obj->rx_msg);
264 // fill CAN message timestamp
265 can_filltimestamp(&obj->rx_msg.timestamp);
267 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
269 // release Receive buffer
270 can_write_register(chip, CAN_CMR_RRB, CAN_CMR_o);
274 int lpc17xx_fill_chipspecops(struct canchip_t *chip){
278 lpc17xx_register(chip->chipspecops);
283 int lpc17xx_register(struct chipspecops_t *chipspecops){
285 CANMSG("initializing lpc17xx can chip operations\n");
287 chipspecops->attach_to_chip = lpc17xx_attach_to_chip;
288 chipspecops->pre_read_config = lpc17xx_pre_read_config;
289 chipspecops->chip_config = lpc17xx_chip_config;
290 chipspecops->pre_write_config = lpc17xx_pre_write_config;
291 chipspecops->send_msg = lpc17xx_send_msg;
292 chipspecops->wakeup_tx = lpc17xx_wakeup_tx;
293 chipspecops->irq_handler = lpc17xx_irq_handler;
300 int lpc17xx_attach_to_chip(struct canchip_t *chip){
305 int lpc17xx_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj){
312 //---------------------------------------------------------------------------------
313 //---------------------------------------------------------------------------------
316 static void CAN_configPin(){
318 // CAN1 - select P0.0 as RD1. P0.1 as TD1
322 uint32_t pinmode_od0;
323 uint8_t pinsel0_val = 1;
324 uint8_t pinmode0_val = 0;
325 uint8_t pinmode_od0_val = 0;
328 pinsel0 = PINCON->PINSEL0;
329 pinsel0 &= ~CAN1_RX_MASK;
330 pinsel0 &= ~CAN1_TX_MASK;
331 pinsel0 |= __val2mfld(CAN1_RX_MASK, pinsel0_val);
332 pinsel0 |= __val2mfld(CAN1_TX_MASK, pinsel0_val);
333 PINCON->PINSEL0 = pinsel0;
335 pinmode0 = PINCON->PINMODE0;
336 pinmode0 &= ~CAN1_RX_MASK;
337 pinmode0 &= ~CAN1_TX_MASK;
338 pinmode0 |= __val2mfld(CAN1_RX_MASK, pinmode0_val);
339 pinmode0 |= __val2mfld(CAN1_TX_MASK, pinmode0_val);
340 PINCON->PINMODE0 = pinmode0;
342 pinmode_od0 = PINCON->PINMODE_OD0;
343 if (pinmode_od0_val){
344 pinmode_od0 |= CAN1_RX_BIT;
345 pinmode_od0 |= CAN1_TX_BIT;
348 pinmode_od0 &= ~CAN1_RX_BIT;
349 pinmode_od0 &= ~CAN1_TX_BIT;
351 PINCON->PINMODE_OD0 = pinmode_od0;
356 void CAN_recv(struct canchip_t *chip, canmsg_t* msg){
358 volatile uint32_t data;
362 msg->length = (can_read_register(chip, CAN_RFS_o)>>16) & 0xF;
365 msg->id = can_read_register(chip, CAN_RID_o);
368 if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_EXT)
369 msg->flags |= MSG_EXT;
371 msg->flags &= ~MSG_EXT;
375 if(can_read_register(chip, CAN_RFS_o) & CAN_RFS_RTR)
376 msg->flags |= MSG_RTR;
378 msg->flags &= ~MSG_RTR;
382 data = can_read_register(chip, CAN_RDA_o);
384 msg->data[i] = (data>>(i*8)) & 0xFF;
386 data = can_read_register(chip, CAN_RDB_o);
388 msg->data[i] = (data>>((i-4)*8)) & 0xFF;
392 void CAN_send(struct canchip_t *chip, canmsg_t* msg){
394 volatile uint32_t data;
395 volatile uint32_t can_tfi1;
398 // check status of TB1
399 while (!(can_read_register(chip, CAN_SR_o) & CAN_SR_TBS1)){}
401 can_tfi1 = can_read_register(chip, CAN_TFI1_o);
403 can_tfi1 &= ~0x000F0000;
404 can_tfi1 |= (msg->length)<<16;
407 if(msg->flags & MSG_EXT)
408 can_tfi1 |= CAN_TFI1_EXT;
410 can_tfi1 &= ~CAN_TFI1_EXT;
413 if(msg->flags & MSG_RTR)
414 can_tfi1 |= CAN_TFI1_RTR;
416 can_tfi1 &= ~CAN_TFI1_RTR;
418 can_write_register(chip, can_tfi1, CAN_TFI1_o);
422 can_write_register(chip, msg->id, CAN_TID1_o);
425 // write first 4 data bytes
428 data |= (msg->data[i])<<(i*8);
430 can_write_register(chip, data, CAN_TDA1_o);
432 // write second 4 data bytes
435 data |= (msg->data[i])<<((i-4)*8);
437 can_write_register(chip, data, CAN_TDB1_o);
441 void CAN_setBusTiming(struct canchip_t *chip){
446 uint8_t tq_numb; // number of time quantum
447 uint8_t TSEG1, TSEG2;
453 // 0 = the bus is sampled once
456 // the Synchronization Jump Width (this value plus one)
459 // get clock divide for CAN1
460 div = __mfld2val(PCLK_CAN1_MASK, SC->PCLKSEL0);
472 // only for CAN, for other peripherials '11' value means div=8
478 PCLK_CAN = system_frequency / div;
480 res = PCLK_CAN / (chip->baudrate);
483 // calculation of tq_numb - number of time quantum (must be in <8,25>)
484 // tq_numb = TSEG1 + TSEG2 + 3
486 for(tq_numb=25; tq_numb>=8; tq_numb--){
488 if ((res%tq_numb)==0){
490 // Baud Rate Prescaler. The PCLK clock is divided by (this value plus one) to produce the CAN clock.
491 BRP = (res / tq_numb) - 1;
493 // sync. segment allways 1 tq
496 // number of tq from the sample point to the next nominal Sync. point (this value plus one)
497 TSEG2 = (tq_numb/3) - 1;
499 // number of tq from Sync. point to the sample point (this value plus one)
500 TSEG1 = tq_numb - (tq_numb/3) - 1;
506 can_write_register(chip, ((SAM<<23)|(TSEG2<<20)|(TSEG1<<16)|(SJW<<14)|(BRP<<0)), CAN_BTR_o);
510 void CAN_init(struct canchip_t *chip){
517 printf("CAN INIT, baudrate: %d\n", chip->baudrate);
519 // configure CAN1 pins
522 // turn on power and clock for CAN1
525 // set clock divide for CAN1
527 val = 0x00; // 00 PCLK_peripheral = CCLK/4
528 pclksel0 = SC->PCLKSEL0;
529 pclksel0 &= ~PCLK_CAN1_MASK;
530 pclksel0 &= ~PCLK_CAN2_MASK;
531 pclksel0 &= ~PCLK_ACF_MASK;
532 pclksel0 |= __val2mfld(PCLK_CAN1_MASK, val);
533 pclksel0 |= __val2mfld(PCLK_CAN2_MASK, val);
534 pclksel0 |= __val2mfld(PCLK_ACF_MASK, val);
535 SC->PCLKSEL0 = pclksel0;
538 can_write_register(chip, 1, CAN_MOD_o);
540 // disable all CAN interrupts
541 can_write_register(chip, 0, CAN_IER_o);
543 // reset value of Global Status Register (global controller status and error counters)
544 can_write_register(chip, 0x3C, CAN_GSR_o);
546 // request command to release Rx, Tx buffer and clear data overrun
547 can_write_register(chip, (CAN_CMR_AT | CAN_CMR_RRB | CAN_CMR_CDO), CAN_CMR_o);
549 // read to clear interrupt pending in Interrupt Capture Register
550 tmp = can_read_register(chip, CAN_ICR_o);
553 CAN_setBusTiming(chip);
555 // return to normal operating
556 can_write_register(chip, 0, CAN_MOD_o);
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;
575 // Acceptance Filter Bypass Mode - all messages accepted
578 //--------------------------
581 // enable interrupt after transmit
582 // enable receive interrupt
583 // enable data overrun interrupt
584 can_write_register(chip, (CAN_IER_TIE1 | CAN_IER_RIE | CAN_IER_DOIE), CAN_IER_o);
586 // enable CAN interrupt
587 NVIC_EnableIRQ(CAN_IRQn);