PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FlexCAN.cpp 38KB

3 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643
  1. // -------------------------------------------------------------
  2. // a simple Arduino Teensy 3.1/3.2/3.5/3.6 CAN driver
  3. // by teachop
  4. // dual CAN support for MK66FX1M0 and updates for MK64FX512 by Pawelsky
  5. // Interrupt driven Rx/Tx with buffers, object oriented callbacks by Collin Kidder
  6. // RTR related code by H4nky84
  7. // Statistics collection, timestamp and code clean-up my mdapoz
  8. //
  9. #include "FlexCAN.h"
  10. #include "kinetis_flexcan.h"
  11. #define FLEXCANb_MCR(b) (*(vuint32_t*)(b))
  12. #define FLEXCANb_CTRL1(b) (*(vuint32_t*)(b+4))
  13. #define FLEXCANb_RXMGMASK(b) (*(vuint32_t*)(b+0x10))
  14. #define FLEXCANb_IFLAG1(b) (*(vuint32_t*)(b+0x30))
  15. #define FLEXCANb_IMASK1(b) (*(vuint32_t*)(b+0x28))
  16. #define FLEXCANb_RXFGMASK(b) (*(vuint32_t*)(b+0x48))
  17. #define FLEXCANb_MBn_CS(b, n) (*(vuint32_t*)(b+0x80+n*0x10))
  18. #define FLEXCANb_MBn_ID(b, n) (*(vuint32_t*)(b+0x84+n*0x10))
  19. #define FLEXCANb_MBn_WORD0(b, n) (*(vuint32_t*)(b+0x88+n*0x10))
  20. #define FLEXCANb_MBn_WORD1(b, n) (*(vuint32_t*)(b+0x8C+n*0x10))
  21. #define FLEXCANb_IDFLT_TAB(b, n) (*(vuint32_t*)(b+0xE0+(n*4)))
  22. #define FLEXCANb_MB_MASK(b, n) (*(vuint32_t*)(b+0x880+(n*4)))
  23. #define FLEXCANb_ESR1(b) (*(vuint32_t*)(b+0x20))
  24. #if defined(__MK66FX1M0__)
  25. # define INCLUDE_FLEXCAN_CAN1
  26. #endif
  27. #undef INCLUDE_FLEXCAN_DEBUG
  28. #if defined(INCLUDE_FLEXCAN_DEBUG)
  29. # define dbg_print(fmt, args...) Serial.print (fmt , ## args)
  30. # define dbg_println(fmt, args...) Serial.println (fmt , ## args)
  31. #else
  32. # define dbg_print(fmt, args...)
  33. # define dbg_println(fmt, args...)
  34. #endif
  35. // Supported FlexCAN interfaces
  36. FlexCAN Can0 (0);
  37. #if defined(INCLUDE_FLEXCAN_CAN1)
  38. FlexCAN Can1 (1);
  39. #endif
  40. // default mask to apply to all mailboxes
  41. CAN_filter_t FlexCAN::defaultMask;
  42. // Some of these are complete guesses. Only really 8 and 16 have been validated.
  43. // You have been warned. But, there aren't too many options for some of these
  44. uint8_t bitTimingTable[21][3] = {
  45. // prop, seg1, seg2 (4 + prop + seg1 + seg2, seg2 must be at least 1)
  46. // No value can go over 7 here.
  47. {0,0,1}, //5
  48. {1,0,1}, //6
  49. {1,1,1}, //7
  50. {2,1,1}, //8
  51. {2,2,1}, //9
  52. {2,3,1}, //10
  53. {2,3,2}, //11
  54. {2,4,2}, //12
  55. {2,5,2}, //13
  56. {2,5,3}, //14
  57. {2,6,3}, //15
  58. {2,7,3}, //16
  59. {2,7,4}, //17
  60. {3,7,4}, //18
  61. {3,7,5}, //19
  62. {4,7,5}, //20
  63. {4,7,6}, //21
  64. {5,7,6}, //22
  65. {6,7,6}, //23
  66. {6,7,7}, //24
  67. {7,7,7}, //25
  68. };
  69. /*
  70. * \brief Initialize the FlexCAN driver class
  71. *
  72. * \param id - CAN bus interface selection
  73. *
  74. * \retval none
  75. *
  76. */
  77. FlexCAN::FlexCAN (uint8_t id)
  78. {
  79. uint32_t i;
  80. numTxMailboxes=2;
  81. flexcanBase = FLEXCAN0_BASE;
  82. #if defined (INCLUDE_FLEXCAN_CAN1)
  83. if (id > 0) {
  84. flexcanBase = FLEXCAN1_BASE;
  85. }
  86. #else
  87. (void)id; // Just for avoid warning.
  88. #endif
  89. #if defined(__MK20DX256__)
  90. IrqMessage=IRQ_CAN_MESSAGE;
  91. #elif defined(__MK64FX512__)
  92. IrqMessage=IRQ_CAN0_MESSAGE;
  93. #elif defined(__MK66FX1M0__)
  94. if (flexcanBase == FLEXCAN0_BASE) {
  95. IrqMessage=IRQ_CAN0_MESSAGE;
  96. } else {
  97. IrqMessage=IRQ_CAN1_MESSAGE;
  98. }
  99. #endif
  100. // Default mask is allow everything
  101. defaultMask.flags.remote = 0;
  102. defaultMask.flags.extended = 0;
  103. defaultMask.id = 0;
  104. sizeRxBuffer=SIZE_RX_BUFFER;
  105. sizeTxBuffer=SIZE_TX_BUFFER;
  106. tx_buffer=0;
  107. rx_buffer=0;
  108. // Initialize all message box spesific ring buffers to 0.
  109. for (i=0; i<getNumMailBoxes(); i++) {
  110. txRings[i]=0;
  111. }
  112. // clear any listeners for received packets
  113. for (i = 0; i < SIZE_LISTENERS; i++) {
  114. listener[i] = NULL;
  115. }
  116. // clear statistics counts
  117. clearStats ();
  118. }
  119. /*
  120. * \brief Bring the hardware into freeze which drops it off the CAN bus
  121. *
  122. * \param none
  123. *
  124. * \retval none
  125. *
  126. */
  127. void FlexCAN::end (void)
  128. {
  129. // enter freeze mode
  130. halt();
  131. FLEXCANb_MCR (flexcanBase) |= (FLEXCAN_MCR_HALT);
  132. while (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK))
  133. ;
  134. }
  135. /*
  136. * \brief Initializes the CAN bus to the given settings
  137. *
  138. * \param baud - Set the baud rate of the bus. Only certain values are valid 50000, 100000, 125000, 250000, 500000, 1000000
  139. * \param mask - A default mask to use for all mailbox masks. Optional.
  140. * \param txAlt - 1 to enable alternate Tx pin (where available)
  141. * \param rxAlt - 1 to enable alternate Rx pin (where available)
  142. *
  143. * \retval none
  144. *
  145. */
  146. void FlexCAN::begin (uint32_t baud, const CAN_filter_t &mask, uint8_t txAlt, uint8_t rxAlt)
  147. {
  148. initializeBuffers();
  149. // set up the pins
  150. setPins(txAlt,rxAlt);
  151. // select clock source 16MHz xtal
  152. OSC0_CR |= OSC_ERCLKEN;
  153. if (flexcanBase == FLEXCAN0_BASE) {
  154. SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0;
  155. #if defined(INCLUDE_FLEXCAN_CAN1)
  156. } else if (flexcanBase == FLEXCAN1_BASE) {
  157. SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1;
  158. #endif
  159. }
  160. FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_CLK_SRC;
  161. // enable CAN
  162. FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_FRZ;
  163. FLEXCANb_MCR (flexcanBase) &= ~FLEXCAN_MCR_MDIS;
  164. while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_LPM_ACK)
  165. ;
  166. // soft reset
  167. softReset();
  168. // wait for freeze ack
  169. waitFrozen();
  170. // disable self-reception
  171. FLEXCANb_MCR (flexcanBase) |= FLEXCAN_MCR_SRX_DIS;
  172. setBaudRate(baud);
  173. // enable per-mailbox filtering
  174. FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_IRMQ;
  175. // now have to set mask and filter for all the Rx mailboxes or they won't receive anything by default.
  176. for (uint8_t c = 0; c < getNumRxBoxes(); c++) {
  177. setMask (0, c);
  178. setFilter (mask, c);
  179. }
  180. // start the CAN
  181. exitHalt();
  182. waitReady();
  183. setNumTxBoxes (numTxMailboxes);
  184. NVIC_SET_PRIORITY (IrqMessage, IRQ_PRIORITY);
  185. NVIC_ENABLE_IRQ (IrqMessage);
  186. // enable interrupt masks for all 16 mailboxes
  187. FLEXCANb_IMASK1 (flexcanBase) = 0xFFFF;
  188. dbg_println ("CAN initialized properly");
  189. }
  190. /*
  191. * \brief
  192. *
  193. * \param
  194. *
  195. * \retval None.
  196. *
  197. */
  198. void FlexCAN::setMailBoxTxBufferSize(uint8_t mbox, uint16_t size) {
  199. if ( mbox>=getNumMailBoxes() || txRings[mbox]!=0 ) return;
  200. volatile CAN_message_t *buf=new CAN_message_t[size];
  201. txRings[mbox]=new ringbuffer_t;
  202. initRingBuffer (*(txRings[mbox]), buf, size);
  203. }
  204. /*
  205. * \brief Initializes dynamically sized buffers.
  206. *
  207. * \param mask - default filter mask
  208. *
  209. * \retval None.
  210. *
  211. */
  212. void FlexCAN::initializeBuffers() {
  213. if ( isInitialized() ) return;
  214. // set up the transmit and receive ring buffers
  215. if (tx_buffer==0) tx_buffer=new CAN_message_t[sizeTxBuffer];
  216. if (rx_buffer==0) rx_buffer=new CAN_message_t[sizeRxBuffer];
  217. initRingBuffer (txRing, tx_buffer, sizeTxBuffer);
  218. initRingBuffer (rxRing, rx_buffer, sizeRxBuffer);
  219. }
  220. /*
  221. * \brief Initializes CAN pin definitions.
  222. *
  223. * \param txAlt - Atrenate tx pin
  224. * \param rxAlt - Alternate rx pin
  225. *
  226. * \retval None.
  227. *
  228. */
  229. void FlexCAN::setPins(uint8_t txAlt, uint8_t rxAlt) {
  230. if (flexcanBase == FLEXCAN0_BASE) {
  231. dbg_println ("Begin setup of CAN0");
  232. #if defined(__MK66FX1M0__) || defined(__MK64FX512__)
  233. // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default)
  234. // 29=PTB18=CAN0_TX, 30=PTB19=CAN0_RX (alternative)
  235. if (txAlt == 1)
  236. CORE_PIN29_CONFIG = PORT_PCR_MUX(2);
  237. else
  238. CORE_PIN3_CONFIG = PORT_PCR_MUX(2);
  239. // | PORT_PCR_PE | PORT_PCR_PS;
  240. if (rxAlt == 1)
  241. CORE_PIN30_CONFIG = PORT_PCR_MUX(2);
  242. else
  243. CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
  244. #else
  245. // 3=PTA12=CAN0_TX, 4=PTA13=CAN0_RX (default)
  246. // 32=PTB18=CAN0_TX, 25=PTB19=CAN0_RX (alternative)
  247. if (txAlt == 1)
  248. CORE_PIN32_CONFIG = PORT_PCR_MUX(2);
  249. else
  250. CORE_PIN3_CONFIG = PORT_PCR_MUX(2);
  251. // | PORT_PCR_PE | PORT_PCR_PS;
  252. if (rxAlt == 1)
  253. CORE_PIN25_CONFIG = PORT_PCR_MUX(2);
  254. else
  255. CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
  256. #endif
  257. }
  258. #if defined(INCLUDE_FLEXCAN_CAN1)
  259. else if (flexcanBase == FLEXCAN1_BASE) {
  260. dbg_println("Begin setup of CAN1");
  261. // 33=PTE24=CAN1_TX, 34=PTE25=CAN1_RX (default)
  262. // NOTE: Alternative CAN1 pins are not broken out on Teensy 3.6
  263. CORE_PIN33_CONFIG = PORT_PCR_MUX(2);
  264. CORE_PIN34_CONFIG = PORT_PCR_MUX(2);// | PORT_PCR_PE | PORT_PCR_PS;
  265. }
  266. #endif
  267. }
  268. /*
  269. * \brief Intializes bus baud rate setting.
  270. *
  271. * \param baud - desired baud rate
  272. *
  273. * \retval None.
  274. *
  275. now using a system that tries to automatically generate a viable baud setting.
  276. Bear these things in mind:
  277. - The master clock is 16Mhz
  278. - You can freely divide it by anything from 1 to 256
  279. - There is always a start bit (+1)
  280. - The rest (prop, seg1, seg2) are specified 1 less than their actual value (aka +1)
  281. - This gives the low end bit timing as 5 (1 + 1 + 2 + 1) and the high end 25 (1 + 8 + 8 + 8)
  282. A worked example: 16Mhz clock, divisor = 19+1, bit values add up to 16 = 16Mhz / 20 / 16 = 50k baud
  283. */
  284. void FlexCAN::setBaudRate(uint32_t baud) {
  285. // have to find a divisor that ends up as close to the target baud as possible while keeping the end result between 5 and 25
  286. dbg_println ("Set baud rate");
  287. uint32_t divisor = 0;
  288. uint32_t bestDivisor = 0;
  289. uint32_t result = 16000000 / baud / (divisor + 1);
  290. int error = baud - (16000000 / (result * (divisor + 1)));
  291. int bestError = error;
  292. while (result > 5) {
  293. divisor++;
  294. result = 16000000 / baud / (divisor + 1);
  295. if (result <= 25) {
  296. error = baud - (16000000 / (result * (divisor + 1)));
  297. if (error < 0)
  298. error *= -1;
  299. // if this error is better than we've ever seen then use it - it's the best option
  300. if (error < bestError) {
  301. bestError = error;
  302. bestDivisor = divisor;
  303. }
  304. // If this is equal to a previously good option then
  305. // switch to it but only if the bit time result was in the middle of the range
  306. // this biases the output to use the middle of the range all things being equal
  307. // Otherwise it might try to use a higher divisor and smaller values for prop, seg1, seg2
  308. // and that's not necessarily the best idea.
  309. if ((error == bestError) && (result > 11) && (result < 19)) {
  310. bestError = error;
  311. bestDivisor = divisor;
  312. }
  313. }
  314. }
  315. divisor = bestDivisor;
  316. result = 16000000 / baud / (divisor + 1);
  317. if ((result < 5) || (result > 25) || (bestError > 300)) {
  318. Serial.println ("Abort in CAN begin. Couldn't find a suitable baud config!");
  319. return;
  320. }
  321. result -= 5; // the bitTimingTable is offset by 5 since there was no reason to store bit timings for invalid numbers
  322. uint8_t propSeg = bitTimingTable[result][0];
  323. uint8_t pSeg1 = bitTimingTable[result][1];
  324. uint8_t pSeg2 = bitTimingTable[result][2];
  325. // baud rate debug information
  326. dbg_println (" Bit time values:");
  327. dbg_print (" Prop = ");
  328. dbg_println (propSeg + 1);
  329. dbg_print (" Seg1 = ");
  330. dbg_println (pSeg1 + 1);
  331. dbg_print (" Seg2 = ");
  332. dbg_println (pSeg2 + 1);
  333. dbg_print (" Divisor = ");
  334. dbg_println (divisor + 1);
  335. FLEXCANb_CTRL1 (flexcanBase) = (FLEXCAN_CTRL_PROPSEG(propSeg) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_ERR_MSK |
  336. FLEXCAN_CTRL_PSEG1(pSeg1) | FLEXCAN_CTRL_PSEG2(pSeg2) | FLEXCAN_CTRL_PRESDIV(divisor));
  337. }
  338. /*
  339. * \brief Halts CAN bus.
  340. *
  341. * \param None.
  342. *
  343. * \retval None.
  344. *
  345. */
  346. void FlexCAN::halt() {
  347. FLEXCANb_MCR(flexcanBase) |= (FLEXCAN_MCR_HALT);
  348. waitFrozen();
  349. }
  350. /*
  351. * \brief Exits from hat state.
  352. *
  353. * \param None.
  354. *
  355. * \retval None.
  356. *
  357. */
  358. void FlexCAN::exitHalt() {
  359. // exit freeze mode and wait until it is unfrozen.
  360. dbg_println ("Exit halt");
  361. FLEXCANb_MCR(flexcanBase) &= ~(FLEXCAN_MCR_HALT);
  362. waitNotFrozen();
  363. }
  364. /*
  365. * \brief Makes CAN bus soft reset.
  366. *
  367. * \param None.
  368. *
  369. * \retval None.
  370. *
  371. */
  372. void FlexCAN::softReset() {
  373. dbg_println ("Soft reset");
  374. FLEXCANb_MCR (flexcanBase) ^= FLEXCAN_MCR_SOFT_RST;
  375. while (FLEXCANb_MCR (flexcanBase) & FLEXCAN_MCR_SOFT_RST)
  376. ;
  377. }
  378. /*
  379. * \brief Freezes CAN bus.
  380. *
  381. * \param None.
  382. *
  383. * \retval None.
  384. *
  385. */
  386. void FlexCAN::freeze() {
  387. FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_FRZ;
  388. }
  389. /*
  390. * \brief Waits until CAN bus is frozen
  391. *
  392. * \param None.
  393. *
  394. * \retval None.
  395. *
  396. */
  397. void FlexCAN::waitFrozen() {
  398. // wait for freeze ack
  399. dbg_println ("Wait frozen");
  400. while (!isFrozen());
  401. }
  402. /*
  403. * \brief Waits until CAN bus is not frozen.
  404. *
  405. * \param None.
  406. *
  407. * \retval None.
  408. *
  409. */
  410. void FlexCAN::waitNotFrozen() {
  411. // wait for freeze ack
  412. dbg_println ("Wait not frozen");
  413. while (isFrozen());
  414. }
  415. /*
  416. * \brief Waits until CAN bus is ready
  417. *
  418. * \param None.
  419. *
  420. * \retval None.
  421. *
  422. */
  423. void FlexCAN::waitReady() {
  424. while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_NOT_RDY);
  425. }
  426. /*
  427. * \brief Tests is CAN bus frozen.
  428. *
  429. * \param None.
  430. *
  431. * \retval true, if CAN bus is frozen.
  432. *
  433. */
  434. bool FlexCAN::isFrozen() {
  435. return (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK);
  436. }
  437. /*
  438. * \brief Set listen only mode on or off.
  439. *
  440. * \param mode - set listen only mode?
  441. *
  442. * \retval None.
  443. *
  444. */
  445. void FlexCAN::setListenOnly (bool mode)
  446. {
  447. // enter freeze mode if not already there
  448. if (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)) {
  449. FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_FRZ;
  450. FLEXCANb_MCR(flexcanBase) |= FLEXCAN_MCR_HALT;
  451. while (!(FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK))
  452. ;
  453. }
  454. if (mode)
  455. FLEXCANb_CTRL1(flexcanBase) |= FLEXCAN_CTRL_LOM;
  456. else
  457. FLEXCANb_CTRL1(flexcanBase) &= ~FLEXCAN_CTRL_LOM;
  458. // exit freeze mode and wait until it is unfrozen.
  459. FLEXCANb_MCR(flexcanBase) &= ~FLEXCAN_MCR_HALT;
  460. while (FLEXCANb_MCR(flexcanBase) & FLEXCAN_MCR_FRZ_ACK)
  461. ;
  462. }
  463. /*
  464. * \brief Initializes mailboxes to the requested mix of Rx and Tx boxes
  465. *
  466. * \param txboxes - How many of the 8 boxes should be used for Tx
  467. *
  468. * \retval number of tx boxes set.
  469. *
  470. */
  471. uint8_t FlexCAN::setNumTxBoxes (uint8_t txboxes)
  472. {
  473. uint8_t c;
  474. uint32_t oldIde;
  475. if (txboxes > getNumMailBoxes() - 1)
  476. txboxes = getNumMailBoxes() - 1;
  477. if (txboxes < 1)
  478. txboxes = 1;
  479. numTxMailboxes = txboxes;
  480. if ( !isInitialized() ) return numTxMailboxes; // Just set the numTxMailboxes. Begin() will do final initialization.
  481. // Inialize Rx boxen
  482. for (c = 0; c < getNumRxBoxes(); c++) {
  483. // preserve the existing filter ide setting
  484. oldIde = FLEXCANb_MBn_CS(flexcanBase, c) & FLEXCAN_MB_CS_IDE;
  485. FLEXCANb_MBn_CS(flexcanBase, c) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | oldIde;
  486. }
  487. // Initialize Tx boxen
  488. for (c = getFirstTxBox(); c < getNumMailBoxes(); c++) {
  489. FLEXCANb_MBn_CS(flexcanBase, c) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  490. }
  491. return (numTxMailboxes);
  492. }
  493. /*
  494. * \brief Sets a per-mailbox filter. Sets both the storage and the actual mailbox.
  495. *
  496. * \param filter - a filled out filter structure
  497. * \param mbox - the mailbox to update
  498. *
  499. * \retval Nothing
  500. *
  501. */
  502. void FlexCAN::setFilter (const CAN_filter_t &filter, uint8_t mbox)
  503. {
  504. if ( mbox < getNumRxBoxes() ) {
  505. MBFilters[mbox] = filter;
  506. if (filter.flags.extended) {
  507. FLEXCANb_MBn_ID(flexcanBase, mbox) = (filter.id & FLEXCAN_MB_ID_EXT_MASK);
  508. FLEXCANb_MBn_CS(flexcanBase, mbox) |= FLEXCAN_MB_CS_IDE;
  509. } else {
  510. FLEXCANb_MBn_ID(flexcanBase, mbox) = FLEXCAN_MB_ID_IDSTD(filter.id);
  511. FLEXCANb_MBn_CS(flexcanBase, mbox) &= ~FLEXCAN_MB_CS_IDE;
  512. }
  513. }
  514. }
  515. /*
  516. * \brief Gets a per-mailbox filter.
  517. *
  518. * \param filter - returned filter structure
  519. * \param mbox - mailbox selected
  520. *
  521. * \retval true if mailbox s valid, false otherwise
  522. *
  523. */
  524. bool FlexCAN::getFilter (CAN_filter_t &filter, uint8_t mbox)
  525. {
  526. if ( mbox < getNumRxBoxes() ) {
  527. filter.id = MBFilters[mbox].id;
  528. filter.flags.extended = MBFilters[mbox].flags.extended;
  529. filter.flags.remote = MBFilters[mbox].flags.remote;
  530. filter.flags.reserved = MBFilters[mbox].flags.reserved;
  531. return (true);
  532. }
  533. return (false);
  534. }
  535. /*
  536. * \brief Set the mailbox mask for filtering packets
  537. *
  538. * \param mask - mask to apply.
  539. * \param mbox - mailbox number
  540. *
  541. * \retval None.
  542. */
  543. void FlexCAN::setMask (uint32_t mask, uint8_t mbox)
  544. {
  545. if ( mbox < getNumRxBoxes() ) {
  546. /* Per mailbox masks can only be set in freeze mode so have to enter that mode if not already there. */
  547. bool wasFrozen=isFrozen();
  548. if (!wasFrozen) {
  549. freeze();
  550. halt();
  551. }
  552. FLEXCANb_MB_MASK(flexcanBase, mbox) = mask;
  553. if (!wasFrozen) exitHalt();
  554. }
  555. }
  556. /*
  557. * \brief How many messages are available to read.
  558. *
  559. * \param None
  560. *
  561. * \retval A count of the number of messages available.
  562. */
  563. uint32_t FlexCAN::available (void)
  564. {
  565. irqLock();
  566. uint32_t result=(ringBufferCount (rxRing));
  567. irqRelease();
  568. return result;
  569. }
  570. /*
  571. * \brief Clear the collected statistics
  572. *
  573. * \param None
  574. *
  575. * \retval None
  576. */
  577. #if defined(COLLECT_CAN_STATS)
  578. void FlexCAN::clearStats (void)
  579. {
  580. // initialize the statistics structure
  581. memset (&stats, 0, sizeof(stats));
  582. stats.enabled = false;
  583. stats.ringRxMax = SIZE_RX_BUFFER - 1;
  584. stats.ringTxMax = SIZE_TX_BUFFER - 1;
  585. stats.ringRxFramesLost = 0;
  586. }
  587. #endif
  588. /*
  589. * \brief Retrieve a frame from the RX buffer
  590. *
  591. * \param msg - buffer reference to the frame structure to fill out
  592. *
  593. * \retval 0 no frames waiting to be received, 1 if a frame was returned
  594. */
  595. int FlexCAN::read (CAN_message_t &msg)
  596. {
  597. /* pull the next available message from the ring */
  598. int result=0;
  599. irqLock();
  600. if (removeFromRingBuffer (rxRing, msg) == true) {
  601. result=1;
  602. }
  603. irqRelease();
  604. return result;
  605. }
  606. /*
  607. * \brief Send a frame out of this canbus port
  608. *
  609. * \param msg - the filled out frame structure to use for sending
  610. *
  611. * \note Will do one of two things - 1. Send the given frame out of the first available mailbox
  612. * or 2. queue the frame for sending later via interrupt. Automatically turns on TX interrupt
  613. * if necessary.
  614. * Messages may be transmitted out of order, if more than one transmit mailbox is enabled.
  615. * The message queue ignores the message priority.
  616. *
  617. * Returns whether sending/queueing succeeded. Will not smash the queue if it gets full.
  618. */
  619. int FlexCAN::write (const CAN_message_t &msg)
  620. {
  621. uint32_t index=getNumMailBoxes();
  622. int result=0;
  623. irqLock();
  624. if ( isRingBufferEmpty(txRing) ) { // If there is nothing buffered, find free mailbox
  625. for (index = getFirstTxBox(); index < getNumMailBoxes(); index++) {
  626. if ( usesGlobalTxRing(index) && FLEXCAN_get_code(FLEXCANb_MBn_CS(flexcanBase, index)) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
  627. break;// found one
  628. }
  629. }
  630. }
  631. if (index < getNumMailBoxes()) {
  632. dbg_println ("Writing a frame directly.");
  633. writeTxRegisters (msg, index);
  634. result=1;
  635. } else {
  636. // no mailboxes available. Try to buffer it
  637. if (addToRingBuffer (txRing, msg) == true) {
  638. result=1;
  639. }
  640. // else could not send the frame!
  641. }
  642. irqRelease();
  643. return result;
  644. }
  645. /*
  646. * \brief Send a frame out of this canbus port, using a specific mailbox. The TX queue is not used.
  647. *
  648. * \param msg - the filled out frame structure to use for sending
  649. * \param mbox - mailbox selected
  650. *
  651. * \note If the mailbox is available, the message is placed in the mailbox. The CAN controller
  652. * selects the next message to send from all filled transmit mailboxes, based on the priority.
  653. * This method allows callers to not use the transmit queue and prioritize messages by using
  654. * different mailboxes for different priority levels.
  655. * Using the same mailbox for a group of messages enforces the transmit order for this group.
  656. *
  657. * Returns whether the message was placed in the mailbox for sending.
  658. */
  659. int FlexCAN::write (const CAN_message_t &msg, uint8_t mbox)
  660. {
  661. int result=0;
  662. if ( !isTxBox(mbox) ) return result;
  663. irqLock();
  664. if ( txRings[mbox]==0 || isRingBufferEmpty(*txRings[mbox]) ) {
  665. if ( FLEXCAN_get_code(FLEXCANb_MBn_CS(flexcanBase, mbox)) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
  666. writeTxRegisters (msg, mbox);
  667. result=1;
  668. }
  669. }
  670. if (result==0 && txRings[mbox]!=0 && addToRingBuffer(*txRings[mbox], msg) ) {
  671. result=1;
  672. }
  673. irqRelease();
  674. return result;
  675. }
  676. /*
  677. * \brief Write CAN message to the FlexCAN hardware registers.
  678. *
  679. * \param msg - message structure to send.
  680. * \param buffer - mailbox number to write to.
  681. *
  682. * \retval None.
  683. *
  684. */
  685. void FlexCAN::writeTxRegisters (const CAN_message_t &msg, uint8_t buffer)
  686. {
  687. // transmit the frame
  688. // Commented below by TTL. That caused lock time to time to FLEXCAN_MB_CODE_TX_ONCE state.
  689. // FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  690. if (msg.flags.extended) {
  691. FLEXCANb_MBn_ID(flexcanBase, buffer) = (msg.id & FLEXCAN_MB_ID_EXT_MASK);
  692. } else {
  693. FLEXCANb_MBn_ID(flexcanBase, buffer) = FLEXCAN_MB_ID_IDSTD(msg.id);
  694. }
  695. FLEXCANb_MBn_WORD0(flexcanBase, buffer) = (msg.buf[0]<<24)|(msg.buf[1]<<16)|(msg.buf[2]<<8)|msg.buf[3];
  696. FLEXCANb_MBn_WORD1(flexcanBase, buffer) = (msg.buf[4]<<24)|(msg.buf[5]<<16)|(msg.buf[6]<<8)|msg.buf[7];
  697. if (msg.flags.extended) {
  698. if (msg.flags.remote) {
  699. FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) |
  700. FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_SRR |
  701. FLEXCAN_MB_CS_IDE | FLEXCAN_MB_CS_RTR;
  702. } else {
  703. FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) |
  704. FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_SRR |
  705. FLEXCAN_MB_CS_IDE;
  706. }
  707. } else {
  708. if (msg.flags.remote) {
  709. FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) |
  710. FLEXCAN_MB_CS_LENGTH(msg.len) | FLEXCAN_MB_CS_RTR;
  711. } else {
  712. FLEXCANb_MBn_CS(flexcanBase, buffer) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE) |
  713. FLEXCAN_MB_CS_LENGTH(msg.len);
  714. }
  715. }
  716. }
  717. /*
  718. * \brief Read CAN message from the FlexCAN hardware registers.
  719. *
  720. * \param msg - message structure to fill.
  721. * \param buffer - mailbox number to read from.
  722. *
  723. * \retval None.
  724. *
  725. */
  726. void FlexCAN::readRxRegisters (CAN_message_t& msg, uint8_t buffer)
  727. {
  728. uint32_t mb_CS = FLEXCANb_MBn_CS(flexcanBase, buffer);
  729. // get identifier and dlc
  730. msg.len = FLEXCAN_get_length (mb_CS);
  731. msg.flags.extended = (mb_CS & FLEXCAN_MB_CS_IDE) ? 1:0;
  732. msg.flags.remote = (mb_CS & FLEXCAN_MB_CS_RTR) ? 1:0;
  733. msg.timestamp = FLEXCAN_get_timestamp (mb_CS);
  734. msg.flags.overrun = 0;
  735. msg.flags.reserved = 0;
  736. msg.id = (FLEXCANb_MBn_ID(flexcanBase, buffer) & FLEXCAN_MB_ID_EXT_MASK);
  737. if (!msg.flags.extended) {
  738. msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO;
  739. }
  740. // check for mailbox buffer overruns
  741. if (FLEXCAN_get_code (mb_CS) == FLEXCAN_MB_CODE_RX_OVERRUN) {
  742. msg.flags.overrun = 1;
  743. }
  744. // copy out message
  745. uint32_t dataIn = FLEXCANb_MBn_WORD0(flexcanBase, buffer);
  746. msg.buf[3] = dataIn;
  747. dataIn >>=8;
  748. msg.buf[2] = dataIn;
  749. dataIn >>=8;
  750. msg.buf[1] = dataIn;
  751. dataIn >>=8;
  752. msg.buf[0] = dataIn;
  753. if (msg.len > 4) {
  754. dataIn = FLEXCANb_MBn_WORD1(flexcanBase, buffer);
  755. msg.buf[7] = dataIn;
  756. dataIn >>=8;
  757. msg.buf[6] = dataIn;
  758. dataIn >>=8;
  759. msg.buf[5] = dataIn;
  760. dataIn >>=8;
  761. msg.buf[4] = dataIn;
  762. }
  763. for (uint32_t loop=msg.len; loop < 8; loop++ ) {
  764. msg.buf[loop] = 0;
  765. }
  766. }
  767. /*
  768. * \brief Initialize the specified ring buffer.
  769. *
  770. * \param ring - ring buffer to initialize.
  771. * \param buffer - buffer to use for storage.
  772. * \param size - size of the buffer in bytes.
  773. *
  774. * \retval None.
  775. *
  776. */
  777. void FlexCAN::initRingBuffer (ringbuffer_t &ring, volatile CAN_message_t *buffer, uint32_t size)
  778. {
  779. ring.buffer = buffer;
  780. ring.size = size;
  781. ring.head = 0;
  782. ring.tail = 0;
  783. }
  784. /*
  785. * \brief Add a CAN message to the specified ring buffer.
  786. *
  787. * \param ring - ring buffer to use.
  788. * \param msg - message structure to add.
  789. *
  790. * \retval true if added, false if the ring is full.
  791. *
  792. */
  793. bool FlexCAN::addToRingBuffer (ringbuffer_t &ring, const CAN_message_t &msg)
  794. {
  795. uint16_t nextEntry;
  796. nextEntry = (ring.head + 1) % ring.size;
  797. /* check if the ring buffer is full */
  798. if (nextEntry == ring.tail) {
  799. return (false);
  800. }
  801. /* add the element to the ring */
  802. memcpy ((void *)&ring.buffer[ring.head], (void *)&msg, sizeof (CAN_message_t));
  803. /* bump the head to point to the next free entry */
  804. ring.head = nextEntry;
  805. return (true);
  806. }
  807. /*
  808. * \brief Remove a CAN message from the specified ring buffer.
  809. *
  810. * \param ring - ring buffer to use.
  811. * \param msg - message structure to fill in.
  812. *
  813. * \retval true if a message was removed, false if the ring is empty.
  814. *
  815. */
  816. bool FlexCAN::removeFromRingBuffer (ringbuffer_t &ring, CAN_message_t &msg)
  817. {
  818. /* check if the ring buffer has data available */
  819. if (isRingBufferEmpty (ring) == true) {
  820. return (false);
  821. }
  822. /* copy the message */
  823. memcpy ((void *)&msg, (void *)&ring.buffer[ring.tail], sizeof (CAN_message_t));
  824. /* bump the tail pointer */
  825. ring.tail = (ring.tail + 1) % ring.size;
  826. return (true);
  827. }
  828. /*
  829. * \brief Check if the specified ring buffer is empty.
  830. *
  831. * \param ring - ring buffer to use.
  832. *
  833. * \retval true if the ring contains data, false if the ring is empty.
  834. *
  835. */
  836. bool FlexCAN::isRingBufferEmpty (ringbuffer_t &ring)
  837. {
  838. if (ring.head == ring.tail) {
  839. return (true);
  840. }
  841. return (false);
  842. }
  843. /*
  844. * \brief Count the number of entries in the specified ring buffer.
  845. *
  846. * \param ring - ring buffer to use.
  847. *
  848. * \retval a count of the number of elements in the ring buffer.
  849. *
  850. */
  851. uint32_t FlexCAN::ringBufferCount (ringbuffer_t &ring)
  852. {
  853. int32_t entries;
  854. entries = ring.head - ring.tail;
  855. if (entries < 0) {
  856. entries += ring.size;
  857. }
  858. return ((uint32_t)entries);
  859. }
  860. /*
  861. * \brief Interrupt service routine for the FlexCAN class message events.
  862. *
  863. * \param None.
  864. *
  865. * \retval None.
  866. *
  867. */
  868. void FlexCAN::message_isr (void)
  869. {
  870. uint32_t status = FLEXCANb_IFLAG1(flexcanBase);
  871. uint8_t controller = 0;
  872. uint32_t i;
  873. CAN_message_t msg;
  874. bool handledFrame;
  875. CANListener *thisListener;
  876. ringbuffer_t *pRing;
  877. #if defined(COLLECT_CAN_STATS)
  878. uint32_t rxEntries;
  879. #endif
  880. // determine which controller we're servicing
  881. #if defined (INCLUDE_FLEXCAN_CAN1)
  882. if (flexcanBase == FLEXCAN1_BASE)
  883. controller = 1;
  884. #endif
  885. // a message either came in or was freshly sent. Figure out which and act accordingly.
  886. for (i = 0; i < getNumMailBoxes(); i++) {
  887. // skip mailboxes that haven't triggered an interrupt
  888. if ((status & (1UL << i)) == 0) {
  889. continue;
  890. }
  891. // examine the reason the mailbox interrupted us
  892. uint32_t code = FLEXCAN_get_code (FLEXCANb_MBn_CS(flexcanBase, i));
  893. switch (code) {
  894. case FLEXCAN_MB_CODE_RX_FULL: // rx full, Copy the frame to RX buffer
  895. case FLEXCAN_MB_CODE_RX_OVERRUN: // rx overrun. Incomming frame overwrote existing frame.
  896. readRxRegisters (msg, i);
  897. handledFrame = false;
  898. // track message use count if collecting statistics
  899. #if defined(COLLECT_CAN_STATS)
  900. if (stats.enabled == true) {
  901. stats.mb[i].refCount++;
  902. if (msg.flags.overrun) {
  903. stats.mb[i].overrunCount++;
  904. }
  905. }
  906. #endif
  907. // First, try and handle via callback. If callback fails then buffer the frame.
  908. for (uint32_t listenerPos = 0; listenerPos < SIZE_LISTENERS; listenerPos++) {
  909. thisListener = listener[listenerPos];
  910. // process active listeners
  911. if (thisListener != NULL) {
  912. // call the handler if it's active for this mailbox
  913. if (thisListener->callbacksActive & (1UL << i)) {
  914. handledFrame |= thisListener->frameHandler (msg, i, controller);
  915. } else if (thisListener->callbacksActive & (1UL << 31)) {
  916. handledFrame |= thisListener->frameHandler (msg, -1, controller);
  917. }
  918. }
  919. }
  920. // if no objects caught this frame then queue it in the ring buffer
  921. if (handledFrame == false) {
  922. if (addToRingBuffer (rxRing, msg) != true) {
  923. // ring buffer is full, track it
  924. dbg_println ("Receiver buffer overrun!");
  925. #if defined(COLLECT_CAN_STATS)
  926. if (stats.enabled == true) {
  927. stats.ringRxFramesLost++;
  928. }
  929. #endif
  930. }
  931. }
  932. #if defined(COLLECT_CAN_STATS)
  933. if (stats.enabled == true) {
  934. // track the high water mark for the receive ring buffer
  935. rxEntries = ringBufferCount (rxRing);
  936. if (stats.ringRxHighWater < rxEntries) {
  937. stats.ringRxHighWater = rxEntries;
  938. }
  939. }
  940. #endif
  941. // it seems filtering works by matching against the ID stored in the mailbox
  942. // so after a frame comes in we've got to refresh the ID field to be the filter ID and not the ID
  943. // that just came in.
  944. if (MBFilters[i].flags.extended) {
  945. FLEXCANb_MBn_ID(flexcanBase, i) = (MBFilters[i].id & FLEXCAN_MB_ID_EXT_MASK);
  946. } else {
  947. FLEXCANb_MBn_ID(flexcanBase, i) = FLEXCAN_MB_ID_IDSTD(MBFilters[i].id);
  948. }
  949. break;
  950. case FLEXCAN_MB_CODE_TX_INACTIVE: // TX inactive. Just chillin' waiting for a message to send. Let's see if we've got one.
  951. // if there is a frame in the queue then send it
  952. pRing=( usesGlobalTxRing(i) ? &txRing : txRings[i] );
  953. if (isRingBufferEmpty (*pRing) == false) {
  954. if (removeFromRingBuffer (*pRing, msg) == true) {
  955. writeTxRegisters (msg, i);
  956. }
  957. } else {
  958. for (uint32_t listenerPos = 0; listenerPos < SIZE_LISTENERS; listenerPos++) {
  959. thisListener = listener[listenerPos];
  960. // process active listeners
  961. if (thisListener != NULL) {
  962. if (thisListener->callbacksActive & (1UL << i | 1UL << 31)) {
  963. thisListener->txHandler (i, controller);
  964. }
  965. }
  966. }
  967. }
  968. break;
  969. // currently unhandled events
  970. case FLEXCAN_MB_CODE_RX_INACTIVE: // inactive Receive box. Must be a false alarm!?
  971. case FLEXCAN_MB_CODE_RX_BUSY: // mailbox is busy. Don't touch it.
  972. case FLEXCAN_MB_CODE_RX_EMPTY: // rx empty already. Why did it interrupt then?
  973. case FLEXCAN_MB_CODE_TX_ABORT: // TX being aborted.
  974. case FLEXCAN_MB_CODE_TX_RESPONSE: // remote request response (deprecated)
  975. case FLEXCAN_MB_CODE_TX_ONCE: // TX mailbox is full and will be sent as soon as possible
  976. case FLEXCAN_MB_CODE_TX_RESPONSE_TEMPO: // remote request junk again. Go away.
  977. break;
  978. default:
  979. break;
  980. }
  981. }
  982. // writing the flag value back to itself clears all flags
  983. FLEXCANb_IFLAG1(flexcanBase) = status;
  984. }
  985. /*
  986. * \brief Attach an object to the listening list.
  987. *
  988. * \param listener - pointer to listening object
  989. *
  990. * \retval true if listener added to list, false if the list is full.
  991. *
  992. */
  993. bool FlexCAN::attachObj (CANListener *listener)
  994. {
  995. uint32_t i;
  996. for (i = 0; i < SIZE_LISTENERS; i++) {
  997. if (this->listener[i] == NULL) {
  998. this->listener[i] = listener;
  999. listener->callbacksActive = 0;
  1000. return true;
  1001. }
  1002. }
  1003. return false;
  1004. }
  1005. /*
  1006. * \brief Detatch an object from the listening list.
  1007. *
  1008. * \param listener - pointer to listening object
  1009. *
  1010. * \retval true if listener removed from list, false if object not found.
  1011. *
  1012. */
  1013. bool FlexCAN::detachObj (CANListener *listener)
  1014. {
  1015. uint32_t i;
  1016. for (i = 0; i < SIZE_LISTENERS; i++) {
  1017. if (this->listener[i] == listener) {
  1018. this->listener[i] = NULL;
  1019. return true;
  1020. }
  1021. }
  1022. return false;
  1023. }
  1024. void FlexCAN::bus_off_isr (void)
  1025. {
  1026. }
  1027. /*
  1028. * \brief Interrupt service routine for FlexCAN class device errors.
  1029. *
  1030. * \param None.
  1031. *
  1032. * \retval None.
  1033. *
  1034. */
  1035. void FlexCAN::error_isr (void)
  1036. {
  1037. uint32_t status = FLEXCANb_ESR1 (flexcanBase);
  1038. // CAN_message_t msg;
  1039. // an acknowledge error happened - frame was not ACK'd
  1040. if (status & FLEXCAN_ESR_ACK_ERR) {
  1041. // this ISR doesn't get a buffer passed to it so it would have to be cached elsewhere.
  1042. // msg.flags.extended = (FLEXCANb_MBn_CS(flexcanBase, buffer) & FLEXCAN_MB_CS_IDE)? 1:0;
  1043. // msg.id = (FLEXCANb_MBn_ID(flexcanBase, buffer) & FLEXCAN_MB_ID_EXT_MASK);
  1044. // if (!msg.flags.extended) {
  1045. // msg.id >>= FLEXCAN_MB_ID_STD_BIT_NO;
  1046. //
  1047. // }
  1048. }
  1049. }
  1050. /*
  1051. * \brief Interrupt service routine for the FlexCAN class transmit warnings.
  1052. *
  1053. * \param None.
  1054. *
  1055. * \retval None.
  1056. *
  1057. */
  1058. void FlexCAN::tx_warn_isr (void)
  1059. {
  1060. }
  1061. /*
  1062. * \brief Interrupt service routine for the FlexCAN class receive warnings.
  1063. *
  1064. * \param None.
  1065. *
  1066. * \retval None.
  1067. *
  1068. */
  1069. void FlexCAN::rx_warn_isr (void)
  1070. {
  1071. }
  1072. /*
  1073. * \brief Interrupt service routine for the FlexCAN class device wakeup.
  1074. *
  1075. * \param None.
  1076. *
  1077. * \retval None.
  1078. *
  1079. */
  1080. void FlexCAN::wakeup_isr (void)
  1081. {
  1082. }
  1083. /*
  1084. * \brief Interrupt handler for FlexCAN can0 message events.
  1085. *
  1086. * \param None.
  1087. *
  1088. * \retval None.
  1089. *
  1090. */
  1091. void can0_message_isr (void)
  1092. {
  1093. Can0.message_isr ();
  1094. }
  1095. /*
  1096. * \brief Interrupt handler for FlexCAN can0 bus off event.
  1097. *
  1098. * \param None.
  1099. *
  1100. * \retval None.
  1101. *
  1102. */
  1103. void can0_bus_off_isr (void)
  1104. {
  1105. Can0.bus_off_isr ();
  1106. }
  1107. /*
  1108. * \brief Interrupt handler for FlexCAN can0 error events.
  1109. *
  1110. * \param None.
  1111. *
  1112. * \retval None.
  1113. *
  1114. */
  1115. void can0_error_isr (void)
  1116. {
  1117. Can0.error_isr ();
  1118. }
  1119. /*
  1120. * \brief Interrupt handler for FlexCAN can0 transmit warning event.
  1121. *
  1122. * \param None.
  1123. *
  1124. * \retval None.
  1125. *
  1126. */
  1127. void can0_tx_warn_isr (void)
  1128. {
  1129. Can0.tx_warn_isr ();
  1130. }
  1131. /*
  1132. * \brief Interrupt handler for FlexCAN can0 receive warning event.
  1133. *
  1134. * \param None.
  1135. *
  1136. * \retval None.
  1137. *
  1138. */
  1139. void can0_rx_warn_isr (void)
  1140. {
  1141. Can0.rx_warn_isr ();
  1142. }
  1143. /*
  1144. * \brief Interrupt handler for FlexCAN can0 device wakeup event.
  1145. *
  1146. * \param None.
  1147. *
  1148. * \retval None.
  1149. *
  1150. */
  1151. void can0_wakeup_isr (void)
  1152. {
  1153. Can0.wakeup_isr ();
  1154. }
  1155. #if defined(INCLUDE_FLEXCAN_CAN1)
  1156. /*
  1157. * \brief Interrupt handler for FlexCAN can1 message events.
  1158. *
  1159. * \param None.
  1160. *
  1161. * \retval None.
  1162. *
  1163. */
  1164. void can1_message_isr (void)
  1165. {
  1166. Can1.message_isr ();
  1167. }
  1168. /*
  1169. * \brief Interrupt handler for FlexCAN can1 bus off event.
  1170. *
  1171. * \param None.
  1172. *
  1173. * \retval None.
  1174. *
  1175. */
  1176. void can1_bus_off_isr (void)
  1177. {
  1178. Can1.bus_off_isr ();
  1179. }
  1180. /*
  1181. * \brief Interrupt handler for FlexCAN can1 error events.
  1182. *
  1183. * \param None.
  1184. *
  1185. * \retval None.
  1186. *
  1187. */
  1188. void can1_error_isr (void)
  1189. {
  1190. Can1.error_isr ();
  1191. }
  1192. /*
  1193. * \brief Interrupt handler for FlexCAN can1 transmit warning event.
  1194. *
  1195. * \param None.
  1196. *
  1197. * \retval None.
  1198. *
  1199. */
  1200. void can1_tx_warn_isr (void)
  1201. {
  1202. Can1.tx_warn_isr ();
  1203. }
  1204. /*
  1205. * \brief Interrupt handler for FlexCAN can1 receive warning event.
  1206. *
  1207. * \param None.
  1208. *
  1209. * \retval None.
  1210. *
  1211. */
  1212. void can1_rx_warn_isr (void)
  1213. {
  1214. Can1.rx_warn_isr ();
  1215. }
  1216. /*
  1217. * \brief Interrupt handler for FlexCAN can1 device wakeup event.
  1218. *
  1219. * \param None.
  1220. *
  1221. * \retval None.
  1222. *
  1223. */
  1224. void can1_wakeup_isr (void)
  1225. {
  1226. Can1.wakeup_isr ();
  1227. }
  1228. #endif /* INCLUDE_FLEXCAN_CAN1 */
  1229. /*
  1230. * \brief CANListener constructor
  1231. *
  1232. * \param None.
  1233. *
  1234. * \retval None.
  1235. *
  1236. */
  1237. CANListener::CANListener ()
  1238. {
  1239. // none. Bitfield were bits 0-15 are the mailboxes and bit 31 is the general callback
  1240. callbacksActive = 0;
  1241. }
  1242. /*
  1243. * \brief Default CAN received frame handler.
  1244. *
  1245. * \param frame - CAN frame to process.
  1246. * \param mailbox - mailbox number frame arrived at.
  1247. * \param controller - controller number frame arrived from.
  1248. *
  1249. * \retval true if frame was handled, false otherwise.
  1250. *
  1251. */
  1252. bool CANListener::frameHandler (CAN_message_t &/*frame*/, int /*mailbox*/, uint8_t /*controller*/)
  1253. {
  1254. /* default implementation that doesn't handle frames */
  1255. return (false);
  1256. }
  1257. /*
  1258. * \brief Default CAN transmission completed handler.
  1259. *
  1260. * \param mailbox - transmit mailbox that is now available.
  1261. * \param controller - controller number.
  1262. *
  1263. */
  1264. void CANListener::txHandler (int /*mailbox*/, uint8_t /*controller*/)
  1265. {
  1266. }
  1267. /*
  1268. * \brief Indicate mailbox has an active callback.
  1269. *
  1270. * \param mailBox - mailbox number.
  1271. *
  1272. * \retval None.
  1273. *
  1274. */
  1275. void CANListener::attachMBHandler (uint8_t mailBox)
  1276. {
  1277. if ( (mailBox < NUM_MAILBOXES) ) {
  1278. callbacksActive |= (1L << mailBox);
  1279. }
  1280. }
  1281. /*
  1282. * \brief Clear callback indicator for a mailbox.
  1283. *
  1284. * \param mailBox - mailbox number.
  1285. *
  1286. * \retval None.
  1287. *
  1288. */
  1289. void CANListener::detachMBHandler (uint8_t mailBox)
  1290. {
  1291. if ( (mailBox < NUM_MAILBOXES) ) {
  1292. callbacksActive &= ~(1UL << mailBox);
  1293. }
  1294. }
  1295. /*
  1296. * \brief Set general purpose callback indicator.
  1297. *
  1298. * \param None.
  1299. *
  1300. * \retval None.
  1301. *
  1302. */
  1303. void CANListener::attachGeneralHandler (void)
  1304. {
  1305. callbacksActive |= (1UL << 31);
  1306. }
  1307. /*
  1308. * \brief Clear general purpose callback indicator.
  1309. *
  1310. * \param None.
  1311. *
  1312. * \retval None.
  1313. *
  1314. */
  1315. void CANListener::detachGeneralHandler (void)
  1316. {
  1317. callbacksActive &= ~(1UL << 31);
  1318. }