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
00069
00070
00071
00076
00077 #ifdef __GNUC__
00078
00079 #include <cfg/os.h>
00080 #include <string.h>
00081 #include <sys/event.h>
00082 #include <sys/heap.h>
00083 #include <sys/atom.h>
00084 #include <dev/irqreg.h>
00085 #include <dev/can_dev.h>
00086 #include <avr/io.h>
00087 #include <dev/atcan.h>
00088
00089
00090
00091
00092
00093
00094 #define RX_MOB 8
00095
00096 #ifndef CAN_BUF_SIZE
00097 # define CAN_BUF_SIZE 64
00098 #endif
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #if NUT_CPU_FREQ == 12000000
00113
00114 #define CAN_BT1_10K 0x76
00115 #define CAN_BT2_10K 0x2E
00116 #define CAN_BT3_10K 0x2E
00117
00118 #define CAN_BT1_20K 0x4E
00119 #define CAN_BT2_20K 0x2E
00120 #define CAN_BT3_20K 0x16
00121
00122 #define CAN_BT1_50K 0x1C
00123 #define CAN_BT2_50K 0x2E
00124 #define CAN_BT3_50K 0x18
00125
00126 #define CAN_BT1_100K 0x0E
00127 #define CAN_BT2_100K 0x2E
00128 #define CAN_BT3_100K 0x16
00129
00130 #define CAN_BT1_125K 0x0A
00131 #define CAN_BT2_125K 0x2E
00132 #define CAN_BT3_125K 0x18
00133
00134 #define CAN_BT1_250K 0x04
00135 #define CAN_BT2_250K 0x2E
00136 #define CAN_BT3_250K 0x18
00137
00138 #define CAN_BT1_500K 0x02
00139 #define CAN_BT2_500K 0x2C
00140 #define CAN_BT3_500K 0x12
00141
00142 #define CAN_BT1_800K 0x00
00143 #define CAN_BT2_800K 0x2E
00144 #define CAN_BT3_800K 0x16
00145
00146 #define CAN_BT1_1M 0x00
00147 #define CAN_BT2_1M 0x2C
00148 #define CAN_BT3_1M 0x12
00149
00150
00151
00152
00153 #elif NUT_CPU_FREQ == 16000000
00154
00155 #define CAN_BT1_10K 0x7E
00156 #define CAN_BT2_10K 0x2E
00157 #define CAN_BT3_10K 0x7E
00158
00159 #define CAN_BT1_20K 0x62
00160 #define CAN_BT2_20K 0x2E
00161 #define CAN_BT3_20K 0x18
00162
00163 #define CAN_BT1_50K 0x26
00164 #define CAN_BT2_50K 0x2E
00165 #define CAN_BT3_50K 0x18
00166
00167 #define CAN_BT1_100K 0x12
00168 #define CAN_BT2_100K 0x2E
00169 #define CAN_BT3_100K 0x18
00170
00171 #define CAN_BT1_125K 0x0E
00172 #define CAN_BT2_125K 0x2E
00173 #define CAN_BT3_125K 0x18
00174
00175 #define CAN_BT1_250K 0x06
00176 #define CAN_BT2_250K 0x2E
00177 #define CAN_BT3_250K 0x18
00178
00179 #define CAN_BT1_500K 0x02
00180 #define CAN_BT2_500K 0x2E
00181 #define CAN_BT3_500K 0x18
00182
00183 #define CAN_BT1_800K 0x00
00184 #define CAN_BT2_800K 0x2E
00185 #define CAN_BT3_800K 0x2E
00186
00187 #define CAN_BT1_1M 0x00
00188 #define CAN_BT2_1M 0x2E
00189 #define CAN_BT3_1M 0x18
00190 #else
00191 # error Frequency not supported or not set to a Fixed MCU clock!
00192 #endif
00193
00194
00195
00196
00197
00198
00199
00200
00201 struct _CANBuffer {
00202 CANFRAME *dataptr;
00203 uint8_t size;
00204 uint8_t datalength;
00205 uint8_t dataindex;
00206 };
00207
00208 typedef struct _CANBuffer CANBuffer;
00209
00210
00211
00212
00213
00214
00215 static CANBuffer canRxBuf;
00216 CANINFO dcb_atcan;
00217 IFCAN ifc_atcan;
00218 NUTDEVICE devAtCan;
00219
00220
00221
00222
00223
00224
00234 int8_t AtCanGetBusState(void)
00235 {
00236 if (CANGSTA & _BV(BOFF))
00237 return CAN_BUS_OFF;
00238 if (CANGSTA & _BV(ERRP))
00239 return CAN_PASSIVE;
00240 return CAN_SUCCESS;
00241 }
00242
00243
00249 int8_t AtCanGetFreeMob(void)
00250 {
00251 int8_t mob;
00252 uint8_t ctrlReg;
00253
00254 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00255 {
00256 CANPAGE = mob << 4;
00257 ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
00258 if (ctrlReg == 0)
00259 return mob;
00260 if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
00261 {
00262
00263 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00264 return mob;
00265 }
00266 }
00267 return -1;
00268 }
00269
00270
00283 int8_t AtCanEnableMsgObj(uint8_t mob,
00284 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00285 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00286 {
00287 if (mob < ATCAN_MAX_MOB)
00288 {
00289
00290 CANPAGE = mob << 4;
00291
00292 CANCDMOB = 0;
00293
00294 if (idIsExt)
00295 {
00296 CANCDMOB |= _BV(IDE);
00297 CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00298 CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00299 CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00300 CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00301 CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00302 CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00303 CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00304 CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00305 }
00306 else
00307 {
00308 CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00309 CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00310 CANIDT3 = 0;
00311 CANIDT4 = 0;
00312 CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00313 CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00314 CANIDM3 = 0;
00315 CANIDM4 = 0;
00316 }
00317 if (idRemTag)
00318 CANIDT4 |= _BV(RTRTAG);
00319 if (maskIsExt)
00320 CANIDM4 |= _BV(IDEMSK);
00321 if (maskRemTag)
00322 CANIDM4 |= _BV(RTRMSK);
00323
00324 CANCDMOB |= _BV(CONMOB1);
00325 return CAN_SUCCESS;
00326 }
00327 else
00328 return CAN_ILLEGAL_MOB;
00329 }
00330
00331
00351 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00352 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00353 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00354 {
00355 int8_t i;
00356 int8_t result;
00357
00358 for (i = 0; i < noOfMsgObjs; i++)
00359 {
00360 result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00361 if (result != CAN_SUCCESS)
00362 return result;
00363 }
00364 return CAN_SUCCESS;
00365 }
00366
00367
00374 int8_t AtCanSendMsg(CANFRAME *frame)
00375 {
00376 signed char mob, j;
00377
00378 mob = AtCanGetFreeMob();
00379 if (mob < 0)
00380 return CAN_TXBUF_FULL;
00381
00382 CANPAGE = mob << 4;
00383
00384 CANCDMOB = frame->len;
00385
00386 if (frame->ext)
00387 {
00388 CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00389 CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00390 CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00391 CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00392 CANCDMOB |= _BV(IDE);
00393 }
00394 else
00395 {
00396 CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00397 CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00398 CANIDT3 = 0;
00399 CANIDT4 = 0;
00400 }
00401 if (frame->rtr)
00402 CANIDT4 |= _BV(RTRTAG);
00403 for (j = 0; j < 8; j++)
00404 CANMSG = frame->byte[j];
00405
00406 CANCDMOB |= _BV(CONMOB0);
00407
00408 return CAN_SUCCESS;
00409 }
00410
00411
00415 static void AtCanInterrupt(void *arg)
00416 {
00417 uint8_t savedCanPage;
00418 CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00419
00420 savedCanPage = CANPAGE;
00421 ci->can_interrupts++;
00422
00423
00424
00425
00426 if ((CANHPMOB & 0xF0) != 0xF0)
00427 {
00428 CANPAGE = CANHPMOB;
00429
00430 if (bit_is_set(CANSTMOB, RXOK))
00431 {
00432
00433 if (canRxBuf.datalength < canRxBuf.size)
00434 {
00435 int8_t j;
00436 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00437
00438
00439 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00440 if (bufPtr->ext)
00441 {
00442 ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00443 ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00444 ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00445 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00446 }
00447 else
00448 {
00449 ((uint8_t *) &(bufPtr->id))[3] = 0;
00450 ((uint8_t *) &(bufPtr->id))[2] = 0;
00451 ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00452 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00453 }
00454 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00455 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00456 for (j = 0; j < 8; j++)
00457 bufPtr->byte[j] = CANMSG;
00458
00459 canRxBuf.datalength++;
00460 NutEventPostFromIrq(&ci->can_rx_rdy);
00461
00462 ci->can_rx_frames++;
00463 }
00464 else
00465 {
00466
00467 ci->can_overruns++;
00468 }
00469 }
00470
00471 else if (bit_is_set(CANSTMOB, TXOK))
00472 {
00473 NutEventPostFromIrq(&ci->can_tx_rdy);
00474 ci->can_tx_frames++;
00475 }
00476
00477 else
00478 {
00479
00480 ci->can_errors++;
00481 }
00482
00483
00484
00485
00486 CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) |
00487 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00488
00489 if (bit_is_set(CANCDMOB, CONMOB1))
00490
00491 CANCDMOB |= _BV(CONMOB1);
00492 else
00493
00494 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00495
00496 }
00497 else
00498 {
00499
00500 CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00501
00502 ci->can_errors++;
00503 }
00504 CANPAGE = savedCanPage;
00505 }
00506
00507
00508
00509
00510
00511
00518 u_char AtCanRxAvail(NUTDEVICE * dev)
00519 {
00520 return canRxBuf.datalength;
00521 }
00522
00523
00530 u_char AtCanTxFree(NUTDEVICE * dev)
00531 {
00532 return (AtCanGetFreeMob() >= 0);
00533 }
00534
00535
00545 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00546 {
00547 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00548
00549 while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00550 {
00551 NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00552 };
00553 }
00554
00555
00567 u_char AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00568 {
00569 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00570
00571 while (canRxBuf.datalength == 0)
00572 {
00573 u_long timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00574
00575 if (NutEventWait(&ci->can_rx_rdy, timeout))
00576 return 1;
00577 }
00578 NutEnterCritical();
00579
00580 *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00581
00582 canRxBuf.dataindex++;
00583 if (canRxBuf.dataindex >= canRxBuf.size)
00584 canRxBuf.dataindex %= canRxBuf.size;
00585 canRxBuf.datalength--;
00586 NutExitCritical();
00587
00588 return 0;
00589 }
00590
00591
00598 void AtCanSetAccCode(NUTDEVICE * dev, u_char * ac)
00599 {
00600 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00601 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00602 }
00603
00604
00611 void AtCanSetAccMask(NUTDEVICE * dev, u_char * am)
00612 {
00613 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00614 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00615 }
00616
00617
00625 u_char AtCanSetBaudrate(NUTDEVICE * dev, u_long baudrate)
00626 {
00627 switch (baudrate)
00628 {
00629 case CAN_SPEED_10K:
00630 CANBT1 = CAN_BT1_10K;
00631 CANBT2 = CAN_BT2_10K;
00632 CANBT3 = CAN_BT3_10K;
00633 break;
00634 case CAN_SPEED_20K:
00635 CANBT1 = CAN_BT1_20K;
00636 CANBT2 = CAN_BT2_20K;
00637 CANBT3 = CAN_BT3_20K;
00638 break;
00639 case CAN_SPEED_50K:
00640 CANBT1 = CAN_BT1_50K;
00641 CANBT2 = CAN_BT2_50K;
00642 CANBT3 = CAN_BT3_50K;
00643 break;
00644 case CAN_SPEED_100K:
00645 CANBT1 = CAN_BT1_100K;
00646 CANBT2 = CAN_BT2_100K;
00647 CANBT3 = CAN_BT3_100K;
00648 break;
00649 case CAN_SPEED_125K:
00650 CANBT1 = CAN_BT1_125K;
00651 CANBT2 = CAN_BT2_125K;
00652 CANBT3 = CAN_BT3_125K;
00653 break;
00654 case CAN_SPEED_250K:
00655 CANBT1 = CAN_BT1_250K;
00656 CANBT2 = CAN_BT2_250K;
00657 CANBT3 = CAN_BT3_250K;
00658 break;
00659 case CAN_SPEED_500K:
00660 CANBT1 = CAN_BT1_500K;
00661 CANBT2 = CAN_BT2_500K;
00662 CANBT3 = CAN_BT3_500K;
00663 break;
00664 case CAN_SPEED_800K:
00665 CANBT1 = CAN_BT1_800K;
00666 CANBT2 = CAN_BT2_800K;
00667 CANBT3 = CAN_BT3_800K;
00668 break;
00669 case CAN_SPEED_1M:
00670 CANBT1 = CAN_BT1_1M;
00671 CANBT2 = CAN_BT2_1M;
00672 CANBT3 = CAN_BT3_1M;
00673 break;
00674 case CAN_SPEED_CUSTOM:
00675
00676 break;
00677 default:
00678 return 1;
00679 }
00680 ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00681 return 0;
00682 }
00683
00684
00695 int AtCanInit(NUTDEVICE * dev)
00696 {
00697 int8_t mob, i;
00698
00699 memset(dev->dev_dcb, 0, sizeof(CANINFO));
00700
00701
00702 canRxBuf.dataptr = NutHeapAlloc(CAN_BUF_SIZE * sizeof(CANFRAME));
00703 if (canRxBuf.dataptr == 0)
00704 return -1;
00705 canRxBuf.size = CAN_BUF_SIZE;
00706 canRxBuf.dataindex = 0;
00707 canRxBuf.datalength = 0;
00708
00709
00710 CANGCON &= ~_BV(ENASTB);
00711 loop_until_bit_is_clear(CANGSTA, ENFG);
00712
00713
00714 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00715 {
00716 CANPAGE = mob << 4;
00717 CANSTMOB = 0;
00718 CANCDMOB = 0;
00719 CANHPMOB = 0;
00720
00721 CANIDT1 = 0;
00722 CANIDT2 = 0;
00723 CANIDT3 = 0;
00724 CANIDT4 = 0;
00725
00726 CANIDM1 = 0;
00727 CANIDM2 = 0;
00728 CANIDM3 = 0;
00729 CANIDM4 = 0;
00730 for (i = 0; i < 8; i++)
00731 {
00732 CANMSG = 0;
00733 }
00734 }
00735
00736 AtCanSetBaudrate(dev, ifc_atcan.can_baudrate);
00737
00738 if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00739 return -1;
00740
00741 CANIE1 = 0x7F;
00742 CANIE2 = 0xFF;
00743 CANGIE = 0xFE;
00744
00745 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00746
00747
00748 CANGCON |= _BV(ENASTB);
00749 loop_until_bit_is_set(CANGSTA, ENFG);
00750
00751 return 0;
00752 }
00753
00754
00761 IFCAN ifc_atcan = {
00762 CAN_IF_2B,
00763 CAN_SPEED_125K,
00764 {0xFF, 0xFF, 0xFF, 0xFF},
00765 {0x00, 0x00, 0x00, 0x00},
00766 NUT_WAIT_INFINITE,
00767 AtCanRxAvail,
00768 AtCanTxFree,
00769 AtCanInput,
00770 AtCanOutput,
00771 AtCanSetAccCode,
00772 AtCanSetAccMask,
00773 AtCanSetBaudrate,
00774 };
00775
00776
00783 NUTDEVICE devAtCan = {
00784 0,
00785 {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0},
00786 IFTYP_CAN,
00787 0,
00788 0,
00789 &ifc_atcan,
00790 &dcb_atcan,
00791 AtCanInit,
00792 0,
00793 0,
00794 0,
00795 0,
00796 0,
00797 0,
00798 0
00799 };
00800
00801 #else
00802
00803 static void keep_icc_happy(void)
00804 {
00805 }
00806
00807 #endif
00808