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