PageRenderTime 36ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/can.c

https://github.com/derkling/DerkGPS
C | 485 lines | 295 code | 100 blank | 90 comment | 50 complexity | 01364b52d14ef70b761c0a6c9d7cc29a MD5 | raw file
  1. /*
  2. odo.c
  3. Copyright (c) 2008-2009 Patrick Bellasi
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General
  13. Public License along with this library; if not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  15. Boston, MA 02111-1307 USA
  16. */
  17. #include "can.h"
  18. /*_____ C O N S T A N T E S - D E F I N I T I O N ___________________________*/
  19. // CAN Baud Rate Settings for 8MHz
  20. #if 1
  21. #if CAN_BITRATE == 1000
  22. # warning Configuring CAN bitrate @ 1000KB
  23. # define CAN_CANBT1 0x00
  24. # define CAN_CANBT2 0x04
  25. # define CAN_CANBT3 0x13
  26. #elif CAN_BITRATE == 500
  27. # warning Configuring CAN bitrate @ 500KB
  28. # define CAN_CANBT1 0x02
  29. # define CAN_CANBT2 0x04
  30. # define CAN_CANBT3 0x13
  31. #elif CAN_BITRATE == 250
  32. # warning Configuring CAN bitrate @ 250KB
  33. # define CAN_CANBT1 0x06
  34. # define CAN_CANBT2 0x04
  35. # define CAN_CANBT3 0x13
  36. #elif CAN_BITRATE == 200
  37. # warning Configuring CAN bitrate @ 200KB
  38. # define CAN_CANBT1 0x08
  39. # define CAN_CANBT2 0x04
  40. # define CAN_CANBT3 0x13
  41. #elif CAN_BITRATE == 125
  42. # warning Configuring CAN bitrate @ 125KB
  43. # define CAN_CANBT1 0x0E
  44. # define CAN_CANBT2 0x04
  45. # define CAN_CANBT3 0x13
  46. #elif CAN_BITRATE == 100
  47. # warning Configuring CAN bitrate @ 100KB
  48. # define CAN_CANBT1 0x08
  49. # define CAN_CANBT2 0x0C
  50. # define CAN_CANBT3 0x37
  51. #endif
  52. #endif
  53. #if 0
  54. #define CAN_CANBT1 0x06
  55. #define CAN_CANBT2 0x00
  56. #define CAN_CANBT3 0x05
  57. #endif
  58. #define FLAG_TX 0x01
  59. #define FLAG_RX 0x02
  60. #define FLAG_OT 0x04
  61. /*_____ M A C R O S - DE C L A R A T I O N ___________________________________*/
  62. #define CAN_SET_CHANNEL(mob) (CANPAGE = (mob << MOBNB0))
  63. #define CAN_GET_CHANNEL (CANPAGE >> MOBNB0)
  64. // Configuration of Extended Identifier
  65. #define CAN_SET_EXT_ID_28_21(id) (((*((unsigned char *)(&id)+3))<<3)+((*((unsigned char *)(&id)+2))>>5))
  66. #define CAN_SET_EXT_ID_20_13(id) (((*((unsigned char *)(&id)+2))<<3)+((*((unsigned char *)(&id)+1))>>5))
  67. #define CAN_SET_EXT_ID_12_5(id) (((*((unsigned char *)(&id)+1))<<3)+((* (unsigned char *)(&id) )>>5))
  68. #define CAN_SET_EXT_ID_4_0(id) ((* (unsigned char *)(&id) )<<3)
  69. #define CAN_SET_EXT_MSK_28_21(mask) CAN_SET_EXT_ID_28_21(mask)
  70. #define CAN_SET_EXT_MSK_20_13(mask) CAN_SET_EXT_ID_20_13(mask)
  71. #define CAN_SET_EXT_MSK_12_5(mask) CAN_SET_EXT_ID_12_5(mask)
  72. #define CAN_SET_EXT_MSK_4_0(mask) CAN_SET_EXT_ID_4_0(mask)
  73. // Configuration of Standard Identifier
  74. #define CAN_SET_STD_ID_10_3(id) (((*((unsigned char *)(&id)+1))<<5)+((*(unsigned char *)(&id))>>3))
  75. #define CAN_SET_STD_ID_2_0(id) ((*(unsigned char *)(&id))<<5)
  76. #define CAN_SET_STD_MSK_10_3(mask) CAN_SET_STD_ID_10_3(mask)
  77. #define CAN_SET_STD_MSK_2_0(mask) CAN_SET_STD_ID_2_0(mask)
  78. #define CAN_DISABLE_CH ( CANCDMOB &= ~(0x3 << CONMOB0) )
  79. #define CAN_ENABLE_CH_TX { CAN_DISABLE_CH ; CANCDMOB |= (0x1 << CONMOB0); }
  80. #define CAN_ENABLE_CH_RX { CAN_DISABLE_CH ; CANCDMOB |= (0x2 << CONMOB0); }
  81. #define CAN_ENABLE_CH_BUFF { CAN_DISABLE_CH ; CANCDMOB |= (0x3 << CONMOB0); }
  82. /*_____ L O C A L E S ______________________________________________________*/
  83. unsigned int canOvrTCount = 0; //
  84. unsigned int canDlcwCount = 0; //
  85. unsigned int canTxCount = 0; //
  86. unsigned int canRxCount = 0; //
  87. unsigned int canBxCount = 0; // Frame Buffer Receive Interrupt
  88. unsigned int canMObErrCount = 0; // CAN General error count
  89. unsigned int canAckMObErrCount = 0; // Acknowledgment Error
  90. unsigned int canForMObErrCount = 0; // Form Error
  91. unsigned int canCrcMObErrCount = 0; // CRC Error
  92. unsigned int canStuMObErrCount = 0; // Stuff Error
  93. unsigned int canBitMObErrCount = 0; // Bit Error (Only in Transmission)
  94. unsigned int canGenErrCount = 0; // CAN General error count
  95. unsigned int canAckGenErrCount = 0; // Acknowledgment Error
  96. unsigned int canForGenErrCount = 0; // Form Error
  97. unsigned int canCrcGenErrCount = 0; // CRC Error
  98. unsigned int canStuGenErrCount = 0; // Stuff Error
  99. unsigned int canBusOffCount = 0; // Bus Off Interrupt Flag
  100. unsigned int numMObTx; // MOb number with TxOK
  101. unsigned int numMObRx; // MOb number with RxOK
  102. // Status flasg
  103. volatile unsigned char canFlags = 0x00;
  104. char canDebugBuff[32];
  105. static void canResetAllMailbox (void) {
  106. unsigned char ch, data;
  107. for (ch = 0; ch < CAN_CHANNELS; ch++) {
  108. CANPAGE = (ch << MOBNB0);
  109. CANSTMOB = 0x00;
  110. CANCDMOB = 0x00;
  111. CANIDT4 = 0x00;
  112. CANIDT3 = 0x00;
  113. CANIDT2 = 0x00;
  114. CANIDT1 = 0x00;
  115. CANIDM4 = 0x00;
  116. CANIDM3 = 0x00;
  117. CANIDM2 = 0x00;
  118. CANIDM1 = 0x00;
  119. for (data = 0; data < CAN_MAX_DATA; data++) {
  120. // This pointer will auto-increment if auto-incrementation is used
  121. CANMSG = 0x00;
  122. }
  123. }
  124. }
  125. // NOTE This function MUST be called with interrupt disabled
  126. void initCan(void) {
  127. // Resetting CAN controller
  128. sbi(CANGCON, ENASTB);
  129. // Resetting all mailboxes
  130. canResetAllMailbox();
  131. // Configuring CAN prescaler
  132. // Tclk_CANTIM = Tclk_IO x 8 x (CANTCON [7:0] + 1)
  133. CANTCON = 0xFF;
  134. // Configuring bitrates
  135. CANBT1 = CAN_CANBT1;
  136. CANBT2 = CAN_CANBT2;
  137. CANBT3 = CAN_CANBT3;
  138. // Enable all interrupts
  139. CANGIE=0xFF; // with OVRTIM
  140. // CANGIE=0xFE; // without OVRTIM
  141. // Enable all MOb's interrupts
  142. CANIE2=0xFF;
  143. CANIE1=0xFF;
  144. // Enable CAN Controller
  145. sbi(CANGCON, ENASTB);
  146. }
  147. void canConfChannel_Rx(canChannelConf_t * conf) {
  148. CAN_SET_CHANNEL(conf->ch);
  149. // Resetting CAN MOb Status Register
  150. CANSTMOB = 0x00;
  151. // Resetting CAN MOb Control and DLC Register to default configuration
  152. CANCDMOB = 0x00;
  153. if ( conf->opts & CONF_IDE ) {
  154. // 29-bit CAN Identifier Tag Registers
  155. CANIDT1 = CAN_SET_EXT_ID_28_21 (conf->filter.ext);
  156. CANIDT2 = CAN_SET_EXT_ID_20_13 (conf->filter.ext);
  157. CANIDT3 = CAN_SET_EXT_ID_12_5 (conf->filter.ext);
  158. CANIDT4 = CAN_SET_EXT_ID_4_0 (conf->filter.ext);
  159. // RTRTAG, RB1TAG and RB0TAG cleared
  160. // 29-bit CAN Identifier Mask Registers
  161. CANIDM1 = CAN_SET_EXT_MSK_28_21 (conf->mask.ext);
  162. CANIDM2 = CAN_SET_EXT_MSK_20_13 (conf->mask.ext);
  163. CANIDM3 = CAN_SET_EXT_MSK_12_5 (conf->mask.ext);
  164. CANIDM4 = CAN_SET_EXT_MSK_4_0 (conf->mask.ext);
  165. // RTRMSK and IDEMSK cleared
  166. // Enable IDentifier Extension" on CAN MOb Control and DLC Register
  167. sbi(CANCDMOB, IDE);
  168. } else {
  169. // 11-bit identifier tag
  170. CANIDT1 = CAN_SET_STD_ID_10_3 (conf->filter.std);
  171. CANIDT2 = CAN_SET_STD_ID_2_0 (conf->filter.std);
  172. // Clear RTRTAG, RB1TAG and RB0TAG
  173. CANIDT4 = 0x00;
  174. // 11-bit identifier mask
  175. CANIDM1 = CAN_SET_STD_MSK_10_3 (conf->mask.std);
  176. CANIDM2 = CAN_SET_STD_MSK_2_0 (conf->mask.std);
  177. // Clear RTRMSK and IDEMSK
  178. CANIDM4 = 0x00;
  179. // IDE=0 in CANCDMOB already done at the beginning
  180. }
  181. CANCDMOB |= ( CAN_MAX_DATA && 0X0F) ;
  182. // If DLC of received message < NB_DATA_MAX, DLCW will be set
  183. if ( conf->opts & CONF_RTR ) {
  184. // Enabling "Remote Transmission Request Tag"
  185. sbi(CANIDT4, RTRTAG);
  186. }
  187. if ( conf->opts & CONF_MSK_RTR ) {
  188. // Enable "Remote Transmission Request Mask" (bit-comparision)
  189. sbi(CANIDM4, RTRMSK);
  190. }
  191. if ( conf->opts & CONF_MSK_IDE ) {
  192. // Enable "Identifier Extension Mask" (bit-comparision)
  193. sbi(CANIDM4, IDEMSK);
  194. }
  195. // Enable reception on this channel
  196. if ( conf->opts & CONF_BUFFER ) {
  197. CAN_ENABLE_CH_BUFF;
  198. } else {
  199. CAN_ENABLE_CH_RX;
  200. }
  201. }
  202. void canReadMsg (canMsg_t * msg, unsigned char nextConf) {
  203. unsigned char * pData = 0;
  204. unsigned char dlc2read = 0;
  205. unsigned char rxConf = CANCDMOB;
  206. // Save control register
  207. msg->ctrl = rxConf;
  208. if ( rxConf & CONF_IDE ) {
  209. msg->id.tab[3] = (CANIDT1 >> 3);
  210. msg->id.tab[2] = (CANIDT1 << 5) | (CANIDT2 >> 3);
  211. msg->id.tab[1] = (CANIDT2 << 5) | (CANIDT3 >> 3);
  212. msg->id.tab[0] = (CANIDT3 << 5) | (CANIDT4 >> 3);
  213. } else {
  214. msg->id.std = (CANIDT1 << 3) | (CANIDT2 >> 5);
  215. }
  216. // Reading msg data
  217. pData = msg->pData;
  218. dlc2read = (rxConf & 0x0F);
  219. for ( ; dlc2read!=0; dlc2read--) {
  220. *pData++ = CANMSG;
  221. }
  222. //--- Reconfiguring this channel
  223. if ( nextConf == CONF_CH_DISABLE ) {
  224. CAN_DISABLE_CH;
  225. } else if ( nextConf == CONF_CH_RX_ENABLE ) {
  226. CAN_ENABLE_CH_RX;
  227. } else {
  228. CAN_ENABLE_CH_BUFF;
  229. }
  230. }
  231. unsigned char canFindFirstChIt (void) {
  232. unsigned char chNum;
  233. chNum = (CANHPMOB >> HPMOB0);
  234. return ( (chNum <= CAN_LAST_CHANNEL) ? chNum : NO_CHANNEL );
  235. }
  236. static void readOnMOb0 (void) {
  237. canChannelConf_t conf;
  238. canMsg_t canRxMsg;
  239. unsigned char data[CAN_MAX_DATA];
  240. // Configure standard reception on MOb 0
  241. #if 0
  242. conf.ch = CHANNEL_0;
  243. // conf.filter.ext = 0UL;
  244. // conf.mask.ext = 0UL;
  245. conf.filter.std = 0xF003;
  246. conf.mask.std = 0xFFFF;
  247. // conf.opts = 0x00 | CONF_NOIDE | CONF_NORTR | CONF_DLC_8;
  248. conf.opts = 0x00 | CONF_NOIDE | CONF_MSK_IDE | CONF_NORTR | CONF_DLC_8;
  249. canConfChannel_Rx(&conf);
  250. #endif
  251. // Configure extended reception on MOb 1
  252. conf.ch = CHANNEL_1;
  253. // conf.filter.ext = 0UL;
  254. // conf.mask.ext = 0UL;
  255. conf.filter.ext = 0xF00300;
  256. conf.mask.ext = 0xFFFFFF;
  257. conf.opts = 0x00 | CONF_IDE | CONF_MSK_IDE | CONF_NORTR | CONF_DLC_8;
  258. canConfChannel_Rx(&conf);
  259. conf.ch = CHANNEL_2;
  260. // conf.filter.ext = 0UL;
  261. // conf.mask.ext = 0UL;
  262. conf.filter.ext = 0xF00400;
  263. conf.mask.ext = 0xFFFFFF;
  264. conf.opts = 0x00 | CONF_IDE | CONF_MSK_IDE | CONF_NORTR | CONF_DLC_8;
  265. canConfChannel_Rx(&conf);
  266. digitalWrite(led1, HIGH);
  267. while ( canFlags == 0x00 ) {
  268. /* Waiting for a CAN Message */;
  269. }
  270. digitalWrite(led1, LOW);
  271. // Get MOb number of the incomming message
  272. CAN_SET_CHANNEL(numMObRx);
  273. // Read incomming message
  274. canRxMsg.pData = data;
  275. canReadMsg(&canRxMsg, CONF_CH_DISABLE);
  276. //----- Echo message on UART
  277. // Print ID
  278. if ( canRxMsg.ctrl & CONF_IDE ) {
  279. snprintf(canDebugBuff, 32, "Ch-%d %08lX ",
  280. numMObRx, canRxMsg.id.ext);
  281. } else {
  282. snprintf(canDebugBuff, 32, "Ch-%d %04X ",
  283. numMObRx, canRxMsg.id.std);
  284. }
  285. Serial_printStr(canDebugBuff);
  286. // Print DATA
  287. snprintf(canDebugBuff, 32, "%02X %02x %02x %02x %02X %02x %02x %02x",
  288. canRxMsg.pData[7],
  289. canRxMsg.pData[6],
  290. canRxMsg.pData[5],
  291. canRxMsg.pData[4],
  292. canRxMsg.pData[3],
  293. canRxMsg.pData[2],
  294. canRxMsg.pData[1],
  295. canRxMsg.pData[0]
  296. );
  297. Serial_printLine(canDebugBuff);
  298. // Resetting flag
  299. canFlags = 0x00;
  300. }
  301. void canSniff ( void ) {
  302. while ( 1 ) {
  303. readOnMOb0();
  304. }
  305. }
  306. /*_____ INTERRUPT HANDLERS____________________________________________________*/
  307. SIGNAL(SIG_CAN_INTERRUPT1) {
  308. unsigned char ch;
  309. unsigned char savedCanPage;
  310. unsigned char error;
  311. // Save the current page
  312. savedCanPage = CANPAGE;
  313. digitalSwitch(led3);
  314. ch = canFindFirstChIt();
  315. if ( ch != NO_CHANNEL ) {
  316. // MOB Interrupts
  317. CAN_SET_CHANNEL(ch);
  318. // snprintf(canDebugBuff, 32, "MObInt: %02X Ch-%d %d", CANSTMOB, ch, (CANCDMOB & 0x0F) );
  319. // Serial_printLine(canDebugBuff);
  320. if ( tbi(CANSTMOB, DLCW) ) {
  321. canDlcwCount++;
  322. }
  323. if ( tbi(CANSTMOB, RXOK) ) {
  324. canRxCount++;
  325. canFlags = FLAG_RX;
  326. numMObRx = ch;
  327. CAN_DISABLE_CH;
  328. digitalSwitch(led2);
  329. }
  330. if ( tbi(CANSTMOB, TXOK) ) {
  331. canTxCount++;
  332. canFlags = FLAG_TX;
  333. numMObTx = ch;
  334. CAN_DISABLE_CH;
  335. }
  336. error = CANSTMOB & 0x1F;
  337. if ( error ) {
  338. canMObErrCount++;
  339. if ( error & 0x01 ) canAckMObErrCount++;
  340. if ( error & 0x02 ) canForMObErrCount++;
  341. if ( error & 0x04 ) canCrcMObErrCount++;
  342. if ( error & 0x08 ) canStuMObErrCount++;
  343. if ( error & 0x10 ) canBitMObErrCount++;
  344. }
  345. // Reset all MOb Int, Keep WDLC
  346. CANSTMOB = CANSTMOB & 0x80;
  347. } else {
  348. // No Channel matchs with the interrupt => General IT
  349. // snprintf(canDebugBuff, 32, "GenErr: %02X", CANGIT);
  350. // Serial_printLine(canDebugBuff);
  351. // Reset Int_flag setting it "1"
  352. error = CANGIT & 0x1F;
  353. if (error != 0x00) {
  354. canGenErrCount++;
  355. if ( error & 0x01 ) canAckGenErrCount++;
  356. if ( error & 0x02 ) canForGenErrCount++;
  357. if ( error & 0x04 ) canCrcGenErrCount++;
  358. if ( error & 0x08 ) canStuGenErrCount++;
  359. // Reset Int_ERR_GEN done (global) in IT_Handler
  360. }
  361. if ( tbi(CANGIT,BXOK) ) {
  362. canBxCount++;
  363. // Reset Int_Buffer_OK done (global) in IT_Handler
  364. }
  365. if ( tbi(CANGIT,BOFFIT)) {
  366. canBusOffCount++;
  367. Serial_printLine("\r\n CAN Error Bus Off ");
  368. // Reset Int_Bus_Off done in (global) IT_Handler
  369. }
  370. // New for AVR
  371. CANGIT = 0x5F;
  372. }
  373. // Restore the previous page
  374. CANPAGE = savedCanPage;
  375. }
  376. SIGNAL(SIG_CAN_OVERFLOW1) {
  377. canOvrTCount++;
  378. // PORTA=(unsigned char)(canOvrTCount);
  379. canFlags &= (0x01 << FLAG_OT);
  380. }