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