00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00073
00074 #ifdef __GNUC__
00075
00076 #include <cfg/os.h>
00077 #include <string.h>
00078 #include <sys/event.h>
00079 #include <sys/heap.h>
00080 #include <sys/atom.h>
00081 #include <dev/irqreg.h>
00082 #include <dev/can_dev.h>
00083 #include <avr/io.h>
00084 #include <dev/atcan.h>
00085
00086
00087
00088
00089
00090
00091 #define RX_MOB 8
00092
00093 #ifndef CAN_BUF_SIZE
00094 # define CAN_BUF_SIZE 64
00095 #endif
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 #if NUT_CPU_FREQ == 12000000
00108
00109 #define CAN_BT1_10K 0x76
00110 #define CAN_BT2_10K 0x0E
00111 #define CAN_BT3_10K 0x4B
00112
00113 #define CAN_BT1_20K 0x3A
00114 #define CAN_BT2_20K 0x0E
00115 #define CAN_BT3_20K 0x4B
00116
00117 #define CAN_BT1_50K 0x26
00118 #define CAN_BT2_50K 0x08
00119 #define CAN_BT3_50K 0x25
00120
00121 #define CAN_BT1_100K 0x12
00122 #define CAN_BT2_100K 0x08
00123 #define CAN_BT3_100K 0x25
00124
00125 #define CAN_BT1_125K 0x0A
00126 #define CAN_BT2_125K 0x0C
00127 #define CAN_BT3_125K 0x37
00128
00129 #define CAN_BT1_250K 0x04
00130 #define CAN_BT2_250K 0x0C
00131 #define CAN_BT3_250K 0x37
00132
00133 #define CAN_BT1_500K 0x02
00134 #define CAN_BT2_500K 0x08
00135 #define CAN_BT3_500K 0x25
00136
00137 #define CAN_BT1_800K 0x00
00138 #define CAN_BT2_800K 0x0E
00139 #define CAN_BT3_800K 0x25
00140
00141 #define CAN_BT1_1M 0x00
00142 #define CAN_BT2_1M 0x08
00143 #define CAN_BT3_1M 0x25
00144
00145
00146
00147
00148 #elif NUT_CPU_FREQ == 16000000
00149
00150 #define CAN_BT1_10K 0x7E
00151 #define CAN_BT2_10K 0x0E
00152 #define CAN_BT3_10K 0x53
00153
00154 #define CAN_BT1_20K 0x4E
00155 #define CAN_BT2_20K 0x0E
00156 #define CAN_BT3_20K 0x4B
00157
00158 #define CAN_BT1_50K 0x26
00159 #define CAN_BT2_50K 0x0C
00160 #define CAN_BT3_50K 0x37
00161
00162 #define CAN_BT1_100K 0x12
00163 #define CAN_BT2_100K 0x0C
00164 #define CAN_BT3_100K 0x37
00165
00166 #define CAN_BT1_125K 0x0E
00167 #define CAN_BT2_125K 0x0C
00168 #define CAN_BT3_125K 0x37
00169
00170 #define CAN_BT1_250K 0x06
00171 #define CAN_BT2_250K 0x0C
00172 #define CAN_BT3_250K 0x37
00173
00174 #define CAN_BT1_500K 0x02
00175 #define CAN_BT2_500K 0x0C
00176 #define CAN_BT3_500K 0x37
00177
00178 #define CAN_BT1_800K 0x00
00179 #define CAN_BT2_800K 0x0E
00180 #define CAN_BT3_800K 0x4B
00181
00182 #define CAN_BT1_1M 0x00
00183 #define CAN_BT2_1M 0x0C
00184 #define CAN_BT3_1M 0x37
00185 #else
00186 # error Frequency not supported or not set to a Fixed MCU clock!
00187 #endif
00188
00189
00190
00191
00192
00193
00194
00195
00196 struct _CANBuffer {
00197 CANFRAME *dataptr;
00198 uint8_t size;
00199 uint8_t datalength;
00200 uint8_t dataindex;
00201 };
00202
00203 typedef struct _CANBuffer CANBuffer;
00204
00205
00206
00207
00208
00209
00210 static CANBuffer canRxBuf;
00211 CANINFO dcb_atcan;
00212 IFCAN ifc_atcan;
00213 NUTDEVICE devAtCan;
00214
00215
00216
00217
00218
00219
00229 int8_t AtCanGetBusState(void)
00230 {
00231 if (CANGSTA & _BV(BOFF))
00232 return CAN_BUS_OFF;
00233 if (CANGSTA & _BV(ERRP))
00234 return CAN_PASSIVE;
00235 return CAN_SUCCESS;
00236 }
00237
00238
00244 int8_t AtCanGetFreeMob(void)
00245 {
00246 int8_t mob;
00247 uint8_t ctrlReg;
00248
00249 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00250 {
00251 CANPAGE = mob << 4;
00252 ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
00253 if (ctrlReg == 0)
00254 return mob;
00255 if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
00256 {
00257
00258 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00259 return mob;
00260 }
00261 }
00262 return -1;
00263 }
00264
00265
00278 int8_t AtCanEnableMsgObj(uint8_t mob,
00279 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00280 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00281 {
00282 if (mob < ATCAN_MAX_MOB)
00283 {
00284
00285 CANPAGE = mob << 4;
00286
00287 CANCDMOB = 0;
00288
00289 if (idIsExt)
00290 {
00291 CANCDMOB |= _BV(IDE);
00292 CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00293 CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00294 CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00295 CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00296 CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00297 CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00298 CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00299 CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00300 }
00301 else
00302 {
00303 CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00304 CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00305 CANIDT3 = 0;
00306 CANIDT4 = 0;
00307 CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00308 CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00309 CANIDM3 = 0;
00310 CANIDM4 = 0;
00311 }
00312 if (idRemTag)
00313 CANIDT4 |= _BV(RTRTAG);
00314 if (maskIsExt)
00315 CANIDM4 |= _BV(IDEMSK);
00316 if (maskRemTag)
00317 CANIDM4 |= _BV(RTRMSK);
00318
00319 CANCDMOB |= _BV(CONMOB1);
00320 return CAN_SUCCESS;
00321 }
00322 else
00323 return CAN_ILLEGAL_MOB;
00324 }
00325
00326
00346 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00347 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00348 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00349 {
00350 int8_t i;
00351 int8_t result;
00352
00353 for (i = 0; i < noOfMsgObjs; i++)
00354 {
00355 result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00356 if (result != CAN_SUCCESS)
00357 return result;
00358 }
00359 return CAN_SUCCESS;
00360 }
00361
00362
00369 int8_t AtCanSendMsg(CANFRAME *frame)
00370 {
00371 signed char mob, j;
00372
00373 mob = AtCanGetFreeMob();
00374 if (mob < 0)
00375 return CAN_TXBUF_FULL;
00376
00377 CANPAGE = mob << 4;
00378
00379 CANCDMOB = frame->len;
00380
00381 if (frame->ext)
00382 {
00383 CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00384 CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00385 CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00386 CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00387 CANCDMOB |= _BV(IDE);
00388 }
00389 else
00390 {
00391 CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00392 CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00393 CANIDT3 = 0;
00394 CANIDT4 = 0;
00395 }
00396 if (frame->rtr)
00397 CANIDT4 |= _BV(RTRTAG);
00398 for (j = 0; j < 8; j++)
00399 CANMSG = frame->byte[j];
00400
00401 CANCDMOB |= _BV(CONMOB0);
00402
00403 return CAN_SUCCESS;
00404 }
00405
00406
00410 static void AtCanInterrupt(void *arg)
00411 {
00412 uint8_t savedCanPage;
00413 CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00414
00415 savedCanPage = CANPAGE;
00416 ci->can_interrupts++;
00417
00418
00419
00420
00421 if ((CANHPMOB & 0xF0) != 0xF0)
00422 {
00423 CANPAGE = CANHPMOB;
00424
00425 if (bit_is_set(CANSTMOB, RXOK))
00426 {
00427
00428 if (canRxBuf.datalength < canRxBuf.size)
00429 {
00430 int8_t j;
00431 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00432
00433
00434 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00435 if (bufPtr->ext)
00436 {
00437 ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00438 ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00439 ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00440 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00441 }
00442 else
00443 {
00444 ((uint8_t *) &(bufPtr->id))[3] = 0;
00445 ((uint8_t *) &(bufPtr->id))[2] = 0;
00446 ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00447 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00448 }
00449 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00450 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00451 for (j = 0; j < 8; j++)
00452 bufPtr->byte[j] = CANMSG;
00453
00454 canRxBuf.datalength++;
00455 NutEventPostFromIrq(&ci->can_rx_rdy);
00456
00457 ci->can_rx_frames++;
00458 }
00459 else
00460 {
00461
00462 ci->can_overruns++;
00463 }
00464 }
00465
00466 else if (bit_is_set(CANSTMOB, TXOK))
00467 {
00468 NutEventPostFromIrq(&ci->can_tx_rdy);
00469 ci->can_tx_frames++;
00470 }
00471
00472 else
00473 {
00474
00475 ci->can_errors++;
00476 }
00477
00478
00479
00480
00481 CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) |
00482 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00483
00484 if (bit_is_set(CANCDMOB, CONMOB1))
00485
00486 CANCDMOB |= _BV(CONMOB1);
00487 else
00488
00489 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00490
00491 }
00492 else
00493 {
00494
00495 CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00496
00497 ci->can_errors++;
00498 }
00499 CANPAGE = savedCanPage;
00500 }
00501
00502
00503
00504
00505
00506
00513 u_char AtCanRxAvail(NUTDEVICE * dev)
00514 {
00515 return canRxBuf.datalength;
00516 }
00517
00518
00525 u_char AtCanTxFree(NUTDEVICE * dev)
00526 {
00527 return (AtCanGetFreeMob() >= 0);
00528 }
00529
00530
00540 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00541 {
00542 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00543
00544 while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00545 {
00546 NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00547 };
00548 }
00549
00550
00562 u_char AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00563 {
00564 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00565
00566 while (canRxBuf.datalength == 0)
00567 {
00568 u_long timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00569
00570 if (NutEventWait(&ci->can_rx_rdy, timeout))
00571 return 1;
00572 }
00573 NutEnterCritical();
00574
00575 *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00576
00577 canRxBuf.dataindex++;
00578 if (canRxBuf.dataindex >= canRxBuf.size)
00579 canRxBuf.dataindex %= canRxBuf.size;
00580 canRxBuf.datalength--;
00581 NutExitCritical();
00582
00583 return 0;
00584 }
00585
00586
00593 void AtCanSetAccCode(NUTDEVICE * dev, u_char * ac)
00594 {
00595 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00596 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00597 }
00598
00599
00606 void AtCanSetAccMask(NUTDEVICE * dev, u_char * am)
00607 {
00608 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00609 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00610 }
00611
00612
00620 u_char AtCanSetBaudrate(NUTDEVICE * dev, u_long baudrate)
00621 {
00622 switch (baudrate)
00623 {
00624 case CAN_SPEED_10K:
00625 CANBT1 = CAN_BT1_10K;
00626 CANBT2 = CAN_BT2_10K;
00627 CANBT3 = CAN_BT3_10K;
00628 break;
00629 case CAN_SPEED_20K:
00630 CANBT1 = CAN_BT1_20K;
00631 CANBT2 = CAN_BT2_20K;
00632 CANBT3 = CAN_BT3_20K;
00633 break;
00634 case CAN_SPEED_50K:
00635 CANBT1 = CAN_BT1_50K;
00636 CANBT2 = CAN_BT2_50K;
00637 CANBT3 = CAN_BT3_50K;
00638 break;
00639 case CAN_SPEED_100K:
00640 CANBT1 = CAN_BT1_100K;
00641 CANBT2 = CAN_BT2_100K;
00642 CANBT3 = CAN_BT3_100K;
00643 break;
00644 case CAN_SPEED_125K:
00645 CANBT1 = CAN_BT1_125K;
00646 CANBT2 = CAN_BT2_125K;
00647 CANBT3 = CAN_BT3_125K;
00648 break;
00649 case CAN_SPEED_250K:
00650 CANBT1 = CAN_BT1_250K;
00651 CANBT2 = CAN_BT2_250K;
00652 CANBT3 = CAN_BT3_250K;
00653 break;
00654 case CAN_SPEED_500K:
00655 CANBT1 = CAN_BT1_500K;
00656 CANBT2 = CAN_BT2_500K;
00657 CANBT3 = CAN_BT3_500K;
00658 break;
00659 case CAN_SPEED_800K:
00660 CANBT1 = CAN_BT1_800K;
00661 CANBT2 = CAN_BT2_800K;
00662 CANBT3 = CAN_BT3_800K;
00663 break;
00664 case CAN_SPEED_1M:
00665 CANBT1 = CAN_BT1_1M;
00666 CANBT2 = CAN_BT2_1M;
00667 CANBT3 = CAN_BT3_1M;
00668 break;
00669 case CAN_SPEED_CUSTOM:
00670
00671 break;
00672 default:
00673 return 1;
00674 }
00675 ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00676 return 0;
00677 }
00678
00679
00690 int AtCanInit(NUTDEVICE * dev)
00691 {
00692 int8_t mob, i;
00693
00694 memset(dev->dev_dcb, 0, sizeof(CANINFO));
00695
00696
00697 canRxBuf.dataptr = NutHeapAlloc(CAN_BUF_SIZE * sizeof(CANFRAME));
00698 if (canRxBuf.dataptr == 0)
00699 return -1;
00700 canRxBuf.size = CAN_BUF_SIZE;
00701 canRxBuf.dataindex = 0;
00702 canRxBuf.datalength = 0;
00703
00704
00705 CANGCON &= ~_BV(ENASTB);
00706 loop_until_bit_is_clear(CANGSTA, ENFG);
00707
00708
00709 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00710 {
00711 CANPAGE = mob << 4;
00712 CANSTMOB = 0;
00713 CANCDMOB = 0;
00714 CANHPMOB = 0;
00715
00716 CANIDT1 = 0;
00717 CANIDT2 = 0;
00718 CANIDT3 = 0;
00719 CANIDT4 = 0;
00720
00721 CANIDM1 = 0;
00722 CANIDM2 = 0;
00723 CANIDM3 = 0;
00724 CANIDM4 = 0;
00725 for (i = 0; i < 8; i++)
00726 {
00727 CANMSG = 0;
00728 }
00729 }
00730
00731 AtCanSetBaudrate(dev, ifc_atcan.can_baudrate);
00732
00733 if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00734 return -1;
00735
00736 CANIE1 = 0x7F;
00737 CANIE2 = 0xFF;
00738 CANGIE = 0xFE;
00739
00740 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00741
00742
00743 CANGCON |= _BV(ENASTB);
00744 loop_until_bit_is_set(CANGSTA, ENFG);
00745
00746 return 0;
00747 }
00748
00749
00756 IFCAN ifc_atcan = {
00757 CAN_IF_2B,
00758 CAN_SPEED_125K,
00759 {0xFF, 0xFF, 0xFF, 0xFF},
00760 {0x00, 0x00, 0x00, 0x00},
00761 NUT_WAIT_INFINITE,
00762 AtCanRxAvail,
00763 AtCanTxFree,
00764 AtCanInput,
00765 AtCanOutput,
00766 AtCanSetAccCode,
00767 AtCanSetAccMask,
00768 AtCanSetBaudrate,
00769 };
00770
00771
00778 NUTDEVICE devAtCan = {
00779 0,
00780 {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0},
00781 IFTYP_CAN,
00782 0,
00783 0,
00784 &ifc_atcan,
00785 &dcb_atcan,
00786 AtCanInit,
00787 0,
00788 0,
00789 0,
00790 0,
00791 0,
00792 0,
00793 0
00794 };
00795
00796 #else
00797
00798 static void keep_icc_happy(void)
00799 {
00800 }
00801
00802 #endif
00803