atcan.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /*
  2. * Copyright (c) 2005-2009 proconX Pty Ltd. All rights reserved.
  3. *
  4. * This driver has been closely modeled after the existing Nut/OS SJA1000
  5. * driver and the buffer management and some code snippets have been borrowed
  6. * from sja1000.c.
  7. *
  8. * Portions Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>,
  9. * Kernelconcepts http://www.kernelconcepts.de
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. Neither the name of the copyright holders nor the names of
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  31. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  32. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  33. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  34. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. *
  37. * For additional information see http://www.ethernut.de/
  38. *
  39. */
  40. /*!
  41. * \file arch/avr/dev/atcan.c
  42. * \brief AVR on-chip CAN support.
  43. *
  44. * \verbatim
  45. * $Id: atcan.c 5472 2013-12-06 00:16:28Z olereinhardt $
  46. * \endverbatim
  47. */
  48. /*!
  49. * \addtogroup xgCanAvr
  50. */
  51. /*@{*/
  52. #ifdef __GNUC__
  53. #include <cfg/arch/avr.h>
  54. #include <string.h>
  55. #include <sys/event.h>
  56. #include <sys/heap.h>
  57. #include <sys/atom.h>
  58. #include <dev/irqreg.h>
  59. #include <dev/can_dev.h>
  60. #include <avr/io.h>
  61. #include <dev/atcan.h>
  62. /*****************************************************************************
  63. * Definitions
  64. *****************************************************************************/
  65. #define RX_MOB 8
  66. #ifndef ATCAN_RX_BUF_SIZE
  67. # define ATCAN_RX_BUF_SIZE 64
  68. #endif
  69. /*****************************************************************************
  70. * CAN baud rate table
  71. *
  72. * Tried to match as closely as possible a sampling point of 87.5 %
  73. * which is recommended by CiA for CANOpen. DeviceNet specifies a
  74. * sampling point > 80%. SQW is 2.
  75. *****************************************************************************/
  76. #if defined(NUT_CPU_FREQ)
  77. //
  78. // 8.00 MHz
  79. //
  80. #if NUT_CPU_FREQ == 8000000
  81. // 100 kbit/s 86.67% 15 quanta (BRP=7 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
  82. #define CAN_BT1_100K 0x08
  83. #define CAN_BT2_100K 0x0C
  84. #define CAN_BT3_100K 0x37
  85. // 125 kbit/s 87.50% 16 quanta (BRP=5 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  86. #define CAN_BT1_125K 0x0E
  87. #define CAN_BT2_125K 0x04
  88. #define CAN_BT3_125K 0x13
  89. // 250 kbit/s 87.50% 16 quanta (BRP=2 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  90. #define CAN_BT1_250K 0x06
  91. #define CAN_BT2_250K 0x04
  92. #define CAN_BT3_250K 0x13
  93. // 500 kbit/s 83.33% 12 quanta (BRP=1 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
  94. #define CAN_BT1_500K 0x02
  95. #define CAN_BT2_500K 0x0C
  96. #define CAN_BT3_500K 0x37
  97. // 1000 kbit/s 83.33% 12 quanta (BRP=0 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
  98. #define CAN_BT1_1M 0x00
  99. #define CAN_BT2_1M 0x04
  100. #define CAN_BT3_1M 0x12
  101. //
  102. // 12.00 MHz
  103. //
  104. #elif NUT_CPU_FREQ == 12000000
  105. // 10 kbit/s 85.00% 20 quanta (BRP=59 Tprs=8 Tph1=8 Tph2=3 Tsjw=2)
  106. #define CAN_BT1_10K 0x76
  107. #define CAN_BT2_10K 0x2E
  108. #define CAN_BT3_10K 0x2E
  109. // 20 kbit/s 86.67% 15 quanta (BRP=39 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
  110. #define CAN_BT1_20K 0x4E
  111. #define CAN_BT2_20K 0x2E
  112. #define CAN_BT3_20K 0x16
  113. // 50 kbit/s 87.50% 16 quanta (BRP=14 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  114. #define CAN_BT1_50K 0x1C
  115. #define CAN_BT2_50K 0x2E
  116. #define CAN_BT3_50K 0x18
  117. // 100 kbit/s 86.67% 15 quanta (BRP=7 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
  118. #define CAN_BT1_100K 0x0E
  119. #define CAN_BT2_100K 0x2E
  120. #define CAN_BT3_100K 0x16
  121. // 125 kbit/s 87.50% 16 quanta (BRP=5 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  122. #define CAN_BT1_125K 0x0A
  123. #define CAN_BT2_125K 0x2E
  124. #define CAN_BT3_125K 0x18
  125. // 250 kbit/s 87.50% 16 quanta (BRP=2 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  126. #define CAN_BT1_250K 0x04
  127. #define CAN_BT2_250K 0x2E
  128. #define CAN_BT3_250K 0x18
  129. // 500 kbit/s 83.33% 12 quanta (BRP=1 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
  130. #define CAN_BT1_500K 0x02
  131. #define CAN_BT2_500K 0x2C
  132. #define CAN_BT3_500K 0x12
  133. // 800 kbit/s 86.67% 15 quanta (BRP=0 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
  134. #define CAN_BT1_800K 0x00
  135. #define CAN_BT2_800K 0x2E
  136. #define CAN_BT3_800K 0x16
  137. // 1000 kbit/s 83.33% 12 quanta (BRP=0 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
  138. #define CAN_BT1_1M 0x00
  139. #define CAN_BT2_1M 0x2C
  140. #define CAN_BT3_1M 0x12
  141. //
  142. // 16.00 MHz
  143. //
  144. #elif NUT_CPU_FREQ == 16000000
  145. // 10 kbit/s 68.00% 25 quanta (BRP=63 Tprs=8 Tph1=8 Tph2=8 Tsjw=2)
  146. #define CAN_BT1_10K 0x7E
  147. #define CAN_BT2_10K 0x2E
  148. #define CAN_BT3_10K 0x7E
  149. // 20 kbit/s 87.50% 16 quanta (BRP=49 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  150. #define CAN_BT1_20K 0x62
  151. #define CAN_BT2_20K 0x2E
  152. #define CAN_BT3_20K 0x18
  153. // 50 kbit/s 87.50% 16 quanta (BRP=19 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  154. #define CAN_BT1_50K 0x26
  155. #define CAN_BT2_50K 0x2E
  156. #define CAN_BT3_50K 0x18
  157. // 100 kbit/s 87.50% 16 quanta (BRP=9 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  158. #define CAN_BT1_100K 0x12
  159. #define CAN_BT2_100K 0x2E
  160. #define CAN_BT3_100K 0x18
  161. // 125 kbit/s 87.50% 16 quanta (BRP=7 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  162. #define CAN_BT1_125K 0x0E
  163. #define CAN_BT2_125K 0x2E
  164. #define CAN_BT3_125K 0x18
  165. // 250 kbit/s 87.50% 16 quanta (BRP=3 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  166. #define CAN_BT1_250K 0x06
  167. #define CAN_BT2_250K 0x2E
  168. #define CAN_BT3_250K 0x18
  169. // 500 kbit/s 87.50% 16 quanta (BRP=1 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  170. #define CAN_BT1_500K 0x02
  171. #define CAN_BT2_500K 0x2E
  172. #define CAN_BT3_500K 0x18
  173. // 800 kbit/s 85.00% 20 quanta (BRP=0 Tprs=8 Tph1=8 Tph2=3 Tsjw=2)
  174. #define CAN_BT1_800K 0x00
  175. #define CAN_BT2_800K 0x2E
  176. #define CAN_BT3_800K 0x2E
  177. // 1000 kbit/s 87.50% 16 quanta (BRP=0 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
  178. #define CAN_BT1_1M 0x00
  179. #define CAN_BT2_1M 0x2E
  180. #define CAN_BT3_1M 0x18
  181. #else
  182. # error Frequency not supported or not set to a Fixed MCU clock!
  183. #endif
  184. #endif
  185. /*****************************************************************************
  186. * Buffer management
  187. *
  188. * Note: Buffer concept borrowed from existing Nut/OS sja1000.c driver
  189. *****************************************************************************/
  190. struct _CANBuffer {
  191. CANFRAME *dataptr; // the physical memory address where the buffer is stored
  192. uint8_t size; // the allocated size of the buffer
  193. uint8_t datalength; // the length of the data currently in the buffer
  194. uint8_t dataindex; // the index into the buffer where the data starts
  195. };
  196. typedef struct _CANBuffer CANBuffer;
  197. /*****************************************************************************
  198. * Driver data
  199. *****************************************************************************/
  200. static CANBuffer canRxBuf;
  201. CANINFO dcb_atcan;
  202. IFCAN ifc_atcan;
  203. NUTDEVICE devAtCan;
  204. /*****************************************************************************
  205. * Low level functions
  206. *****************************************************************************/
  207. /**
  208. * Returns the state of this CAN node.
  209. * Refer to state diagram in AT90CAN128 dataheet chapter 20.7 "Error
  210. * Management"
  211. *
  212. * @retval CAN_SUCCESS if CAN node is in ACTIVE state
  213. * @retval CAN_PASSIVE if CAN node is in PASSIVE state
  214. * @retval CAN_BUS_OFF if CAN node is in BUS OFF state
  215. */
  216. int8_t AtCanGetBusState(void)
  217. {
  218. if (CANGSTA & _BV(BOFF))
  219. return CAN_BUS_OFF;
  220. if (CANGSTA & _BV(ERRP))
  221. return CAN_PASSIVE;
  222. return CAN_SUCCESS;
  223. }
  224. /**
  225. * @internal
  226. * Search for a free message object
  227. * @return Index of free message object or -1 if none is available
  228. */
  229. int8_t AtCanGetFreeMob(void)
  230. {
  231. int8_t mob;
  232. uint8_t ctrlReg;
  233. for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
  234. {
  235. CANPAGE = mob << 4;
  236. ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
  237. if (ctrlReg == 0)
  238. return mob;
  239. if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
  240. {
  241. // Free MOB
  242. CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
  243. return mob;
  244. }
  245. }
  246. return -1;
  247. }
  248. /**
  249. * Configure a single message object for receiption.
  250. *
  251. * All 15 MOBS can be set up for reception, not only RX_MOB MOBs
  252. *
  253. * @param mob Message object index (0-14)
  254. * @param id Acceptance code
  255. * @param idIsExt Flag if acceptance code is extended (0 = standard, 1 = extended)
  256. * @param idRemTag Id's remote tag (0 or 1)
  257. * @param mask Acceptance mask
  258. * @param maskIsExt Flag if acceptance mask is extended (0 = standard, 1 = extended)
  259. * @param maskRemTag Mask's remote tag (0 or 1)
  260. * @return Result code. See @ref CAN_RESULT
  261. */
  262. int8_t AtCanEnableMsgObj(uint8_t mob,
  263. uint32_t id, int8_t idIsExt, int8_t idRemTag,
  264. uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
  265. {
  266. if (mob < ATCAN_MAX_MOB)
  267. {
  268. // Select MOb
  269. CANPAGE = mob << 4;
  270. // Abort MOb
  271. CANCDMOB = 0;
  272. // Set identifier and mask
  273. if (idIsExt)
  274. {
  275. CANCDMOB |= _BV(IDE);
  276. CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
  277. CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
  278. CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
  279. CANIDT4 = (((uint8_t *) &(id))[0] << 3);
  280. CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
  281. CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
  282. CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
  283. CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
  284. }
  285. else
  286. {
  287. CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
  288. CANIDT2 = (((uint8_t *) &(id))[0] << 5);
  289. CANIDT3 = 0;
  290. CANIDT4 = 0;
  291. CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
  292. CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
  293. CANIDM3 = 0;
  294. CANIDM4 = 0;
  295. }
  296. if (idRemTag)
  297. CANIDT4 |= _BV(RTRTAG);
  298. if (maskIsExt)
  299. CANIDM4 |= _BV(IDEMSK);
  300. if (maskRemTag)
  301. CANIDM4 |= _BV(RTRMSK);
  302. // Enable reception
  303. CANCDMOB |= _BV(CONMOB1);
  304. return CAN_SUCCESS;
  305. }
  306. else
  307. return CAN_ILLEGAL_MOB;
  308. }
  309. /**
  310. * Configure message objects for receiption.
  311. *
  312. * @param noOfMsgObjs Number of message objects used for receiption (1-14).
  313. * Message objects not configured for receiption are used for
  314. * transmission.
  315. * The same acceptance filter and mask is applied to the
  316. * message objects.
  317. * If it is required to set-up more complex
  318. * filtering mechanisms use canEnableMsgObj() instead, which
  319. * allows setting filters on a per message object basis.
  320. * @param id Acceptance code
  321. * @param idIsExt Flag if acceptance code is extended (0 = standard, 1 = extended)
  322. * @param idRemTag Id's remote tag (0 or 1)
  323. * @param mask Acceptance mask
  324. * @param maskIsExt Flag if acceptance mask is extended (0 = standard, 1 = extended)
  325. * @param maskRemTag Mask's remote tag (0 or 1)
  326. * @return Result code. See @ref CAN_RESULT
  327. */
  328. int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
  329. uint32_t id, int8_t idIsExt, int8_t idRemTag,
  330. uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
  331. {
  332. int8_t i;
  333. int8_t result;
  334. for (i = 0; i < noOfMsgObjs; i++)
  335. {
  336. result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
  337. if (result != CAN_SUCCESS)
  338. return result;
  339. }
  340. return CAN_SUCCESS;
  341. }
  342. /**
  343. * Send a CAN message
  344. *
  345. * @param frame Container for CAN message to be sent
  346. * @return Result code. See @ref CAN_RESULT
  347. */
  348. int8_t AtCanSendMsg(CANFRAME *frame)
  349. {
  350. signed char mob, j;
  351. mob = AtCanGetFreeMob();
  352. if (mob < 0)
  353. return CAN_TXBUF_FULL;
  354. // Select MOB
  355. CANPAGE = mob << 4;
  356. // Abort MOB and set length fields
  357. CANCDMOB = frame->len;
  358. // Check for ID type
  359. if (frame->ext)
  360. {
  361. CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
  362. CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
  363. CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
  364. CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
  365. CANCDMOB |= _BV(IDE);
  366. }
  367. else
  368. {
  369. CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
  370. CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
  371. CANIDT3 = 0;
  372. CANIDT4 = 0;
  373. }
  374. if (frame->rtr)
  375. CANIDT4 |= _BV(RTRTAG);
  376. for (j = 0; j < 8; j++)
  377. CANMSG = frame->byte[j];
  378. // Enable transmission
  379. CANCDMOB |= _BV(CONMOB0);
  380. return CAN_SUCCESS;
  381. }
  382. /*!
  383. * AtCan interrupt service routine
  384. */
  385. static void AtCanInterrupt(void *arg)
  386. {
  387. uint8_t savedCanPage;
  388. CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
  389. savedCanPage = CANPAGE; // Save the current CAN page
  390. ci->can_interrupts++;
  391. //
  392. // Check for MOb interrupt
  393. //
  394. if ((CANHPMOB & 0xF0) != 0xF0)
  395. {
  396. CANPAGE = CANHPMOB; // Switch page
  397. // RX interrupt ?
  398. if (bit_is_set(CANSTMOB, RXOK))
  399. {
  400. // Space in buffer ?
  401. if (canRxBuf.datalength < canRxBuf.size)
  402. {
  403. int8_t j;
  404. CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
  405. // Extended or standard ID?
  406. bufPtr->ext = bit_is_set(CANCDMOB, IDE);
  407. if (bufPtr->ext)
  408. {
  409. ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
  410. ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
  411. ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
  412. ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
  413. }
  414. else
  415. {
  416. ((uint8_t *) &(bufPtr->id))[3] = 0;
  417. ((uint8_t *) &(bufPtr->id))[2] = 0;
  418. ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
  419. ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
  420. }
  421. bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
  422. bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
  423. for (j = 0; j < 8; j++)
  424. bufPtr->byte[j] = CANMSG;
  425. // Increment buffer length
  426. canRxBuf.datalength++;
  427. NutEventPostFromIrq(&ci->can_rx_rdy);
  428. // Stat houskeeping
  429. ci->can_rx_frames++;
  430. }
  431. else
  432. {
  433. // Stat houskeeping
  434. ci->can_overruns++;
  435. }
  436. }
  437. // TX interrupt ?
  438. else if (bit_is_set(CANSTMOB, TXOK))
  439. {
  440. NutEventPostFromIrq(&ci->can_tx_rdy);
  441. ci->can_tx_frames++;
  442. }
  443. // Error interrupts ?
  444. else
  445. {
  446. // Stat houskeeping
  447. ci->can_errors++;
  448. }
  449. //
  450. // Acknowledge all MOB interrupts and manage MObs
  451. //
  452. CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) |
  453. _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
  454. if (bit_is_set(CANCDMOB, CONMOB1))
  455. // Re-enable MOb for reception by re-writing CONMOB1 bit
  456. CANCDMOB |= _BV(CONMOB1);
  457. else
  458. // Re-claim MOb as send buffer
  459. CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
  460. }
  461. else
  462. {
  463. // Acknowledge general CAN interrupt
  464. CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
  465. // Stat houskeeping
  466. ci->can_errors++;
  467. }
  468. CANPAGE = savedCanPage; // Restore CAN page register
  469. }
  470. /*****************************************************************************
  471. * Function definitions
  472. *****************************************************************************/
  473. /*!
  474. * Checks if data is available in input buffer
  475. *
  476. * \param dev Pointer to the device structure
  477. * \return Number of frames available
  478. */
  479. uint8_t AtCanRxAvail(NUTDEVICE * dev)
  480. {
  481. return canRxBuf.datalength;
  482. }
  483. /*!
  484. * Checks if there's still space in output buffer
  485. *
  486. * \param dev Pointer to the device structure
  487. * \return 1 if space is available
  488. */
  489. uint8_t AtCanTxFree(NUTDEVICE * dev)
  490. {
  491. return (AtCanGetFreeMob() >= 0);
  492. }
  493. /*!
  494. * Write a frame from to output buffer
  495. *
  496. * This function writes a frame to the output buffer. If the output buffer
  497. * is full the function will block until frames are send.
  498. *
  499. * \param dev Pointer to the device structure
  500. * \param frame Pointer to the receive frame
  501. */
  502. void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
  503. {
  504. CANINFO * ci = (CANINFO *) dev->dev_dcb;
  505. while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
  506. {
  507. NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
  508. };
  509. }
  510. /*!
  511. * Reads a frame from input buffer
  512. *
  513. * This function reads a frame from the input buffer. If the input buffer
  514. * is empty the function will block unitl new frames are received,
  515. * or the timeout is reached.
  516. *
  517. * \param dev Pointer to the device structure
  518. * \param frame Pointer to the receive frame
  519. * \return 1 if timeout, 0 otherwise
  520. */
  521. uint8_t AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
  522. {
  523. CANINFO * ci = (CANINFO *) dev->dev_dcb;
  524. while (canRxBuf.datalength == 0)
  525. {
  526. uint32_t timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
  527. if (NutEventWait(&ci->can_rx_rdy, timeout))
  528. return 1;
  529. }
  530. NutEnterCritical();
  531. // Get the first frame from buffer
  532. *frame = canRxBuf.dataptr[canRxBuf.dataindex];
  533. // Move index down and decrement length
  534. canRxBuf.dataindex++;
  535. if (canRxBuf.dataindex >= canRxBuf.size)
  536. canRxBuf.dataindex %= canRxBuf.size;
  537. canRxBuf.datalength--;
  538. NutExitCritical();
  539. return 0;
  540. }
  541. /*!
  542. * Sets the acceptance code
  543. *
  544. * \param dev Pointer to the device structure
  545. * \param ac 4 byte char array with the acceptance code
  546. */
  547. void AtCanSetAccCode(NUTDEVICE * dev, uint8_t * ac)
  548. {
  549. memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
  550. AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt TODO: Implement it!
  551. }
  552. /*!
  553. * Sets the acceptance mask
  554. *
  555. * \param dev Pointer to the device structure
  556. * \param am 4 byte char array with the acceptance mask
  557. */
  558. void AtCanSetAccMask(NUTDEVICE * dev, uint8_t * am)
  559. {
  560. memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
  561. AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt TODO: Implement it!
  562. }
  563. /*!
  564. * Sets the CAN baud rate
  565. *
  566. * \param dev Pointer to the device structure
  567. * \param baudrate Baud rate (One of the defined baud rates. See AtCan.h)
  568. * \return 0 for success
  569. */
  570. uint8_t AtCanSetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
  571. {
  572. #if !defined(NUT_CPU_FREQ)
  573. return -1;
  574. #else
  575. switch (baudrate)
  576. {
  577. #if NUT_CPU_FREQ != 8000000
  578. case CAN_SPEED_10K:
  579. CANBT1 = CAN_BT1_10K;
  580. CANBT2 = CAN_BT2_10K;
  581. CANBT3 = CAN_BT3_10K;
  582. break;
  583. case CAN_SPEED_20K:
  584. CANBT1 = CAN_BT1_20K;
  585. CANBT2 = CAN_BT2_20K;
  586. CANBT3 = CAN_BT3_20K;
  587. break;
  588. case CAN_SPEED_50K:
  589. CANBT1 = CAN_BT1_50K;
  590. CANBT2 = CAN_BT2_50K;
  591. CANBT3 = CAN_BT3_50K;
  592. break;
  593. #endif
  594. case CAN_SPEED_100K:
  595. CANBT1 = CAN_BT1_100K;
  596. CANBT2 = CAN_BT2_100K;
  597. CANBT3 = CAN_BT3_100K;
  598. break;
  599. case CAN_SPEED_125K:
  600. CANBT1 = CAN_BT1_125K;
  601. CANBT2 = CAN_BT2_125K;
  602. CANBT3 = CAN_BT3_125K;
  603. break;
  604. case CAN_SPEED_250K:
  605. CANBT1 = CAN_BT1_250K;
  606. CANBT2 = CAN_BT2_250K;
  607. CANBT3 = CAN_BT3_250K;
  608. break;
  609. case CAN_SPEED_500K:
  610. CANBT1 = CAN_BT1_500K;
  611. CANBT2 = CAN_BT2_500K;
  612. CANBT3 = CAN_BT3_500K;
  613. break;
  614. #if NUT_CPU_FREQ != 8000000
  615. case CAN_SPEED_800K:
  616. CANBT1 = CAN_BT1_800K;
  617. CANBT2 = CAN_BT2_800K;
  618. CANBT3 = CAN_BT3_800K;
  619. break;
  620. #endif
  621. case CAN_SPEED_1M:
  622. CANBT1 = CAN_BT1_1M;
  623. CANBT2 = CAN_BT2_1M;
  624. CANBT3 = CAN_BT3_1M;
  625. break;
  626. case CAN_SPEED_CUSTOM:
  627. // Do nothing, user sets baud rate directly but don't report an error
  628. break;
  629. default:
  630. return 1;
  631. }
  632. ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
  633. return 0;
  634. #endif
  635. }
  636. /*!
  637. * Initialize CAN interface.
  638. *
  639. * Applications typically do not use this function, but
  640. * call NutRegisterDevice().
  641. *
  642. * \param dev Identifies the device to initialize. The
  643. * structure must be properly set.
  644. * \return 0 for successful initialisation or -1 in case init failed
  645. */
  646. int AtCanInit(NUTDEVICE * dev)
  647. {
  648. int8_t mob, i;
  649. #if !defined( NUT_CPU_FREQ)
  650. return -1;
  651. #endif
  652. memset(dev->dev_dcb, 0, sizeof(CANINFO));
  653. // Init receive buffer
  654. canRxBuf.dataptr = NutHeapAlloc(ATCAN_RX_BUF_SIZE * sizeof(CANFRAME));
  655. if (canRxBuf.dataptr == 0)
  656. return -1;
  657. canRxBuf.size = ATCAN_RX_BUF_SIZE;
  658. canRxBuf.dataindex = 0;
  659. canRxBuf.datalength = 0;
  660. // Disable AT90CAN128 CAN system
  661. CANGCON &= ~_BV(ENASTB);
  662. loop_until_bit_is_clear(CANGSTA, ENFG);
  663. // Clear all MObs
  664. for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
  665. {
  666. CANPAGE = mob << 4;
  667. CANSTMOB = 0; // Clear status register
  668. CANCDMOB = 0; // Clear control register
  669. CANHPMOB = 0; // Clear HP flags
  670. // Clear identifier tag
  671. CANIDT1 = 0;
  672. CANIDT2 = 0;
  673. CANIDT3 = 0;
  674. CANIDT4 = 0;
  675. // Clear identifier mask
  676. CANIDM1 = 0;
  677. CANIDM2 = 0;
  678. CANIDM3 = 0;
  679. CANIDM4 = 0;
  680. for (i = 0; i < 8; i++)
  681. {
  682. CANMSG = 0;
  683. }
  684. }
  685. // Set baudrate
  686. AtCanSetBaudrate(dev, ifc_atcan.can_baudrate); // Errors silently ingnored here
  687. // Install IRQ handler
  688. if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
  689. return -1;
  690. // Enable all interrupts
  691. CANIE1 = 0x7F;
  692. CANIE2 = 0xFF;
  693. CANGIE = 0xFE; // All interrupts except OVRTIM
  694. // Enable receiving MOBs
  695. AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
  696. // Enable AT90CAN128 CAN system
  697. CANGCON |= _BV(ENASTB);
  698. loop_until_bit_is_set(CANGSTA, ENFG);
  699. return 0;
  700. }
  701. /*!
  702. * Interface information structure.
  703. *
  704. * This structure stores some interface parameters like bit rate,
  705. * acceptance mask, acceptance code and callback handlers.
  706. */
  707. IFCAN ifc_atcan = {
  708. CAN_IF_2B, /*!< \brief Interface type. */
  709. CAN_SPEED_125K, /*!< \brief Baudrate of device. */
  710. {0xFF, 0xFF, 0xFF, 0xFF}, /*!< \brief Acceptance mask */
  711. {0x00, 0x00, 0x00, 0x00}, /*!< \brief Acceptance code */
  712. NUT_WAIT_INFINITE, /*!< \brief Receive time-out */
  713. AtCanRxAvail, /*!< \brief Data in RxBuffer available? */
  714. AtCanTxFree, /*!< \brief TxBuffer free? */
  715. AtCanInput, /*!< \brief CAN Input routine */
  716. AtCanOutput, /*!< \brief CAN Output routine */
  717. AtCanSetAccCode, /*!< \brief Set acceptance code */
  718. AtCanSetAccMask, /*!< \brief Set acceptance mask */
  719. AtCanSetBaudrate, /*!< \brief Set baudrate */
  720. };
  721. /*!
  722. * Device information structure.
  723. *
  724. * Applications must pass this structure to NutRegisterDevice()
  725. * to bind this CAN device driver to the Nut/OS kernel.
  726. */
  727. NUTDEVICE devAtCan = {
  728. 0, /*!< Pointer to next device. */
  729. {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0}, /*!< Unique device name. */
  730. IFTYP_CAN, /*!< Type of device. */
  731. 0, /*!< Base address. */
  732. 0, /*!< First interrupt number. */
  733. &ifc_atcan, /*!< Interface control block. */
  734. &dcb_atcan, /*!< Driver control block. */
  735. AtCanInit, /*!< Driver initialization routine. */
  736. 0, /*!< Driver specific control function. */
  737. 0, /*!< Read from device. */
  738. 0, /*!< Write to device. */
  739. 0, /*!< Write from program space data to device. */
  740. 0, /*!< Open a device or file. */
  741. 0, /*!< Close a device or file. */
  742. 0, /*!< Request file size. */
  743. 0, /*!< Select function, optional, not yet implemented */
  744. };
  745. #else
  746. static void keep_icc_happy(void)
  747. {
  748. }
  749. #endif
  750. /*@}*/