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
00314 int8_t AtCanEnableMsgObj(uint8_t mob,
00315 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00316 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00317 {
00318 if (mob < ATCAN_MAX_MOB)
00319 {
00320
00321 CANPAGE = mob << 4;
00322
00323 CANCDMOB = 0;
00324
00325 if (idIsExt)
00326 {
00327 CANCDMOB |= _BV(IDE);
00328 CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00329 CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00330 CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00331 CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00332 CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00333 CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00334 CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00335 CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00336 }
00337 else
00338 {
00339 CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00340 CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00341 CANIDT3 = 0;
00342 CANIDT4 = 0;
00343 CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00344 CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00345 CANIDM3 = 0;
00346 CANIDM4 = 0;
00347 }
00348 if (idRemTag)
00349 CANIDT4 |= _BV(RTRTAG);
00350 if (maskIsExt)
00351 CANIDM4 |= _BV(IDEMSK);
00352 if (maskRemTag)
00353 CANIDM4 |= _BV(RTRMSK);
00354
00355 CANCDMOB |= _BV(CONMOB1);
00356 return CAN_SUCCESS;
00357 }
00358 else
00359 return CAN_ILLEGAL_MOB;
00360 }
00361
00362
00382 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00383 uint32_t id, int8_t idIsExt, int8_t idRemTag,
00384 uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00385 {
00386 int8_t i;
00387 int8_t result;
00388
00389 for (i = 0; i < noOfMsgObjs; i++)
00390 {
00391 result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00392 if (result != CAN_SUCCESS)
00393 return result;
00394 }
00395 return CAN_SUCCESS;
00396 }
00397
00398
00405 int8_t AtCanSendMsg(CANFRAME *frame)
00406 {
00407 signed char mob, j;
00408
00409 mob = AtCanGetFreeMob();
00410 if (mob < 0)
00411 return CAN_TXBUF_FULL;
00412
00413 CANPAGE = mob << 4;
00414
00415 CANCDMOB = frame->len;
00416
00417 if (frame->ext)
00418 {
00419 CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00420 CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00421 CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00422 CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00423 CANCDMOB |= _BV(IDE);
00424 }
00425 else
00426 {
00427 CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00428 CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00429 CANIDT3 = 0;
00430 CANIDT4 = 0;
00431 }
00432 if (frame->rtr)
00433 CANIDT4 |= _BV(RTRTAG);
00434 for (j = 0; j < 8; j++)
00435 CANMSG = frame->byte[j];
00436
00437 CANCDMOB |= _BV(CONMOB0);
00438
00439 return CAN_SUCCESS;
00440 }
00441
00442
00446 static void AtCanInterrupt(void *arg)
00447 {
00448 uint8_t savedCanPage;
00449 CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00450
00451 savedCanPage = CANPAGE;
00452 ci->can_interrupts++;
00453
00454
00455
00456
00457 if ((CANHPMOB & 0xF0) != 0xF0)
00458 {
00459 CANPAGE = CANHPMOB;
00460
00461 if (bit_is_set(CANSTMOB, RXOK))
00462 {
00463
00464 if (canRxBuf.datalength < canRxBuf.size)
00465 {
00466 int8_t j;
00467 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00468
00469
00470 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00471 if (bufPtr->ext)
00472 {
00473 ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00474 ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00475 ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00476 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00477 }
00478 else
00479 {
00480 ((uint8_t *) &(bufPtr->id))[3] = 0;
00481 ((uint8_t *) &(bufPtr->id))[2] = 0;
00482 ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00483 ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00484 }
00485 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00486 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00487 for (j = 0; j < 8; j++)
00488 bufPtr->byte[j] = CANMSG;
00489
00490 canRxBuf.datalength++;
00491 NutEventPostFromIrq(&ci->can_rx_rdy);
00492
00493 ci->can_rx_frames++;
00494 }
00495 else
00496 {
00497
00498 ci->can_overruns++;
00499 }
00500 }
00501
00502 else if (bit_is_set(CANSTMOB, TXOK))
00503 {
00504 NutEventPostFromIrq(&ci->can_tx_rdy);
00505 ci->can_tx_frames++;
00506 }
00507
00508 else
00509 {
00510
00511 ci->can_errors++;
00512 }
00513
00514
00515
00516
00517 CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) |
00518 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00519
00520 if (bit_is_set(CANCDMOB, CONMOB1))
00521
00522 CANCDMOB |= _BV(CONMOB1);
00523 else
00524
00525 CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00526
00527 }
00528 else
00529 {
00530
00531 CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00532
00533 ci->can_errors++;
00534 }
00535 CANPAGE = savedCanPage;
00536 }
00537
00538
00539
00540
00541
00542
00549 uint8_t AtCanRxAvail(NUTDEVICE * dev)
00550 {
00551 return canRxBuf.datalength;
00552 }
00553
00554
00561 uint8_t AtCanTxFree(NUTDEVICE * dev)
00562 {
00563 return (AtCanGetFreeMob() >= 0);
00564 }
00565
00566
00576 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00577 {
00578 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00579
00580 while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00581 {
00582 NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00583 };
00584 }
00585
00586
00598 uint8_t AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00599 {
00600 CANINFO * ci = (CANINFO *) dev->dev_dcb;
00601
00602 while (canRxBuf.datalength == 0)
00603 {
00604 uint32_t timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00605
00606 if (NutEventWait(&ci->can_rx_rdy, timeout))
00607 return 1;
00608 }
00609 NutEnterCritical();
00610
00611 *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00612
00613 canRxBuf.dataindex++;
00614 if (canRxBuf.dataindex >= canRxBuf.size)
00615 canRxBuf.dataindex %= canRxBuf.size;
00616 canRxBuf.datalength--;
00617 NutExitCritical();
00618
00619 return 0;
00620 }
00621
00622
00629 void AtCanSetAccCode(NUTDEVICE * dev, uint8_t * ac)
00630 {
00631 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00632 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00633 }
00634
00635
00642 void AtCanSetAccMask(NUTDEVICE * dev, uint8_t * am)
00643 {
00644 memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00645 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00646 }
00647
00648
00656 uint8_t AtCanSetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
00657 {
00658 switch (baudrate)
00659 {
00660 #if NUT_CPU_FREQ != 8000000
00661 case CAN_SPEED_10K:
00662 CANBT1 = CAN_BT1_10K;
00663 CANBT2 = CAN_BT2_10K;
00664 CANBT3 = CAN_BT3_10K;
00665 break;
00666 case CAN_SPEED_20K:
00667 CANBT1 = CAN_BT1_20K;
00668 CANBT2 = CAN_BT2_20K;
00669 CANBT3 = CAN_BT3_20K;
00670 break;
00671 case CAN_SPEED_50K:
00672 CANBT1 = CAN_BT1_50K;
00673 CANBT2 = CAN_BT2_50K;
00674 CANBT3 = CAN_BT3_50K;
00675 break;
00676 #endif
00677 case CAN_SPEED_100K:
00678 CANBT1 = CAN_BT1_100K;
00679 CANBT2 = CAN_BT2_100K;
00680 CANBT3 = CAN_BT3_100K;
00681 break;
00682 case CAN_SPEED_125K:
00683 CANBT1 = CAN_BT1_125K;
00684 CANBT2 = CAN_BT2_125K;
00685 CANBT3 = CAN_BT3_125K;
00686 break;
00687 case CAN_SPEED_250K:
00688 CANBT1 = CAN_BT1_250K;
00689 CANBT2 = CAN_BT2_250K;
00690 CANBT3 = CAN_BT3_250K;
00691 break;
00692 case CAN_SPEED_500K:
00693 CANBT1 = CAN_BT1_500K;
00694 CANBT2 = CAN_BT2_500K;
00695 CANBT3 = CAN_BT3_500K;
00696 break;
00697 #if NUT_CPU_FREQ != 8000000
00698 case CAN_SPEED_800K:
00699 CANBT1 = CAN_BT1_800K;
00700 CANBT2 = CAN_BT2_800K;
00701 CANBT3 = CAN_BT3_800K;
00702 break;
00703 #endif
00704 case CAN_SPEED_1M:
00705 CANBT1 = CAN_BT1_1M;
00706 CANBT2 = CAN_BT2_1M;
00707 CANBT3 = CAN_BT3_1M;
00708 break;
00709 case CAN_SPEED_CUSTOM:
00710
00711 break;
00712 default:
00713 return 1;
00714 }
00715 ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00716 return 0;
00717 }
00718
00719
00730 int AtCanInit(NUTDEVICE * dev)
00731 {
00732 int8_t mob, i;
00733
00734 memset(dev->dev_dcb, 0, sizeof(CANINFO));
00735
00736
00737 canRxBuf.dataptr = NutHeapAlloc(ATCAN_RX_BUF_SIZE * sizeof(CANFRAME));
00738 if (canRxBuf.dataptr == 0)
00739 return -1;
00740 canRxBuf.size = ATCAN_RX_BUF_SIZE;
00741 canRxBuf.dataindex = 0;
00742 canRxBuf.datalength = 0;
00743
00744
00745 CANGCON &= ~_BV(ENASTB);
00746 loop_until_bit_is_clear(CANGSTA, ENFG);
00747
00748
00749 for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00750 {
00751 CANPAGE = mob << 4;
00752 CANSTMOB = 0;
00753 CANCDMOB = 0;
00754 CANHPMOB = 0;
00755
00756 CANIDT1 = 0;
00757 CANIDT2 = 0;
00758 CANIDT3 = 0;
00759 CANIDT4 = 0;
00760
00761 CANIDM1 = 0;
00762 CANIDM2 = 0;
00763 CANIDM3 = 0;
00764 CANIDM4 = 0;
00765 for (i = 0; i < 8; i++)
00766 {
00767 CANMSG = 0;
00768 }
00769 }
00770
00771 AtCanSetBaudrate(dev, ifc_atcan.can_baudrate);
00772
00773 if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00774 return -1;
00775
00776 CANIE1 = 0x7F;
00777 CANIE2 = 0xFF;
00778 CANGIE = 0xFE;
00779
00780 AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00781
00782
00783 CANGCON |= _BV(ENASTB);
00784 loop_until_bit_is_set(CANGSTA, ENFG);
00785
00786 return 0;
00787 }
00788
00789
00796 IFCAN ifc_atcan = {
00797 CAN_IF_2B,
00798 CAN_SPEED_125K,
00799 {0xFF, 0xFF, 0xFF, 0xFF},
00800 {0x00, 0x00, 0x00, 0x00},
00801 NUT_WAIT_INFINITE,
00802 AtCanRxAvail,
00803 AtCanTxFree,
00804 AtCanInput,
00805 AtCanOutput,
00806 AtCanSetAccCode,
00807 AtCanSetAccMask,
00808 AtCanSetBaudrate,
00809 };
00810
00811
00818 NUTDEVICE devAtCan = {
00819 0,
00820 {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0},
00821 IFTYP_CAN,
00822 0,
00823 0,
00824 &ifc_atcan,
00825 &dcb_atcan,
00826 AtCanInit,
00827 0,
00828 0,
00829 0,
00830 0,
00831 0,
00832 0,
00833 0
00834 };
00835
00836 #else
00837
00838 static void keep_icc_happy(void)
00839 {
00840 }
00841
00842 #endif
00843