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 == 8000000
00119
00120 #define CAN_BT1_100K 0x08
00121 #define CAN_BT2_100K 0x0C
00122 #define CAN_BT3_100K 0x37
00123
00124 #define CAN_BT1_125K 0x0E
00125 #define CAN_BT2_125K 0x04
00126 #define CAN_BT3_125K 0x13
00127
00128 #define CAN_BT1_250K 0x06
00129 #define CAN_BT2_250K 0x04
00130 #define CAN_BT3_250K 0x13
00131
00132 #define CAN_BT1_500K 0x02
00133 #define CAN_BT2_500K 0x0C
00134 #define CAN_BT3_500K 0x37
00135
00136 #define CAN_BT1_1M 0x00
00137 #define CAN_BT2_1M 0x04
00138 #define CAN_BT3_1M 0x12
00139
00140
00141
00142
00143 #elif NUT_CPU_FREQ == 12000000
00144
00145 #define CAN_BT1_10K 0x76
00146 #define CAN_BT2_10K 0x2E
00147 #define CAN_BT3_10K 0x2E
00148
00149 #define CAN_BT1_20K 0x4E
00150 #define CAN_BT2_20K 0x2E
00151 #define CAN_BT3_20K 0x16
00152
00153 #define CAN_BT1_50K 0x1C
00154 #define CAN_BT2_50K 0x2E
00155 #define CAN_BT3_50K 0x18
00156
00157 #define CAN_BT1_100K 0x0E
00158 #define CAN_BT2_100K 0x2E
00159 #define CAN_BT3_100K 0x16
00160
00161 #define CAN_BT1_125K 0x0A
00162 #define CAN_BT2_125K 0x2E
00163 #define CAN_BT3_125K 0x18
00164
00165 #define CAN_BT1_250K 0x04
00166 #define CAN_BT2_250K 0x2E
00167 #define CAN_BT3_250K 0x18
00168
00169 #define CAN_BT1_500K 0x02
00170 #define CAN_BT2_500K 0x2C
00171 #define CAN_BT3_500K 0x12
00172
00173 #define CAN_BT1_800K 0x00
00174 #define CAN_BT2_800K 0x2E
00175 #define CAN_BT3_800K 0x16
00176
00177 #define CAN_BT1_1M 0x00
00178 #define CAN_BT2_1M 0x2C
00179 #define CAN_BT3_1M 0x12
00180
00181
00182
00183
00184 #elif NUT_CPU_FREQ == 16000000
00185
00186 #define CAN_BT1_10K 0x7E
00187 #define CAN_BT2_10K 0x2E
00188 #define CAN_BT3_10K 0x7E
00189
00190 #define CAN_BT1_20K 0x62
00191 #define CAN_BT2_20K 0x2E
00192 #define CAN_BT3_20K 0x18
00193
00194 #define CAN_BT1_50K 0x26
00195 #define CAN_BT2_50K 0x2E
00196 #define CAN_BT3_50K 0x18
00197
00198 #define CAN_BT1_100K 0x12
00199 #define CAN_BT2_100K 0x2E
00200 #define CAN_BT3_100K 0x18
00201
00202 #define CAN_BT1_125K 0x0E
00203 #define CAN_BT2_125K 0x2E
00204 #define CAN_BT3_125K 0x18
00205
00206 #define CAN_BT1_250K 0x06
00207 #define CAN_BT2_250K 0x2E
00208 #define CAN_BT3_250K 0x18
00209
00210 #define CAN_BT1_500K 0x02
00211 #define CAN_BT2_500K 0x2E
00212 #define CAN_BT3_500K 0x18
00213
00214 #define CAN_BT1_800K 0x00
00215 #define CAN_BT2_800K 0x2E
00216 #define CAN_BT3_800K 0x2E
00217
00218 #define CAN_BT1_1M 0x00
00219 #define CAN_BT2_1M 0x2E
00220 #define CAN_BT3_1M 0x18
00221 #else
00222 # error Frequency not supported or not set to a Fixed MCU clock!
00223 #endif
00224
00225
00226
00227
00228
00229
00230
00231
00232 struct _CANBuffer {
00233 CANFRAME *dataptr;
00234 uint8_t size;
00235 uint8_t datalength;
00236 uint8_t dataindex;
00237 };
00238
00239 typedef struct _CANBuffer CANBuffer;
00240
00241
00242
00243
00244
00245
00246 static CANBuffer canRxBuf;
00247 CANINFO dcb_atcan;
00248 IFCAN ifc_atcan;
00249 NUTDEVICE devAtCan;
00250
00251
00252
00253
00254
00255
00265 int8_t AtCanGetBusState(void)
00266 {
00267 if (CANGSTA & _BV(BOFF))
00268 return CAN_BUS_OFF;
00269 if (CANGSTA & _BV(ERRP))
00270 return CAN_PASSIVE;
00271 return CAN_SUCCESS;
00272 }
00273
00274
00280 int8_t AtCanGetFreeMob(void)
00281 {
00282 int8_t mob;
00283 uint8_t ctrlReg;
00284
00285 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00286 {
00287 CANPAGE = mob << 4;
00288 ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
00289 if (ctrlReg == 0)
00290 return mob;
00291 if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
00292 {
00293
00294 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00295 return mob;
00296 }
00297 }
00298 return -1;
00299 }
00300
00301
00316 int8_t AtCanEnableMsgObj(uint8_t mob,
00317 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00318 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00319 {
00320 if (mob < ATCAN_MAX_MOB)
00321 {
00322
00323 CANPAGE = mob << 4;
00324
00325 CANCDMOB = 0;
00326
00327 if (idIsExt)
00328 {
00329 CANCDMOB |= _BV(IDE);
00330 CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00331 CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00332 CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00333 CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00334 CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00335 CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00336 CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00337 CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00338 }
00339 else
00340 {
00341 CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00342 CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00343 CANIDT3 = 0;
00344 CANIDT4 = 0;
00345 CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00346 CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00347 CANIDM3 = 0;
00348 CANIDM4 = 0;
00349 }
00350 if (idRemTag)
00351 CANIDT4 |= _BV(RTRTAG);
00352 if (maskIsExt)
00353 CANIDM4 |= _BV(IDEMSK);
00354 if (maskRemTag)
00355 CANIDM4 |= _BV(RTRMSK);
00356
00357 CANCDMOB |= _BV(CONMOB1);
00358 return CAN_SUCCESS;
00359 }
00360 else
00361 return CAN_ILLEGAL_MOB;
00362 }
00363
00364
00384 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00385 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00386 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00387 {
00388 int8_t i;
00389 int8_t result;
00390
00391 for (i = 0; i < noOfMsgObjs; i++)
00392 {
00393 result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00394 if (result != CAN_SUCCESS)
00395 return result;
00396 }
00397 return CAN_SUCCESS;
00398 }
00399
00400
00407 int8_t AtCanSendMsg(CANFRAME *frame)
00408 {
00409 signed char mob, j;
00410
00411 mob = AtCanGetFreeMob();
00412 if (mob < 0)
00413 return CAN_TXBUF_FULL;
00414
00415 CANPAGE = mob << 4;
00416
00417 CANCDMOB = frame->len;
00418
00419 if (frame->ext)
00420 {
00421 CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00422 CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00423 CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00424 CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00425 CANCDMOB |= _BV(IDE);
00426 }
00427 else
00428 {
00429 CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00430 CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00431 CANIDT3 = 0;
00432 CANIDT4 = 0;
00433 }
00434 if (frame->rtr)
00435 CANIDT4 |= _BV(RTRTAG);
00436 for (j = 0; j < 8; j++)
00437 CANMSG = frame->byte[j];
00438
00439 CANCDMOB |= _BV(CONMOB0);
00440
00441 return CAN_SUCCESS;
00442 }
00443
00444
00448 static void AtCanInterrupt(void *arg)
00449 {
00450 uint8_t savedCanPage;
00451 CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00452
00453 savedCanPage = CANPAGE;
00454 ci->can_interrupts++;
00455
00456
00457
00458
00459 if ((CANHPMOB & 0xF0) != 0xF0)
00460 {
00461 CANPAGE = CANHPMOB;
00462
00463 if (bit_is_set(CANSTMOB, RXOK))
00464 {
00465
00466 if (canRxBuf.datalength < canRxBuf.size)
00467 {
00468 int8_t j;
00469 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00470
00471
00472 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00473 if (bufPtr->ext)
00474 {
00475 ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00476 ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00477 ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00478 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00479 }
00480 else
00481 {
00482 ((uint8_t *) &(bufPtr->id))[3] = 0;
00483 ((uint8_t *) &(bufPtr->id))[2] = 0;
00484 ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00485 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00486 }
00487 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00488 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00489 for (j = 0; j < 8; j++)
00490 bufPtr->byte[j] = CANMSG;
00491
00492 canRxBuf.datalength++;
00493 NutEventPostFromIrq(&ci->can_rx_rdy);
00494
00495 ci->can_rx_frames++;
00496 }
00497 else
00498 {
00499
00500 ci->can_overruns++;
00501 }
00502 }
00503
00504 else if (bit_is_set(CANSTMOB, TXOK))
00505 {
00506 NutEventPostFromIrq(&ci->can_tx_rdy);
00507 ci->can_tx_frames++;
00508 }
00509
00510 else
00511 {
00512
00513 ci->can_errors++;
00514 }
00515
00516
00517
00518
00519 CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) |
00520 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00521
00522 if (bit_is_set(CANCDMOB, CONMOB1))
00523
00524 CANCDMOB |= _BV(CONMOB1);
00525 else
00526
00527 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00528
00529 }
00530 else
00531 {
00532
00533 CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00534
00535 ci->can_errors++;
00536 }
00537 CANPAGE = savedCanPage;
00538 }
00539
00540
00541
00542
00543
00544
00551 uint8_t AtCanRxAvail(NUTDEVICE * dev)
00552 {
00553 return canRxBuf.datalength;
00554 }
00555
00556
00563 uint8_t AtCanTxFree(NUTDEVICE * dev)
00564 {
00565 return (AtCanGetFreeMob() >= 0);
00566 }
00567
00568
00578 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00579 {
00580 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00581
00582 while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00583 {
00584 NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00585 };
00586 }
00587
00588
00600 uint8_t AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00601 {
00602 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00603
00604 while (canRxBuf.datalength == 0)
00605 {
00606 uint32_t timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00607
00608 if (NutEventWait(&ci->can_rx_rdy, timeout))
00609 return 1;
00610 }
00611 NutEnterCritical();
00612
00613 *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00614
00615 canRxBuf.dataindex++;
00616 if (canRxBuf.dataindex >= canRxBuf.size)
00617 canRxBuf.dataindex %= canRxBuf.size;
00618 canRxBuf.datalength--;
00619 NutExitCritical();
00620
00621 return 0;
00622 }
00623
00624
00631 void AtCanSetAccCode(NUTDEVICE * dev, uint8_t * ac)
00632 {
00633 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00634 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00635 }
00636
00637
00644 void AtCanSetAccMask(NUTDEVICE * dev, uint8_t * am)
00645 {
00646 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00647 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00648 }
00649
00650
00658 uint8_t AtCanSetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
00659 {
00660 switch (baudrate)
00661 {
00662 #if NUT_CPU_FREQ != 8000000
00663 case CAN_SPEED_10K:
00664 CANBT1 = CAN_BT1_10K;
00665 CANBT2 = CAN_BT2_10K;
00666 CANBT3 = CAN_BT3_10K;
00667 break;
00668 case CAN_SPEED_20K:
00669 CANBT1 = CAN_BT1_20K;
00670 CANBT2 = CAN_BT2_20K;
00671 CANBT3 = CAN_BT3_20K;
00672 break;
00673 case CAN_SPEED_50K:
00674 CANBT1 = CAN_BT1_50K;
00675 CANBT2 = CAN_BT2_50K;
00676 CANBT3 = CAN_BT3_50K;
00677 break;
00678 #endif
00679 case CAN_SPEED_100K:
00680 CANBT1 = CAN_BT1_100K;
00681 CANBT2 = CAN_BT2_100K;
00682 CANBT3 = CAN_BT3_100K;
00683 break;
00684 case CAN_SPEED_125K:
00685 CANBT1 = CAN_BT1_125K;
00686 CANBT2 = CAN_BT2_125K;
00687 CANBT3 = CAN_BT3_125K;
00688 break;
00689 case CAN_SPEED_250K:
00690 CANBT1 = CAN_BT1_250K;
00691 CANBT2 = CAN_BT2_250K;
00692 CANBT3 = CAN_BT3_250K;
00693 break;
00694 case CAN_SPEED_500K:
00695 CANBT1 = CAN_BT1_500K;
00696 CANBT2 = CAN_BT2_500K;
00697 CANBT3 = CAN_BT3_500K;
00698 break;
00699 #if NUT_CPU_FREQ != 8000000
00700 case CAN_SPEED_800K:
00701 CANBT1 = CAN_BT1_800K;
00702 CANBT2 = CAN_BT2_800K;
00703 CANBT3 = CAN_BT3_800K;
00704 break;
00705 #endif
00706 case CAN_SPEED_1M:
00707 CANBT1 = CAN_BT1_1M;
00708 CANBT2 = CAN_BT2_1M;
00709 CANBT3 = CAN_BT3_1M;
00710 break;
00711 case CAN_SPEED_CUSTOM:
00712
00713 break;
00714 default:
00715 return 1;
00716 }
00717 ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00718 return 0;
00719 }
00720
00721
00732 int AtCanInit(NUTDEVICE * dev)
00733 {
00734 int8_t mob, i;
00735
00736 memset(dev->dev_dcb, 0, sizeof(CANINFO));
00737
00738
00739 canRxBuf.dataptr = NutHeapAlloc(ATCAN_RX_BUF_SIZE * sizeof(CANFRAME));
00740 if (canRxBuf.dataptr == 0)
00741 return -1;
00742 canRxBuf.size = ATCAN_RX_BUF_SIZE;
00743 canRxBuf.dataindex = 0;
00744 canRxBuf.datalength = 0;
00745
00746
00747 CANGCON &= ~_BV(ENASTB);
00748 loop_until_bit_is_clear(CANGSTA, ENFG);
00749
00750
00751 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00752 {
00753 CANPAGE = mob << 4;
00754 CANSTMOB = 0;
00755 CANCDMOB = 0;
00756 CANHPMOB = 0;
00757
00758 CANIDT1 = 0;
00759 CANIDT2 = 0;
00760 CANIDT3 = 0;
00761 CANIDT4 = 0;
00762
00763 CANIDM1 = 0;
00764 CANIDM2 = 0;
00765 CANIDM3 = 0;
00766 CANIDM4 = 0;
00767 for (i = 0; i < 8; i++)
00768 {
00769 CANMSG = 0;
00770 }
00771 }
00772
00773 AtCanSetBaudrate(dev, ifc_atcan.can_baudrate);
00774
00775 if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00776 return -1;
00777
00778 CANIE1 = 0x7F;
00779 CANIE2 = 0xFF;
00780 CANGIE = 0xFE;
00781
00782 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00783
00784
00785 CANGCON |= _BV(ENASTB);
00786 loop_until_bit_is_set(CANGSTA, ENFG);
00787
00788 return 0;
00789 }
00790
00791
00798 IFCAN ifc_atcan = {
00799 CAN_IF_2B,
00800 CAN_SPEED_125K,
00801 {0xFF, 0xFF, 0xFF, 0xFF},
00802 {0x00, 0x00, 0x00, 0x00},
00803 NUT_WAIT_INFINITE,
00804 AtCanRxAvail,
00805 AtCanTxFree,
00806 AtCanInput,
00807 AtCanOutput,
00808 AtCanSetAccCode,
00809 AtCanSetAccMask,
00810 AtCanSetBaudrate,
00811 };
00812
00813
00820 NUTDEVICE devAtCan = {
00821 0,
00822 {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0},
00823 IFTYP_CAN,
00824 0,
00825 0,
00826 &ifc_atcan,
00827 &dcb_atcan,
00828 AtCanInit,
00829 0,
00830 0,
00831 0,
00832 0,
00833 0,
00834 0,
00835 0
00836 };
00837
00838 #else
00839
00840 static void keep_icc_happy(void)
00841 {
00842 }
00843
00844 #endif
00845