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