PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

1352 Zeilen
67KB

  1. /*
  2. MIT License
  3. Copyright (c) 2018 Antonio Alexander Brewer (tonton81) - https://github.com/tonton81
  4. Designed and tested for PJRC Teensy 4.0.
  5. Forum link : https://forum.pjrc.com/threads/56035-FlexCAN_T4-FlexCAN-for-Teensy-4?highlight=flexcan_t4
  6. Thanks goes to skpang, mjs513, and collin for tech/testing support
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in all
  14. copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. SOFTWARE.
  22. */
  23. #include <FlexCAN_T4.h>
  24. #include "imxrt_flexcan.h"
  25. #include "Arduino.h"
  26. #if defined(__IMXRT1062__)
  27. static void flexcan_isr_can3();
  28. static void flexcan_isr_can2();
  29. static void flexcan_isr_can1();
  30. #endif
  31. #if defined(__MK20DX256__) || defined(__MK64FX512__)
  32. static void flexcan_isr_can0();
  33. #endif
  34. #if defined(__MK66FX1M0__)
  35. static void flexcan_isr_can0();
  36. static void flexcan_isr_can1();
  37. #endif
  38. FCTP_FUNC FCTP_OPT::FlexCAN_T4() {
  39. #if defined(__IMXRT1062__)
  40. if ( _bus == CAN3 ) _CAN3 = this;
  41. if ( _bus == CAN2 ) _CAN2 = this;
  42. if ( _bus == CAN1 ) _CAN1 = this;
  43. #endif
  44. #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  45. if ( _bus == CAN1 ) _CAN1 = this;
  46. if ( _bus == CAN0 ) _CAN0 = this;
  47. #endif
  48. }
  49. #if defined(__IMXRT1062__)
  50. FCTP_FUNC void FCTP_OPT::setClock(FLEXCAN_CLOCK clock) {
  51. if ( clock == CLK_OFF ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(3) | CCM_CSCMR2_CAN_CLK_PODF(0);
  52. if ( clock == CLK_8MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(2) | CCM_CSCMR2_CAN_CLK_PODF(9);
  53. if ( clock == CLK_16MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(2) | CCM_CSCMR2_CAN_CLK_PODF(4);
  54. if ( clock == CLK_24MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(1) | CCM_CSCMR2_CAN_CLK_PODF(0);
  55. if ( clock == CLK_20MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(2) | CCM_CSCMR2_CAN_CLK_PODF(3);
  56. if ( clock == CLK_30MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(0) | CCM_CSCMR2_CAN_CLK_PODF(1);
  57. if ( clock == CLK_40MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(2) | CCM_CSCMR2_CAN_CLK_PODF(1);
  58. if ( clock == CLK_60MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(0) | CCM_CSCMR2_CAN_CLK_PODF(0);
  59. if ( clock == CLK_80MHz ) CCM_CSCMR2 = (CCM_CSCMR2 & 0xFFFFFC03) | CCM_CSCMR2_CAN_CLK_SEL(2) | CCM_CSCMR2_CAN_CLK_PODF(0);
  60. if ( _CAN1 ) _CAN1->setBaudRate(currentBitrate, (( FLEXCANb_CTRL1(_bus) & FLEXCAN_CTRL_LOM ) ? LISTEN_ONLY : TX));
  61. if ( _CAN2 ) _CAN2->setBaudRate(currentBitrate, (( FLEXCANb_CTRL1(_bus) & FLEXCAN_CTRL_LOM ) ? LISTEN_ONLY : TX));
  62. if ( _CAN3 ) _CAN3->setBaudRate(currentBitrate, (( FLEXCANb_CTRL1(_bus) & FLEXCAN_CTRL_LOM ) ? LISTEN_ONLY : TX));
  63. }
  64. FCTP_FUNC uint32_t FCTP_OPT::getClock() {
  65. const uint8_t clocksrc[4] = {60, 24, 80, 0};
  66. return clocksrc[(CCM_CSCMR2 & 0x300) >> 8];
  67. }
  68. #endif
  69. FCTP_FUNC void FCTP_OPT::begin() {
  70. #if defined(__IMXRT1062__)
  71. if ( !getClock() ) setClock(CLK_24MHz); /* no clock enabled, enable osc clock */
  72. if ( _bus == CAN3 ) {
  73. nvicIrq = IRQ_CAN3;
  74. _VectorsRam[16 + nvicIrq] = flexcan_isr_can3;
  75. CCM_CCGR7 |= 0x3C0;
  76. busNumber = 3;
  77. }
  78. if ( _bus == CAN2 ) {
  79. nvicIrq = IRQ_CAN2;
  80. _VectorsRam[16 + nvicIrq] = flexcan_isr_can2;
  81. CCM_CCGR0 |= 0x3C0000;
  82. busNumber = 2;
  83. }
  84. if ( _bus == CAN1 ) {
  85. nvicIrq = IRQ_CAN1;
  86. _VectorsRam[16 + nvicIrq] = flexcan_isr_can1;
  87. CCM_CCGR0 |= 0x3C000;
  88. busNumber = 1;
  89. }
  90. #endif
  91. #if defined(__MK20DX256__)
  92. if ( _bus == CAN0 ) {
  93. nvicIrq = IRQ_CAN_MESSAGE;
  94. _VectorsRam[16 + nvicIrq] = flexcan_isr_can0;
  95. busNumber = 0;
  96. }
  97. #endif
  98. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  99. if ( _bus == CAN0 ) {
  100. nvicIrq = IRQ_CAN0_MESSAGE;
  101. _VectorsRam[16 + nvicIrq] = flexcan_isr_can0;
  102. busNumber = 0;
  103. }
  104. #endif
  105. #if defined(__MK66FX1M0__)
  106. else if ( _bus == CAN1 ) {
  107. nvicIrq = IRQ_CAN1_MESSAGE;
  108. _VectorsRam[16 + nvicIrq] = flexcan_isr_can1;
  109. busNumber = 1;
  110. }
  111. #endif
  112. #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  113. OSC0_CR |= OSC_ERCLKEN;
  114. if ( _bus == CAN0 ) SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0;
  115. #if defined(__MK66FX1M0__)
  116. else if ( _bus == CAN1 ) SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1;
  117. #endif
  118. FLEXCANb_CTRL1(_bus) &= ~FLEXCAN_CTRL_CLK_SRC;
  119. #endif
  120. setTX(); setRX();
  121. FLEXCANb_MCR(_bus) &= ~FLEXCAN_MCR_MDIS; /* enable module */
  122. FLEXCAN_EnterFreezeMode();
  123. FLEXCANb_CTRL1(_bus) |= FLEXCAN_CTRL_LOM; /* listen only mode */
  124. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_FRZ; /* enable freeze bit */
  125. while (FLEXCANb_MCR(_bus) & FLEXCAN_MCR_LPM_ACK);
  126. softReset(); /* reset bus */
  127. while (!(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK));
  128. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_SRX_DIS; /* Disable self-reception */
  129. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_IRMQ; // individual mailbox masking
  130. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_AEN; // TX ABORT FEATURE
  131. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_LPRIO_EN; // TX PRIORITY FEATURE
  132. FLEXCANb_MCR(_bus) &= ~0x8800; // disable DMA and FD (valid bits are reserved in legacy controllers)
  133. FLEXCANb_CTRL2(_bus) |= FLEXCAN_CTRL2_RRS | // store remote frames
  134. FLEXCAN_CTRL2_EACEN | /* handles the way filtering works. Library adjusts to whether you use this or not */
  135. FLEXCAN_CTRL2_MRP; // mailbox > FIFO priority.
  136. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_WRN_EN;
  137. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_WAK_MSK;
  138. disableFIFO(); /* clears all data and layout to legacy mailbox mode */
  139. FLEXCAN_ExitFreezeMode();
  140. NVIC_ENABLE_IRQ(nvicIrq);
  141. }
  142. FCTP_FUNC void FCTP_OPT::enableFIFO(bool status) {
  143. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  144. FLEXCAN_EnterFreezeMode();
  145. FLEXCANb_MCR(_bus) &= ~FLEXCAN_MCR_FEN; // Disable FIFO if already enabled for cleanup.
  146. writeIMASK(0ULL); // disable all FIFO/MB Interrupts
  147. for (uint8_t i = 0; i < FLEXCANb_MAXMB_SIZE(_bus); i++ ) { // clear all mailboxes
  148. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (i * 0x10)));
  149. mbxAddr[0] = mbxAddr[1] = mbxAddr[2] = mbxAddr[3] = 0; // code, id, word0, word1
  150. FLEXCANb_RXIMR(_bus, i) = 0UL; // CLEAR MAILBOX MASKS (RXIMR)
  151. }
  152. FLEXCANb_RXMGMASK(_bus) = FLEXCANb_RXFGMASK(_bus) = 0;
  153. writeIFLAG(readIFLAG()); // (all bits reset when written back)
  154. if ( status ) {
  155. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_FEN;
  156. for (uint8_t i = mailboxOffset(); i < FLEXCANb_MAXMB_SIZE(_bus); i++) FLEXCANb_MBn_CS(_bus,i) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  157. }
  158. else { // FIFO disabled default setup of mailboxes, 0-7 RX, 8-15 TX
  159. for (uint8_t i = 0; i < FLEXCANb_MAXMB_SIZE(_bus); i++ ) { // clear all mailboxes
  160. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (i * 0x10)));
  161. if ( i < (FLEXCANb_MAXMB_SIZE(_bus) / 2) ) {
  162. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | ((i < (FLEXCANb_MAXMB_SIZE(_bus) / 4)) ? 0 : FLEXCAN_MB_CS_IDE | FLEXCAN_MB_CS_SRR);
  163. FLEXCANb_RXIMR(_bus, i) = 0UL | ((FLEXCANb_CTRL2(_bus) & FLEXCAN_CTRL2_EACEN) ? (1UL << 30) : 0); // (RXIMR)
  164. }
  165. else {
  166. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  167. }
  168. }
  169. }
  170. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  171. }
  172. FCTP_FUNC void FCTP_OPT::enableFIFOInterrupt(bool status) {
  173. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN) ) return; /* FIFO must be enabled first */
  174. if ( FLEXCANb_IMASK1(_bus) & FLEXCAN_IMASK1_BUF5M ) return; /* FIFO interrupts already enabled */
  175. FLEXCANb_IMASK1(_bus) &= ~0xFF; /* disable FIFO interrupt flags */
  176. if ( status ) FLEXCANb_IMASK1(_bus) |= FLEXCAN_IMASK1_BUF5M; /* enable FIFO interrupt */
  177. }
  178. FCTP_FUNC void FCTP_OPT::enableMBInterrupts(bool status) {
  179. FLEXCAN_EnterFreezeMode();
  180. for ( uint8_t mb_num = mailboxOffset(); mb_num < FLEXCANb_MAXMB_SIZE(_bus); mb_num++ ) {
  181. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) continue; // skip TX mailboxes
  182. enableMBInterrupt((FLEXCAN_MAILBOX)mb_num, status);
  183. }
  184. FLEXCAN_ExitFreezeMode();
  185. }
  186. FCTP_FUNC void FCTP_OPT::enableMBInterrupt(const FLEXCAN_MAILBOX &mb_num, bool status) {
  187. if ( mb_num < mailboxOffset() ) return; /* mailbox not available */
  188. if ( status ) writeIMASKBit(mb_num); /* enable mailbox interrupt */
  189. else writeIMASKBit(mb_num, 0); /* disable mailbox interrupt */
  190. }
  191. FCTP_FUNC bool FCTP_OPT::setMB(const FLEXCAN_MAILBOX &mb_num, const FLEXCAN_RXTX &mb_rx_tx, const FLEXCAN_IDE &ide) {
  192. if ( mb_num < mailboxOffset() ) return 0; /* mailbox not available */
  193. writeIMASKBit(mb_num, 0); /* immediately disable mailbox interrupt */
  194. FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)); // Reading Control Status atomically locks mailbox (if it is RX mode).
  195. FLEXCANb_MBn_ID(_bus, mb_num) = 0UL;
  196. FLEXCANb_MBn_WORD0(_bus, mb_num) = 0UL;
  197. FLEXCANb_MBn_WORD1(_bus, mb_num) = 0UL;
  198. if ( mb_rx_tx == RX ) {
  199. if ( ide != EXT ) FLEXCANb_MBn_CS(_bus, mb_num) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY);
  200. else FLEXCANb_MBn_CS(_bus, mb_num) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE;
  201. }
  202. if ( mb_rx_tx == TX ) {
  203. FLEXCANb_MBn_CS(_bus, mb_num) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  204. }
  205. if ( ide == INACTIVE ) {
  206. FLEXCANb_MBn_CS(_bus, mb_num) = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_INACTIVE);
  207. }
  208. (void)FLEXCANb_TIMER(_bus);
  209. writeIFLAGBit(mb_num); /* clear mailbox reception flag */
  210. mb_filter_table[mb_num][0] = ( ((FLEXCANb_MBn_CS(_bus, mb_num) & 0x600000) ? 1UL : 0UL) << 27); /* extended flag check */
  211. return 1;
  212. }
  213. FCTP_FUNC void FCTP_OPT::mailboxStatus() {
  214. if ( FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN ) {
  215. Serial.print("FIFO Enabled --> "); ( FLEXCANb_IMASK1(_bus) & FLEXCAN_IFLAG1_BUF5I ) ? Serial.println("Interrupt Enabled") : Serial.println("Interrupt Disabled");
  216. Serial.print("\tFIFO Filters in use: ");
  217. uint32_t remaining_mailboxes = FLEXCANb_MAXMB_SIZE(_bus) - 6 /* MAXMB - FIFO */ - ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2);
  218. if ( FLEXCANb_MAXMB_SIZE(_bus) < (6 + ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2))) remaining_mailboxes = 0;
  219. Serial.println(constrain((uint8_t)(FLEXCANb_MAXMB_SIZE(_bus) - remaining_mailboxes), 0, 32));
  220. Serial.print("\tRemaining Mailboxes: ");
  221. if ( FLEXCANb_MAXMB_SIZE(_bus) < (6 + ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2))) remaining_mailboxes = 0;
  222. Serial.println(remaining_mailboxes); // 8 filters per 2 mailboxes
  223. for ( uint8_t i = FLEXCANb_MAXMB_SIZE(_bus) - remaining_mailboxes; i < FLEXCANb_MAXMB_SIZE(_bus); i++ ) {
  224. switch ( FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, i)) ) {
  225. case 0b0000: {
  226. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_INACTIVE"); break;
  227. }
  228. case 0b0100: {
  229. Serial.print("\t\tMB"); Serial.print(i); Serial.print(" code: RX_EMPTY");
  230. (FLEXCANb_MBn_CS(_bus, i) & FLEXCAN_MB_CS_IDE) ? Serial.println("\t(Extended Frame)") : Serial.println("\t(Standard Frame)");
  231. break;
  232. }
  233. case 0b0010: {
  234. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_FULL"); break;
  235. }
  236. case 0b0110: {
  237. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_OVERRUN"); break;
  238. }
  239. case 0b1010: {
  240. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_RANSWER"); break;
  241. }
  242. case 0b0001: {
  243. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_BUSY"); break;
  244. }
  245. case 0b1000: {
  246. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_INACTIVE"); break;
  247. }
  248. case 0b1001: {
  249. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_ABORT"); break;
  250. }
  251. case 0b1100: {
  252. Serial.print("\t\tMB"); Serial.print(i); Serial.print(" code: TX_DATA (Transmitting)");
  253. uint32_t extid = (FLEXCANb_MBn_CS(_bus, i) & FLEXCAN_MB_CS_IDE);
  254. (extid) ? Serial.print("(Extended Frame)") : Serial.print("(Standard Frame)");
  255. uint32_t dataIn = FLEXCANb_MBn_WORD0(_bus, i);
  256. uint32_t id = (FLEXCANb_MBn_ID(_bus, i) & FLEXCAN_MB_ID_EXT_MASK);
  257. if (!extid) id >>= FLEXCAN_MB_ID_STD_BIT_NO;
  258. Serial.print("(ID: 0x"); Serial.print(id, HEX); Serial.print(")");
  259. Serial.print("(Payload: "); Serial.print((uint8_t)(dataIn >> 24), HEX);
  260. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 16), HEX);
  261. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 8), HEX);
  262. Serial.print(" "); Serial.print((uint8_t)dataIn, HEX);
  263. dataIn = FLEXCANb_MBn_WORD1(_bus, i);
  264. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 24), HEX);
  265. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 16), HEX);
  266. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 8), HEX);
  267. Serial.print(" "); Serial.print((uint8_t)dataIn, HEX);
  268. Serial.println(")");
  269. break;
  270. }
  271. case 0b1110: {
  272. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_TANSWER"); break;
  273. }
  274. }
  275. } // for loop
  276. return;
  277. } // fifo detected ends here
  278. Serial.print("FIFO Disabled\n\tMailboxes:\n");
  279. for ( uint8_t i = 0; i < FLEXCANb_MAXMB_SIZE(_bus); i++ ) {
  280. switch ( FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, i)) ) {
  281. case 0b0000: {
  282. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_INACTIVE"); break;
  283. }
  284. case 0b0100: {
  285. Serial.print("\t\tMB"); Serial.print(i); Serial.print(" code: RX_EMPTY");
  286. (FLEXCANb_MBn_CS(_bus, i) & FLEXCAN_MB_CS_IDE) ? Serial.println("\t(Extended Frame)") : Serial.println("\t(Standard Frame)");
  287. break;
  288. }
  289. case 0b0010: {
  290. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_FULL"); break;
  291. }
  292. case 0b0110: {
  293. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_OVERRUN"); break;
  294. }
  295. case 0b1010: {
  296. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_RANSWER"); break;
  297. }
  298. case 0b0001: {
  299. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: RX_BUSY"); break;
  300. }
  301. case 0b1000: {
  302. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_INACTIVE"); break;
  303. }
  304. case 0b1001: {
  305. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_ABORT"); break;
  306. }
  307. case 0b1100: {
  308. Serial.print("\t\tMB"); Serial.print(i); Serial.print(" code: TX_DATA (Transmitting)");
  309. uint32_t extid = (FLEXCANb_MBn_CS(_bus, i) & FLEXCAN_MB_CS_IDE);
  310. (extid) ? Serial.print("(Extended Frame)") : Serial.print("(Standard Frame)");
  311. uint32_t dataIn = FLEXCANb_MBn_WORD0(_bus, i);
  312. uint32_t id = (FLEXCANb_MBn_ID(_bus, i) & FLEXCAN_MB_ID_EXT_MASK);
  313. if (!extid) id >>= FLEXCAN_MB_ID_STD_BIT_NO;
  314. Serial.print("(ID: 0x"); Serial.print(id, HEX); Serial.print(")");
  315. Serial.print("(Payload: "); Serial.print((uint8_t)(dataIn >> 24), HEX);
  316. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 16), HEX);
  317. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 8), HEX);
  318. Serial.print(" "); Serial.print((uint8_t)dataIn, HEX);
  319. dataIn = FLEXCANb_MBn_WORD1(_bus, i);
  320. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 24), HEX);
  321. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 16), HEX);
  322. Serial.print(" "); Serial.print((uint8_t)(dataIn >> 8), HEX);
  323. Serial.print(" "); Serial.print((uint8_t)dataIn, HEX);
  324. Serial.println(")");
  325. break;
  326. }
  327. case 0b1110: {
  328. Serial.print("\t\tMB"); Serial.print(i); Serial.println(" code: TX_TANSWER"); break;
  329. }
  330. }
  331. } // for loop
  332. }
  333. FCTP_FUNC uint64_t FCTP_OPT::readIFLAG() {
  334. #if defined(__IMXRT1062__)
  335. return (((uint64_t)FLEXCANb_IFLAG2(_bus) << 32) | FLEXCANb_IFLAG1(_bus));
  336. #endif
  337. return FLEXCANb_IFLAG1(_bus);
  338. }
  339. FCTP_FUNC void FCTP_OPT::writeIFLAG(uint64_t value) {
  340. #if defined(__IMXRT1062__)
  341. FLEXCANb_IFLAG2(_bus) = value >> 32;
  342. #endif
  343. FLEXCANb_IFLAG1(_bus) = value;
  344. }
  345. FCTP_FUNC void FCTP_OPT::writeIFLAGBit(uint8_t mb_num) {
  346. if ( mb_num < 32 ) FLEXCANb_IFLAG1(_bus) |= (1UL << mb_num);
  347. else FLEXCANb_IFLAG2(_bus) |= (1UL << (mb_num - 32));
  348. }
  349. FCTP_FUNC void FCTP_OPT::writeIMASK(uint64_t value) {
  350. #if defined(__IMXRT1062__)
  351. FLEXCANb_IMASK2(_bus) = value >> 32;
  352. #endif
  353. FLEXCANb_IMASK1(_bus) = value;
  354. }
  355. FCTP_FUNC uint64_t FCTP_OPT::readIMASK() {
  356. #if defined(__IMXRT1062__)
  357. return (((uint64_t)FLEXCANb_IMASK2(_bus) << 32) | FLEXCANb_IMASK1(_bus));
  358. #endif
  359. return FLEXCANb_IMASK1(_bus);
  360. }
  361. FCTP_FUNC void FCTP_OPT::writeIMASKBit(uint8_t mb_num, bool set) {
  362. if ( mb_num < 32 ) (( set ) ? FLEXCANb_IMASK1(_bus) |= (1UL << mb_num) : FLEXCANb_IMASK1(_bus) &= ~(1UL << mb_num));
  363. else (( set ) ? FLEXCANb_IMASK2(_bus) |= (1UL << (mb_num - 32)) : FLEXCANb_IMASK2(_bus) &= ~(1UL << (mb_num - 32)));
  364. }
  365. FCTP_FUNC void FCTP_OPT::writeTxMailbox(uint8_t mb_num, const CAN_message_t &msg) {
  366. writeIFLAGBit(mb_num);
  367. uint32_t code = 0;
  368. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mb_num * 0x10)));
  369. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  370. mbxAddr[1] = (( msg.flags.extended ) ? ( msg.id & FLEXCAN_MB_ID_EXT_MASK ) : FLEXCAN_MB_ID_IDSTD(msg.id));
  371. if ( msg.flags.remote ) code |= (1UL << 20);
  372. if ( msg.flags.extended ) code |= (3UL << 21);
  373. for ( uint8_t i = 0; i < (8 >> 2); i++ ) mbxAddr[2 + i] = (msg.buf[0 + i * 4] << 24) | (msg.buf[1 + i * 4] << 16) | (msg.buf[2 + i * 4] << 8) | msg.buf[3 + i * 4];
  374. code |= msg.len << 16;
  375. mbxAddr[0] = code | FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_ONCE);
  376. if ( msg.flags.remote ) {
  377. uint32_t timeout = millis();
  378. while ( !(readIFLAG() & (1ULL << mb_num)) && (millis() - timeout < 20) );
  379. writeIFLAGBit(mb_num);
  380. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE);
  381. }
  382. }
  383. FCTP_FUNC uint8_t FCTP_OPT::mailboxOffset() {
  384. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN ) ) return 0; /* return offset 0 since FIFO is disabled */
  385. uint32_t remaining_mailboxes = FLEXCANb_MAXMB_SIZE(_bus) - 6 /* MAXMB - FIFO */ - ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2);
  386. if ( FLEXCANb_MAXMB_SIZE(_bus) < (6 + ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2))) remaining_mailboxes = 0;
  387. return (FLEXCANb_MAXMB_SIZE(_bus) - remaining_mailboxes); /* otherwise return offset MB position after FIFO area */
  388. }
  389. FCTP_FUNC void FCTP_OPT::setMaxMB(uint8_t last) {
  390. last = constrain(last,1,64);
  391. last--;
  392. FLEXCAN_EnterFreezeMode();
  393. bool fifo_was_cleared = FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN;
  394. disableFIFO();
  395. writeIFLAG(readIFLAG()); // (all bits reset when written back) (needed for MAXMB changes)
  396. FLEXCANb_MCR(_bus) &= ~0x7F; // clear current value
  397. FLEXCANb_MCR(_bus) |= last; // set mailbox max
  398. if ( fifo_was_cleared ) enableFIFO();
  399. FLEXCAN_ExitFreezeMode();
  400. }
  401. FCTP_FUNC void FCTP_OPT::softReset() {
  402. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_SOFT_RST;
  403. while (FLEXCANb_MCR(_bus) & FLEXCAN_MCR_SOFT_RST);
  404. }
  405. FCTP_FUNC void FCTP_OPT::FLEXCAN_ExitFreezeMode() {
  406. FLEXCANb_MCR(_bus) &= ~FLEXCAN_MCR_HALT;
  407. while (FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  408. }
  409. FCTP_FUNC void FCTP_OPT::FLEXCAN_EnterFreezeMode() {
  410. FLEXCANb_MCR(_bus) |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT;
  411. while (!(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK));
  412. }
  413. FCTP_FUNC void FCTP_OPT::setBaudRate(uint32_t baud, FLEXCAN_RXTX listen_only) {
  414. currentBitrate = baud;
  415. #if defined(__IMXRT1062__)
  416. uint32_t clockFreq = getClock() * 1000000;
  417. #else
  418. uint32_t clockFreq = 16000000;
  419. #endif
  420. uint32_t divisor = 0, bestDivisor = 0, result = clockFreq / baud / (divisor + 1);
  421. int error = baud - (clockFreq / (result * (divisor + 1))), bestError = error;
  422. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  423. FLEXCAN_EnterFreezeMode();
  424. while (result > 5) {
  425. divisor++;
  426. result = clockFreq / baud / (divisor + 1);
  427. if (result <= 25) {
  428. error = baud - (clockFreq / (result * (divisor + 1)));
  429. if (error < 0) error *= -1;
  430. if (error < bestError) {
  431. bestError = error;
  432. bestDivisor = divisor;
  433. }
  434. if ((error == bestError) && (result > 11) && (result < 19)) {
  435. bestError = error;
  436. bestDivisor = divisor;
  437. }
  438. }
  439. }
  440. divisor = bestDivisor;
  441. result = clockFreq / baud / (divisor + 1);
  442. if ((result < 5) || (result > 25) || (bestError > 300)) {
  443. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  444. return;
  445. }
  446. result -= 5; // the bitTimingTable is offset by 5 since there was no reason to store bit timings for invalid numbers
  447. uint8_t bitTimingTable[21][3] = {
  448. {0, 0, 1}, //5
  449. {1, 0, 1}, //6
  450. {1, 1, 1}, //7
  451. {2, 1, 1}, //8
  452. {2, 2, 1}, //9
  453. {2, 3, 1}, //10
  454. {2, 3, 2}, //11
  455. {2, 4, 2}, //12
  456. {2, 5, 2}, //13
  457. {2, 5, 3}, //14
  458. {2, 6, 3}, //15
  459. {2, 7, 3}, //16
  460. {2, 7, 4}, //17
  461. {3, 7, 4}, //18
  462. {3, 7, 5}, //19
  463. {4, 7, 5}, //20
  464. {4, 7, 6}, //21
  465. {5, 7, 6}, //22
  466. {6, 7, 6}, //23
  467. {6, 7, 7}, //24
  468. {7, 7, 7}, //25
  469. }, propSeg = bitTimingTable[result][0], pSeg1 = bitTimingTable[result][1], pSeg2 = bitTimingTable[result][2];
  470. FLEXCANb_CTRL1(_bus) = (FLEXCAN_CTRL_PROPSEG(propSeg) | FLEXCAN_CTRL_RJW(1) | FLEXCAN_CTRL_PSEG1(pSeg1) |
  471. FLEXCAN_CTRL_PSEG2(pSeg2) | FLEXCAN_CTRL_ERR_MSK | FLEXCAN_CTRL_PRESDIV(divisor));
  472. ( listen_only != LISTEN_ONLY ) ? FLEXCANb_CTRL1(_bus) &= ~FLEXCAN_CTRL_LOM : FLEXCANb_CTRL1(_bus) |= FLEXCAN_CTRL_LOM; /* listen-only mode */
  473. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  474. }
  475. FCTP_FUNC void FCTP_OPT::setMRP(bool mrp) { /* mailbox priority (1) or FIFO priority (0) */
  476. FLEXCAN_EnterFreezeMode();
  477. if ( mrp ) FLEXCANb_CTRL2(_bus) |= FLEXCAN_CTRL2_MRP;
  478. else FLEXCANb_CTRL2(_bus) &= ~FLEXCAN_CTRL2_MRP;
  479. FLEXCAN_ExitFreezeMode();
  480. }
  481. FCTP_FUNC void FCTP_OPT::setRRS(bool rrs) { /* store remote frames */
  482. FLEXCAN_EnterFreezeMode();
  483. if ( rrs ) FLEXCANb_CTRL2(_bus) |= FLEXCAN_CTRL2_RRS;
  484. else FLEXCANb_CTRL2(_bus) &= ~FLEXCAN_CTRL2_RRS;
  485. FLEXCAN_ExitFreezeMode();
  486. }
  487. FCTP_FUNC void FCTP_OPT::setTX(FLEXCAN_PINS pin) {
  488. #if defined(__IMXRT1062__)
  489. if ( _bus == CAN3 ) {
  490. if ( pin == DEF ) {
  491. IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_36 = 0x19; // pin31 T3B2
  492. IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_36 = 0x10B0; // pin31 T3B2
  493. }
  494. }
  495. if ( _bus == CAN2 ) {
  496. if ( pin == DEF ) {
  497. IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02 = 0x10; // pin 1 T4B1+B2
  498. IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_02 = 0x10B0; // pin 1 T4B1+B2
  499. }
  500. }
  501. if ( _bus == CAN1 ) {
  502. if ( pin == DEF ) {
  503. IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08 = 0x12; // pin 22 T4B1+B2
  504. IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_08 = 0x10B0; // pin 22 T4B1+B2
  505. }
  506. if ( pin == ALT ) {
  507. IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 0x12; // pin 11 T4B1+B2
  508. IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02= 0x10B0; // pin 11 T4B1+B2
  509. }
  510. }
  511. #endif
  512. #if defined(__MK20DX256__)
  513. CORE_PIN3_CONFIG = PORT_PCR_MUX(2);
  514. #endif
  515. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  516. if ( _bus == CAN0 ) {
  517. if ( pin == ALT ) {
  518. CORE_PIN3_CONFIG = 0; CORE_PIN29_CONFIG = PORT_PCR_MUX(2);
  519. }
  520. else if ( pin == DEF ) {
  521. CORE_PIN29_CONFIG = 0; CORE_PIN3_CONFIG = PORT_PCR_MUX(2);
  522. }
  523. } /* Alternative CAN1 pins are not broken out on Teensy 3.6 */
  524. #endif
  525. #if defined(__MK66FX1M0__)
  526. if ( _bus == CAN1 ) {
  527. CORE_PIN33_CONFIG = PORT_PCR_MUX(2);
  528. }
  529. #endif
  530. }
  531. FCTP_FUNC void FCTP_OPT::setRX(FLEXCAN_PINS pin) {
  532. #if defined(__IMXRT1062__)
  533. /* DAISY REGISTER CAN3
  534. 00 GPIO_EMC_37_ALT9 — Selecting Pad: GPIO_EMC_37 for Mode: ALT9
  535. 01 GPIO_AD_B0_15_ALT8 — Selecting Pad: GPIO_AD_B0_15 for Mode: ALT8
  536. 10 GPIO_AD_B0_11_ALT8 — Selecting Pad: GPIO_AD_B0_11 for Mode: ALT8
  537. */
  538. /* DAISY REGISTER CAN2
  539. 00 GPIO_EMC_10_ALT3 — Selecting Pad: GPIO_EMC_10 for Mode: ALT3
  540. 01 GPIO_AD_B0_03_ALT0 — Selecting Pad: GPIO_AD_B0_03 for Mode: ALT0
  541. 10 GPIO_AD_B0_15_ALT6 — Selecting Pad: GPIO_AD_B0_15 for Mode: ALT6
  542. 11 GPIO_B1_09_ALT6 — Selecting Pad: GPIO_B1_09 for Mode: ALT6
  543. */
  544. /* DAISY REGISTER CAN1
  545. 00 GPIO_SD_B1_03_ALT4 — Selecting Pad: GPIO_SD_B1_03 for Mode: ALT4
  546. 01 GPIO_EMC_18_ALT3 — Selecting Pad: GPIO_EMC_18 for Mode: ALT3
  547. 10 GPIO_AD_B1_09_ALT2 — Selecting Pad: GPIO_AD_B1_09 for Mode: ALT2
  548. 11 GPIO_B0_03_ALT2 — Selecting Pad: GPIO_B0_03 for Mode: ALT2
  549. */
  550. if ( _bus == CAN3 ) {
  551. if ( pin == DEF ) {
  552. IOMUXC_CANFD_IPP_IND_CANRX_SELECT_INPUT = 0x00;
  553. IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_37 = 0x19; // pin30 T3B2
  554. IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_37 = 0x10B0; // pin30 T3B2
  555. }
  556. }
  557. if ( _bus == CAN2 ) {
  558. if ( pin == DEF ) {
  559. IOMUXC_FLEXCAN2_RX_SELECT_INPUT = 0x01;
  560. IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03 = 0x10; // pin 0 T4B1+B2
  561. IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_03 = 0x10B0; // pin 0 T4B1+B2
  562. }
  563. }
  564. if ( _bus == CAN1 ) {
  565. if ( pin == DEF ) {
  566. IOMUXC_FLEXCAN1_RX_SELECT_INPUT = 0x02;
  567. IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09 = 0x12; // pin 23 T4B1+B2
  568. IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 = 0x10B0; // pin 23 T4B1+B2
  569. }
  570. if ( pin == ALT ) {
  571. IOMUXC_FLEXCAN1_RX_SELECT_INPUT = 0x03;
  572. IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 0x12; // pin 13 T4B1+B2
  573. IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = 0x10B0; // pin 13 T4B1+B2
  574. }
  575. }
  576. #endif
  577. #if defined(__MK20DX256__)
  578. CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
  579. #endif
  580. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  581. if ( _bus == CAN0 ) {
  582. if ( pin == ALT ) {
  583. CORE_PIN4_CONFIG = 0; CORE_PIN30_CONFIG = PORT_PCR_MUX(2);
  584. }
  585. else if ( pin == DEF ) {
  586. CORE_PIN30_CONFIG = 0; CORE_PIN4_CONFIG = PORT_PCR_MUX(2);
  587. }
  588. } /* Alternative CAN1 pins are not broken out on Teensy 3.6 */
  589. #endif
  590. #if defined(__MK66FX1M0__)
  591. if ( _bus == CAN1 ) {
  592. CORE_PIN34_CONFIG = PORT_PCR_MUX(2);
  593. }
  594. #endif
  595. }
  596. FCTP_FUNC void FCTP_OPT::setMBFilterProcessing(FLEXCAN_MAILBOX mb_num, uint32_t filter_id, uint32_t calculated_mask) {
  597. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  598. FLEXCAN_EnterFreezeMode();
  599. FLEXCANb_RXIMR(_bus, mb_num) = calculated_mask | ((FLEXCANb_CTRL2(_bus) & FLEXCAN_CTRL2_EACEN) ? (1UL << 30) : 0);
  600. FLEXCANb_MBn_ID(_bus, mb_num) = ((!(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE)) ? FLEXCAN_MB_ID_IDSTD(filter_id) : FLEXCAN_MB_ID_IDEXT(filter_id));
  601. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  602. }
  603. FCTP_FUNC void FCTP_OPT::setMBFilter(FLEXCAN_FLTEN input) {
  604. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  605. FLEXCAN_EnterFreezeMode();
  606. for (uint8_t i = mailboxOffset(); i < FLEXCANb_MAXMB_SIZE(_bus); i++) {
  607. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, i)) >> 3) ) continue; /* skip TX mailboxes */
  608. if ( input == ACCEPT_ALL ) FLEXCANb_RXIMR(_bus, i) = 0UL | ((FLEXCANb_CTRL2(_bus) & FLEXCAN_CTRL2_EACEN) ? (1UL << 30) : 0); // (RXIMR)
  609. if ( input == REJECT_ALL ) FLEXCANb_RXIMR(_bus, i) = ~0UL; // (RXIMR)
  610. FLEXCANb_MBn_ID(_bus, i) = ~0UL;
  611. mb_filter_table[i][0] = ( ((FLEXCANb_MBn_CS(_bus, i) & 0x600000) ? 1UL : 0UL) << 27); /* extended flag check */
  612. }
  613. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  614. }
  615. FCTP_FUNC void FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, FLEXCAN_FLTEN input) {
  616. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return; /* mailbox not available */
  617. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return; /* exit on TX mailbox */
  618. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  619. FLEXCAN_EnterFreezeMode();
  620. if ( input == ACCEPT_ALL ) FLEXCANb_RXIMR(_bus, mb_num) = 0UL | ((FLEXCANb_CTRL2(_bus) & FLEXCAN_CTRL2_EACEN) ? (1UL << 30) : 0); // (RXIMR)
  621. if ( input == REJECT_ALL ) FLEXCANb_RXIMR(_bus, mb_num) = ~0UL; // (RXIMR)
  622. FLEXCANb_MBn_ID(_bus, mb_num) = 0UL;
  623. mb_filter_table[mb_num][0] = ( ((FLEXCANb_MBn_CS(_bus, mb_num) & 0x600000) ? 1UL : 0UL) << 27); /* extended flag check */
  624. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  625. }
  626. FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1) {
  627. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  628. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  629. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1) ^ (id1)) ^ 0x7FF) : FLEXCAN_MB_ID_IDEXT(((id1) ^ (id1)) ^ 0x1FFFFFFF);
  630. setMBFilterProcessing(mb_num,id1,mask);
  631. filter_store(FLEXCAN_MULTI, mb_num, 1, id1, 0, 0, 0, 0);
  632. return 1;
  633. }
  634. FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2) {
  635. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  636. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  637. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1 | id2) ^ (id1 & id2)) ^ 0x7FF) : FLEXCAN_MB_ID_IDEXT(((id1 | id2) ^ (id1 & id2)) ^ 0x1FFFFFFF);
  638. setMBFilterProcessing(mb_num,id1,mask);
  639. filter_store(FLEXCAN_MULTI, mb_num, 2, id1, id2, 0, 0, 0);
  640. return 1;
  641. }
  642. FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3) {
  643. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  644. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  645. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1 | id2 | id3) ^ (id1 & id2 & id3)) ^ 0x7FF) : FLEXCAN_MB_ID_IDEXT(((id1 | id2 | id3) ^ (id1 & id2 & id3)) ^ 0x1FFFFFFF);
  646. setMBFilterProcessing(mb_num,id1,mask);
  647. filter_store(FLEXCAN_MULTI, mb_num, 3, id1, id2, id3, 0, 0);
  648. return 1;
  649. }
  650. FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4) {
  651. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  652. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  653. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1 | id2 | id3 | id4) ^ (id1 & id2 & id3 & id4)) ^ 0x7FF) : FLEXCAN_MB_ID_IDEXT(((id1 | id2 | id3 | id4) ^ (id1 & id2 & id3 & id4)) ^ 0x1FFFFFFF);
  654. setMBFilterProcessing(mb_num,id1,mask);
  655. filter_store(FLEXCAN_MULTI, mb_num, 4, id1, id2, id3, id4, 0);
  656. return 1;
  657. }
  658. FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t id5) {
  659. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  660. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  661. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1 | id2 | id3 | id4 | id5) ^ (id1 & id2 & id3 & id4 & id5)) ^ 0x7FF) : FLEXCAN_MB_ID_IDEXT(((id1 | id2 | id3 | id4 | id5) ^ (id1 & id2 & id3 & id4 & id5)) ^ 0x1FFFFFFF);
  662. setMBFilterProcessing(mb_num,id1,mask);
  663. filter_store(FLEXCAN_MULTI, mb_num, 5, id1, id2, id3, id4, id5);
  664. return 1;
  665. }
  666. FCTP_FUNC bool FCTP_OPT::setMBFilterRange(FLEXCAN_MAILBOX mb_num, uint32_t id1, uint32_t id2) {
  667. if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
  668. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */
  669. if ( id1 > id2 || ((id2 > id1) && (id2-id1>1000)) || !id1 || !id2 ) return 0; /* don't play around... */
  670. uint32_t stage1 = id1, stage2 = id1;
  671. for ( uint32_t i = id1 + 1; i <= id2; i++ ) {
  672. stage1 |= i; stage2 &= i;
  673. }
  674. uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD( (stage1 ^ stage2) ^ 0x1FFFFFFF ) : FLEXCAN_MB_ID_IDEXT( (stage1 ^ stage2) ^ 0x1FFFFFFF );
  675. setMBFilterProcessing(mb_num,id1,mask);
  676. filter_store(FLEXCAN_RANGE, mb_num, 2, id1, id2, 0, 0, 0);
  677. return 1;
  678. }
  679. FCTP_FUNC int FCTP_OPT::readFIFO(CAN_message_t &msg) {
  680. delayMicroseconds(150);
  681. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN) ) return 0; /* FIFO is disabled */
  682. if ( !(FLEXCANb_MCR(_bus) & (1UL << 15)) ) { /* if DMA is not enabled, check interrupt flag, else continue. */
  683. if ( FLEXCANb_IMASK1(_bus) & FLEXCAN_IMASK1_BUF5M ) return 0; /* FIFO interrupt enabled, polling blocked */
  684. }
  685. if ( FLEXCANb_IFLAG1(_bus) & FLEXCAN_IFLAG1_BUF5I ) { /* message available */
  686. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80));
  687. uint32_t code = mbxAddr[0];
  688. msg.len = (code & 0xF0000) >> 16;
  689. msg.flags.remote = (bool)(code & (1UL << 20));
  690. msg.flags.extended = (bool)(code & (1UL << 21));
  691. msg.timestamp = code & 0xFFFF;
  692. msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
  693. uint32_t data0 = mbxAddr[2];
  694. for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[3 - d] = (uint8_t)(data0 >> (8 * d));
  695. uint32_t data1 = mbxAddr[3];
  696. for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[7 - d] = (uint8_t)(data1 >> (8 * d));
  697. msg.bus = busNumber;
  698. msg.idhit = (uint8_t)(FLEXCANb_RXFIR(_bus) & 0x1FF);
  699. msg.mb = FIFO; /* store the mailbox the message came from (for callback reference) */
  700. if ( !(FLEXCANb_MCR(_bus) & (1UL << 15)) ) writeIFLAGBit(5); /* clear FIFO bit only, NOT FOR DMA USE! */
  701. frame_distribution(msg);
  702. if ( filter_match((FLEXCAN_MAILBOX)msg.mb, msg.id) ) return 1;
  703. }
  704. return 0; /* message not available */
  705. }
  706. FCTP_FUNC int FCTP_OPT::getFirstTxBox() {
  707. for (uint8_t i = mailboxOffset(); i < FLEXCANb_MAXMB_SIZE(_bus); i++) {
  708. if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, i)) >> 3) ) return i; // if TX
  709. }
  710. return -1;
  711. }
  712. FCTP_FUNC int FCTP_OPT::read(CAN_message_t &msg) {
  713. bool _random = random(0, 2);
  714. if ( ( !_random ) && ( FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN ) &&
  715. !( FLEXCANb_IMASK1(_bus) & FLEXCAN_IMASK1_BUF5M ) &&
  716. ( FLEXCANb_IFLAG1(_bus) & FLEXCAN_IFLAG1_BUF5I ) ) return readFIFO(msg);
  717. return readMB(msg);
  718. }
  719. FCTP_FUNC int FCTP_OPT::readMB(CAN_message_t &msg) {
  720. uint64_t iflag = 0;
  721. for ( uint8_t cycle_limit = 3, mailboxes = mailboxOffset(); mailbox_reader_increment <= FLEXCANb_MAXMB_SIZE(_bus); ++mailbox_reader_increment ) {
  722. iflag = readIFLAG();
  723. if ( iflag && (mailbox_reader_increment >= (64 - __builtin_clzll(iflag))) ) { /* break from MSB's if unset, add 1 to prevent undefined behaviour in clz for 0 check */
  724. mailbox_reader_increment = mailboxOffset();
  725. if ( !--cycle_limit ) return 0;
  726. }
  727. if ( FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN ) { /* FIFO is enabled, get only remaining RX (if any) */
  728. if ( mailbox_reader_increment < mailboxes ) mailbox_reader_increment = mailboxes - 1; /* go back to position end of fifo+filter region */
  729. }
  730. if ( mailbox_reader_increment >= FLEXCANb_MAXMB_SIZE(_bus) ) {
  731. mailbox_reader_increment = mailboxOffset();
  732. if ( !--cycle_limit ) return 0;
  733. }
  734. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mailbox_reader_increment * 0x10)));
  735. if ((readIMASK() & (1ULL << mailbox_reader_increment))) continue; /* don't read interrupt enabled mailboxes */
  736. uint32_t code = mbxAddr[0];
  737. if ( (FLEXCAN_get_code(code) >> 3) ) continue; /* skip TX mailboxes */
  738. //if (!(code & 0x600000) && !(iflag & (1ULL << mailbox_reader_increment))) continue; /* don't read unflagged mailboxes, errata: extended mailboxes iflags do not work in poll mode, must check CS field */
  739. if ( ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_FULL ) ||
  740. ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) ) {
  741. msg.flags.remote = (bool)(code & (1UL << 20));
  742. msg.flags.extended = (bool)(code & (1UL << 21));
  743. msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
  744. if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) msg.flags.overrun = 1;
  745. msg.len = (code & 0xF0000) >> 16;
  746. msg.mb = mailbox_reader_increment++;
  747. msg.timestamp = code & 0xFFFF;
  748. msg.bus = busNumber;
  749. for ( uint8_t i = 0; i < (8 >> 2); i++ ) for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[(4 * i) + 3 - d] = (uint8_t)(mbxAddr[2 + i] >> (8 * d));
  750. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | ((msg.flags.extended) ? (FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE) : 0);
  751. (void)FLEXCANb_TIMER(_bus);
  752. writeIFLAGBit(msg.mb);
  753. frame_distribution(msg);
  754. if ( filter_match((FLEXCAN_MAILBOX)msg.mb, msg.id) ) return 1;
  755. }
  756. }
  757. return 0; /* no messages available */
  758. }
  759. FCTP_FUNC void FCTP_OPT::struct2queueTx(const CAN_message_t &msg) {
  760. uint8_t buf[sizeof(CAN_message_t)];
  761. memmove(buf, &msg, sizeof(msg));
  762. txBuffer.push_back(buf, sizeof(CAN_message_t));
  763. }
  764. FCTP_FUNC int FCTP_OPT::write(FLEXCAN_MAILBOX mb_num, const CAN_message_t &msg) {
  765. if ( mb_num < mailboxOffset() ) return 0; /* FIFO doesn't transmit */
  766. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mb_num * 0x10)));
  767. if ( !((FLEXCAN_get_code(mbxAddr[0])) >> 3) ) return 0; /* not a transmit mailbox */
  768. if ( msg.seq && FLEXCAN_get_code(mbxAddr[0]) != FLEXCAN_MB_CODE_TX_INACTIVE ) return 0; /* non blocking resend sequential frames */
  769. uint32_t timeout = millis();
  770. while ( FLEXCAN_get_code(mbxAddr[0]) != FLEXCAN_MB_CODE_TX_INACTIVE ) {
  771. if ( millis() - timeout > 100 ) return 0;
  772. }
  773. writeTxMailbox(mb_num, msg);
  774. return 1; // transmit entry accepted //
  775. }
  776. FCTP_FUNC int FCTP_OPT::write(const CAN_message_t &msg) {
  777. if ( msg.seq ) {
  778. if ( !write((FLEXCAN_MAILBOX)getFirstTxBox(), msg) ) struct2queueTx(msg);
  779. return 1;
  780. }
  781. for (uint8_t i = mailboxOffset(); i < FLEXCANb_MAXMB_SIZE(_bus); i++) {
  782. if ( FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, i)) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
  783. writeTxMailbox(i, msg);
  784. return 1; /* transmit entry accepted */
  785. }
  786. }
  787. return 0; /* transmit entry failed, no mailboxes or queues available */
  788. }
  789. FCTP_FUNC void FCTP_OPT::onReceive(const FLEXCAN_MAILBOX &mb_num, _MB_ptr handler) {
  790. if ( FIFO == mb_num ) {
  791. _mbHandlers[0] = handler;
  792. return;
  793. }
  794. _mbHandlers[mb_num] = handler;
  795. }
  796. FCTP_FUNC void FCTP_OPT::onReceive(_MB_ptr handler) {
  797. _mainHandler = handler;
  798. }
  799. FCTP_FUNC uint64_t FCTP_OPT::events() {
  800. if ( rxBuffer.size() ) {
  801. CAN_message_t frame;
  802. uint8_t buf[sizeof(CAN_message_t)];
  803. rxBuffer.pop_front(buf, sizeof(CAN_message_t));
  804. memmove(&frame, buf, sizeof(frame));
  805. mbCallbacks((FLEXCAN_MAILBOX)frame.mb, frame);
  806. }
  807. if ( txBuffer.size() ) {
  808. CAN_message_t frame;
  809. uint8_t buf[sizeof(CAN_message_t)];
  810. txBuffer.peek_front(buf, sizeof(CAN_message_t));
  811. memmove(&frame, buf, sizeof(frame));
  812. if ( write((FLEXCAN_MAILBOX)getFirstTxBox(), frame) ) txBuffer.pop_front();
  813. }
  814. return (uint64_t)(rxBuffer.size() << 12) | txBuffer.size();
  815. }
  816. #if defined(__IMXRT1062__)
  817. static void flexcan_isr_can1() {
  818. if ( _CAN1 ) _CAN1->flexcan_interrupt();
  819. }
  820. static void flexcan_isr_can2() {
  821. if ( _CAN2 ) _CAN2->flexcan_interrupt();
  822. }
  823. static void flexcan_isr_can3() {
  824. if ( _CAN3 ) _CAN3->flexcan_interrupt();
  825. }
  826. #endif
  827. #if defined(__MK20DX256__) || defined(__MK64FX512__)
  828. static void flexcan_isr_can0() {
  829. if ( _CAN0 ) _CAN0->flexcan_interrupt();
  830. }
  831. #endif
  832. #if defined(__MK66FX1M0__)
  833. static void flexcan_isr_can0() {
  834. if ( _CAN0 ) _CAN0->flexcan_interrupt();
  835. }
  836. static void flexcan_isr_can1() {
  837. if ( _CAN1 ) _CAN1->flexcan_interrupt();
  838. }
  839. #endif
  840. FCTP_FUNC void FCTP_OPT::mbCallbacks(const FLEXCAN_MAILBOX &mb_num, const CAN_message_t &msg) {
  841. if ( mb_num == FIFO ) {
  842. if ( _mbHandlers[0] ) _mbHandlers[0](msg);
  843. if ( _mainHandler ) _mainHandler(msg);
  844. return;
  845. }
  846. if ( _mbHandlers[mb_num] ) _mbHandlers[mb_num](msg);
  847. if ( _mainHandler ) _mainHandler(msg);
  848. }
  849. FCTP_FUNC void FCTP_OPT::struct2queueRx(const CAN_message_t &msg) {
  850. uint8_t buf[sizeof(CAN_message_t)];
  851. memmove(buf, &msg, sizeof(msg));
  852. rxBuffer.push_back(buf, sizeof(CAN_message_t));
  853. }
  854. FCTP_FUNC void FCTP_OPT::flexcan_interrupt() {
  855. CAN_message_t msg; // setup a temporary storage buffer
  856. uint64_t imask = readIMASK(), iflag = readIFLAG();
  857. if ( !(FLEXCANb_MCR(_bus) & (1UL << 15)) ) { /* if DMA is disabled, ONLY THEN you can handle FIFO in ISR */
  858. if ( (FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN) && (imask & FLEXCAN_IMASK1_BUF5M) && (iflag & FLEXCAN_IFLAG1_BUF5I) ) { /* FIFO is enabled, capture frames if triggered */
  859. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (0 * 0x10)));
  860. uint32_t code = mbxAddr[0];
  861. msg.len = (code & 0xF0000) >> 16;
  862. msg.flags.remote = (bool)(code & (1UL << 20));
  863. msg.flags.extended = (bool)(code & (1UL << 21));
  864. msg.timestamp = code & 0xFFFF;
  865. msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
  866. msg.idhit = code >> 23;
  867. for ( uint8_t i = 0; i < (8 >> 2); i++ ) for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[(4 * i) + 3 - d] = (uint8_t)(mbxAddr[2 + i] >> (8 * d));
  868. msg.bus = busNumber;
  869. msg.mb = FIFO; /* store the mailbox the message came from (for callback reference) */
  870. (void)FLEXCANb_TIMER(_bus);
  871. writeIFLAGBit(5); /* clear FIFO bit only! */
  872. if ( iflag & FLEXCAN_IFLAG1_BUF6I ) writeIFLAGBit(6); /* clear FIFO bit only! */
  873. if ( iflag & FLEXCAN_IFLAG1_BUF7I ) writeIFLAGBit(7); /* clear FIFO bit only! */
  874. frame_distribution(msg);
  875. ext_output1(msg);
  876. ext_output2(msg);
  877. ext_output3(msg);
  878. if (fifo_filter_match(msg.id)) struct2queueRx(msg);
  879. }
  880. }
  881. uint8_t exit_point = 64 - __builtin_clzll(iflag | 1); /* break from MSB's if unset, add 1 to prevent undefined behaviour in clz for 0 check */
  882. for ( uint8_t mb_num = mailboxOffset(); mb_num < FLEXCANb_MAXMB_SIZE(_bus); mb_num++ ) {
  883. if ( mb_num >= exit_point ) break; /* early exit from higher unflagged mailboxes */
  884. if (!(imask & (1ULL << mb_num))) continue; /* don't read non-interrupt mailboxes */
  885. if (!(iflag & (1ULL << mb_num))) continue; /* don't read unflagged mailboxes */
  886. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mb_num * 0x10)));
  887. uint32_t code = mbxAddr[0];
  888. if ( ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_FULL ) ||
  889. ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) ) {
  890. msg.flags.extended = (bool)(code & (1UL << 21));
  891. msg.id = (mbxAddr[1] & 0x1FFFFFFF) >> ((msg.flags.extended) ? 0 : 18);
  892. if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_RX_OVERRUN ) msg.flags.overrun = 1;
  893. msg.len = (code & 0xF0000) >> 16;
  894. msg.mb = mb_num;
  895. msg.timestamp = code & 0xFFFF;
  896. msg.bus = busNumber;
  897. for ( uint8_t i = 0; i < (8 >> 2); i++ ) for ( int8_t d = 0; d < 4 ; d++ ) msg.buf[(4 * i) + 3 - d] = (uint8_t)(mbxAddr[2 + i] >> (8 * d));
  898. mbxAddr[0] = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY) | ((msg.flags.extended) ? (FLEXCAN_MB_CS_SRR | FLEXCAN_MB_CS_IDE) : 0);
  899. (void)FLEXCANb_TIMER(_bus);
  900. writeIFLAGBit(mb_num);
  901. if ( filter_match((FLEXCAN_MAILBOX)mb_num, msg.id) ) struct2queueRx(msg); /* store frame in queue */
  902. frame_distribution(msg);
  903. ext_output1(msg);
  904. ext_output2(msg);
  905. ext_output3(msg);
  906. }
  907. if ( FLEXCAN_get_code(code) == FLEXCAN_MB_CODE_TX_INACTIVE ) {
  908. writeIFLAGBit(mb_num); /* clear IFLAG, currently unused */
  909. }
  910. }
  911. FLEXCANb_ESR1(_bus) |= FLEXCANb_ESR1(_bus);
  912. }
  913. FCTP_FUNC void FCTP_OPT::enableDMA(bool state) { /* only CAN3 supports this on 1062, untested */
  914. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  915. FLEXCAN_EnterFreezeMode();
  916. ( !state ) ? FLEXCANb_MCR(_bus) &= ~0x8000 : FLEXCANb_MCR(_bus) |= 0x8000;
  917. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  918. }
  919. FCTP_FUNC uint8_t FCTP_OPT::setRFFN(FLEXCAN_RFFN_TABLE rffn) {
  920. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  921. FLEXCAN_EnterFreezeMode();
  922. FLEXCAN_set_rffn(FLEXCANb_CTRL2(_bus), rffn);
  923. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  924. uint32_t remaining_mailboxes = FLEXCANb_MAXMB_SIZE(_bus) - 6 /* MAXMB - FIFO */ - ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2);
  925. if ( FLEXCANb_MAXMB_SIZE(_bus) < (6 + ((((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 2))) remaining_mailboxes = 0;
  926. return constrain((uint8_t)(FLEXCANb_MAXMB_SIZE(_bus) - remaining_mailboxes), 0, 32);
  927. }
  928. FCTP_FUNC void FCTP_OPT::setFIFOFilter(const FLEXCAN_FLTEN &input) {
  929. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return; /* FIFO not enabled. */
  930. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  931. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  932. FLEXCAN_EnterFreezeMode();
  933. for (uint8_t i = 0; i < max_fifo_filters; i++) { /* block all ID's so filtering could be applied. */
  934. if ( input == REJECT_ALL ) {
  935. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 0 ) { /* If Table A is chosen for FIFO */
  936. FLEXCANb_IDFLT_TAB(_bus, i) = 0xFFFFFFFF; /* reset id */
  937. /* individual masks (RXIMR) will just cover Rx FIFO filters in 0-31 range, and filters 32-127
  938. will use RXFGMASK. */
  939. if ( i < constrain(mailboxOffset(), 0, 32) ) FLEXCANb_RXIMR(_bus, i) = 0x3FFFFFFF; // (RXIMR) /* block all id's (0-31) */
  940. FLEXCANb_RXFGMASK(_bus) = 0x3FFFFFFF;
  941. }
  942. else if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) { /* If Table B is chosen for FIFO */
  943. FLEXCANb_IDFLT_TAB(_bus, i) = 0xFFFFFFFF; /* reset id */
  944. if ( i < constrain(mailboxOffset(), 0, 32) ) FLEXCANb_RXIMR(_bus, i) = 0x7FFF7FFF; // (RXIMR) /* block all id's (0-31) */
  945. FLEXCANb_RXFGMASK(_bus) = 0x7FFF7FFF;
  946. }
  947. else if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 2 ) { /* If Table C is chosen for FIFO */
  948. /* TO BE DONE */ //FLEXCANb_IDFLT_TAB(_bus, i) = 0x6E6E6E6E; /* reset id */
  949. //FLEXCANb_RXIMR(_bus, i) = 0xFFFFFFFF; // (RXIMR) /* block all id's */
  950. }
  951. }
  952. else if ( input == ACCEPT_ALL ) {
  953. FLEXCANb_IDFLT_TAB(_bus, i) = 0; /* reset id */
  954. if ( i < constrain(mailboxOffset(), 0, 32) ) FLEXCANb_RXIMR(_bus, i) = 0; // (RXIMR) /* allow all id's */
  955. FLEXCANb_RXFGMASK(_bus) = 0; /* for masks above IDF 0->31, global is used for rest) */
  956. }
  957. }
  958. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  959. }
  960. FCTP_FUNC bool FCTP_OPT::setFIFOFilter(uint8_t filter, uint32_t id1, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote) {
  961. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  962. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  963. if ( filter >= max_fifo_filters ) return 0;
  964. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  965. FLEXCAN_EnterFreezeMode();
  966. /* ##################################### TABLE A ###################################### */
  967. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 0 ) {
  968. uint32_t mask = ( ide != EXT ) ? ((((id1) ^ (id1)) ^ 0x7FF) << 19 ) | 0xC0000001 : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) << 1 ) | 0xC0000001;
  969. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide == EXT ? 1 : 0) << 30) | ((remote == RTR ? 1 : 0) << 31) |
  970. ((ide == EXT ? ((id1 & FLEXCAN_MB_ID_EXT_MASK) << 1) : (FLEXCAN_MB_ID_IDSTD(id1) << 1)));
  971. if ( filter < constrain(mailboxOffset(), 0, 32) ) FLEXCANb_RXIMR(_bus, filter) = mask;// | ((filter < (max_fifo_filters / 2)) ? 0 : (1UL << 30)); // (RXIMR)
  972. FLEXCANb_RXFGMASK(_bus) = 0x3FFFFFFF; /* enforce it for blocks 32->127, single IDs */
  973. fifo_filter_table[filter][0] = ( ((ide == EXT) ? 1UL : 0UL) << 16); /* extended flag check */
  974. fifo_filter_store(FLEXCAN_MULTI, filter, 1, id1, 0, 0, 0, 0);
  975. }
  976. /* #################################################################################### */
  977. /* ##################################### TABLE B ###################################### */
  978. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) {
  979. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide == EXT ? 1 : 0) << 30) | ((ide == EXT ? 1 : 0) << 14) | /* STD IDs / EXT IDs */
  980. ((remote == RTR ? 1 : 0) << 31) | ((remote == RTR ? 1 : 0) << 15) | /* remote frames */
  981. (ide == EXT ? ((id1 >> (29 - 14)) << 16) : ((id1 & 0x7FF) << 19)) | /* first ID is EXT or STD? */
  982. (ide == EXT ? ((id1 >> (29 - 14)) << 0) : ((id1 & 0x7FF) << 3)) ; /* second ID is EXT or STD? */
  983. uint32_t mask = ( ide != EXT ) ? ((((id1) ^ (id1)) ^ 0x7FF) << 19 ) | ((remote == RTR)?(1UL<<31):0UL) : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) << 16 ) | ((remote == RTR)?(1UL<<31):0UL);
  984. mask |= (( ide != EXT ) ? ((((id1) ^ (id1)) ^ 0x7FF) << 3 ) | ((remote == RTR)?(1UL<<15):0UL) : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) << 0 ) | ((remote == RTR)?(1UL<<15):0UL) ) & 0xFFFF;
  985. mask |= (1UL<<30) | (1UL<<14);
  986. if ( filter < constrain(mailboxOffset(), 0, 32) ) FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  987. FLEXCANb_RXFGMASK(_bus) = 0x7FFF7FFF; /* enforce it for blocks 32->127, single STD IDs / EXT partial matches */
  988. }
  989. /* #################################################################################### */
  990. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  991. return 1;
  992. }
  993. FCTP_FUNC void FCTP_OPT::fifo_filter_store(FLEXCAN_FILTER_TABLE type, uint8_t filter, uint32_t id_count, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t id5) {
  994. fifo_filter_table[filter][0] = (fifo_filter_table[filter][0] & 0xF0000) | filter; // first 7 bits reserved for fifo filter
  995. fifo_filter_table[filter][0] |= (id_count << 7); // we store the quantity of ids after the fifo filter count
  996. /* bit 16-19: extended ids */
  997. /* bit 28: filter enabled */
  998. fifo_filter_table[filter][0] |= (type << 29); // we reserve 3 upper bits for type
  999. fifo_filter_table[filter][1] = id1; // id1
  1000. fifo_filter_table[filter][2] = id2; // id2
  1001. fifo_filter_table[filter][3] = id3; // id3
  1002. fifo_filter_table[filter][4] = id4; // id4
  1003. fifo_filter_table[filter][5] = id5; // id5
  1004. }
  1005. FCTP_FUNC void FCTP_OPT::enhanceFilter(FLEXCAN_MAILBOX mb_num) {
  1006. if ( mb_num == FIFO && !(fifo_filter_table[0][0] & 0xE0000000) ) return;
  1007. else if ( !(mb_filter_table[mb_num][0] & 0xE0000000) ) return;
  1008. if ( mb_num == FIFO ) fifo_filter_table[0][0] |= (1UL << 28); /* enable fifo enhancement */
  1009. else mb_filter_table[mb_num][0] |= (1UL << 28); /* enable mb enhancement */
  1010. }
  1011. FCTP_FUNC volatile bool FCTP_OPT::fifo_filter_match(uint32_t id) {
  1012. if ( !(fifo_filter_table[0][0] & 0x10000000) ) return 1;
  1013. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1014. for (uint8_t mb_num = 0; mb_num < max_fifo_filters; mb_num++) { /* check fifo filters */
  1015. if ( (fifo_filter_table[mb_num][0] >> 29) == FLEXCAN_MULTI ) {
  1016. for ( uint8_t i = 0; i < ((fifo_filter_table[mb_num][0] & 0x380) >> 7); i++) if ( id == fifo_filter_table[mb_num][i+1] ) return 1;
  1017. }
  1018. else if ( (fifo_filter_table[mb_num][0] >> 29) == FLEXCAN_RANGE ) {
  1019. if ( id >= fifo_filter_table[mb_num][1] && id <= fifo_filter_table[mb_num][2] ) return 1;
  1020. }
  1021. }
  1022. return 0;
  1023. }
  1024. FCTP_FUNC volatile bool FCTP_OPT::filter_match(FLEXCAN_MAILBOX mb_num, uint32_t id) {
  1025. if ( !(mb_filter_table[mb_num][0] & 0x10000000) ) return 1;
  1026. if ( (mb_filter_table[mb_num][0] >> 29) == FLEXCAN_MULTI ) {
  1027. for ( uint8_t i = 0; i < ((mb_filter_table[mb_num][0] & 0x380) >> 7); i++) if ( id == mb_filter_table[mb_num][i+1] ) return 1;
  1028. }
  1029. else if ( (mb_filter_table[mb_num][0] >> 29) == FLEXCAN_RANGE ) {
  1030. if ( id >= mb_filter_table[mb_num][1] && id <= mb_filter_table[mb_num][2] ) return 1;
  1031. }
  1032. return 0;
  1033. }
  1034. FCTP_FUNC bool FCTP_OPT::setFIFOFilter(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote) {
  1035. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  1036. if ( filter > 31 ) return 0; /* multi-id & ranges are not allowed */
  1037. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1038. if ( filter >= max_fifo_filters ) return 0;
  1039. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1040. FLEXCAN_EnterFreezeMode();
  1041. /* ##################################### TABLE A ###################################### */
  1042. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 0 ) {
  1043. uint32_t mask = ( ide != EXT ) ? ((((id1 | id2) ^ (id1 & id2)) ^ 0x7FF) << 19 ) | 0xC0000001 : ((((id1 | id2) ^ (id1 & id2)) ^ 0x1FFFFFFF) << 1 ) | 0xC0000001;
  1044. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1045. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide == EXT ? 1 : 0) << 30) | ((remote == RTR ? 1 : 0) << 31) |
  1046. ((ide == EXT ? ((id1 & FLEXCAN_MB_ID_EXT_MASK) << 1) : (FLEXCAN_MB_ID_IDSTD(id1) << 1)));
  1047. fifo_filter_table[filter][0] = ( ((ide == EXT) ? 1UL : 0UL) << 16); /* extended flag check */
  1048. fifo_filter_store(FLEXCAN_MULTI, filter, 2, id1, id2, 0, 0, 0);
  1049. }
  1050. /* #################################################################################### */
  1051. /* ##################################### TABLE B ###################################### */
  1052. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) {
  1053. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide == EXT ? 1 : 0) << 30) | ((ide == EXT ? 1 : 0) << 14) | /* STD IDs / EXT IDs */
  1054. ((remote == RTR ? 1 : 0) << 31) | ((remote == RTR ? 1 : 0) << 15) | /* remote frames */
  1055. (ide == EXT ? ((id1 >> (29 - 14)) << 16) : ((id1 & 0x7FF) << 19)) | /* first ID is EXT or STD? */
  1056. (ide == EXT ? ((id2 >> (29 - 14)) << 0) : ((id2 & 0x7FF) << 3)) ; /* second ID is EXT or STD? */
  1057. uint32_t mask = ( ide != EXT ) ? ((((id1) ^ (id1)) ^ 0x7FF) << 19 ) | ((remote == RTR)?(1UL<<31):0UL) : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) << 16 ) | ((remote == RTR)?(1UL<<31):0UL);
  1058. mask |= (( ide != EXT ) ? ((((id2) ^ (id2)) ^ 0x7FF) << 3 ) | ((remote == RTR)?(1UL<<15):0UL) : ((((id2) ^ (id2)) ^ 0x1FFFFFFF) << 0 ) | ((remote == RTR)?(1UL<<15):0UL) ) & 0xFFFF;
  1059. mask |= (1UL<<30) | (1UL<<14);
  1060. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1061. }
  1062. /* #################################################################################### */
  1063. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1064. return 1;
  1065. }
  1066. FCTP_FUNC bool FCTP_OPT::setFIFOFilterRange(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide, const FLEXCAN_IDE &remote) {
  1067. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  1068. if ( filter > 31 ) return 0; /* multi-id & ranges are not allowed */
  1069. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1070. if ( filter >= max_fifo_filters ) return 0;
  1071. if ( id1 > id2 || ((id2 > id1) && (id2 - id1 > 1000)) || !id1 || !id2 ) return 0; /* don't play around... */
  1072. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1073. FLEXCAN_EnterFreezeMode();
  1074. /* ##################################### TABLE A ###################################### */
  1075. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 0 ) {
  1076. uint32_t stage1 = id1, stage2 = id1;
  1077. for ( uint32_t i = id1 + 1; i <= id2; i++ ) {
  1078. stage1 |= i; stage2 &= i;
  1079. }
  1080. uint32_t mask = ( ide != EXT ) ? (((stage1 ^ stage2) ^ 0x7FF) << 19) | 0xC0000001 : (((stage1 ^ stage2) ^ 0x1FFFFFFF) << 1) | 0xC0000001;
  1081. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1082. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide == EXT ? 1 : 0) << 30) | ((remote == RTR ? 1 : 0) << 31) |
  1083. ((ide == EXT ? ((id1 & FLEXCAN_MB_ID_EXT_MASK) << 1) : (FLEXCAN_MB_ID_IDSTD(id1) << 1)));
  1084. fifo_filter_table[filter][0] = ( ((ide == EXT) ? 1UL : 0UL) << 16); /* extended flag check */
  1085. fifo_filter_store(FLEXCAN_RANGE, filter, 2, id1, id2, 0, 0, 0);
  1086. }
  1087. /* #################################################################################### */
  1088. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1089. return 1;
  1090. }
  1091. FCTP_FUNC bool FCTP_OPT::setFIFOFilter(uint8_t filter, uint32_t id1, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id2, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2) {
  1092. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  1093. if ( filter > 31 ) return 0; /* multi-id & ranges are not allowed */
  1094. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1095. if ( filter >= max_fifo_filters ) return 0;
  1096. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1097. FLEXCAN_EnterFreezeMode();
  1098. /* ##################################### TABLE B ###################################### */
  1099. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) {
  1100. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide1 == EXT ? 1 : 0) << 30) | ((ide2 == EXT ? 1 : 0) << 14) | /* STD IDs / EXT IDs */
  1101. ((remote1 == RTR ? 1 : 0) << 31) | ((remote2 == RTR ? 1 : 0) << 15) | /* remote frames */
  1102. (ide1 == EXT ? ((id1 >> (29 - 14)) << 16) : ((id1 & 0x7FF) << 19)) | /* first ID is EXT or STD? */
  1103. (ide2 == EXT ? ((id2 >> (29 - 14)) << 0) : ((id2 & 0x7FF) << 3)) ; /* second ID is EXT or STD? */
  1104. uint32_t mask = ( ide1 != EXT ) ? ((((id1) ^ (id1)) ^ 0x7FF) << 19 ) | ((remote1 == RTR)?(1UL<<31):0UL) : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) << 16 ) | ((remote1 == RTR)?(1UL<<31):0UL);
  1105. mask |= (( ide2 != EXT ) ? ((((id2) ^ (id2)) ^ 0x7FF) << 3 ) | ((remote2 == RTR)?(1UL<<15):0UL) : ((((id2) ^ (id2)) ^ 0x1FFFFFFF) << 0 ) | ((remote2 == RTR)?(1UL<<15):0UL) ) & 0xFFFF;
  1106. mask |= (1UL<<30) | (1UL<<14);
  1107. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1108. }
  1109. /* #################################################################################### */
  1110. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1111. return 1;
  1112. }
  1113. FCTP_FUNC bool FCTP_OPT::setFIFOFilter(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id3, uint32_t id4, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2) {
  1114. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  1115. if ( filter > 31 ) return 0; /* multi-id & ranges are not allowed */
  1116. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1117. if ( filter >= max_fifo_filters ) return 0;
  1118. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1119. FLEXCAN_EnterFreezeMode();
  1120. /* ##################################### TABLE B ###################################### */
  1121. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) {
  1122. uint32_t mask = ( ide1 != EXT ) ? ((((id1 | id2) ^ (id1 & id2)) ^ 0x7FF) << 19 ) | ((remote1 == RTR)?(1UL<<31):0UL) : ((((id1 | id2) ^ (id1 & id2)) ^ 0x1FFFFFFF) << 16 ) | ((remote1 == RTR)?(1UL<<31):0UL);
  1123. mask |= (( ide2 != EXT ) ? ((((id3 | id4) ^ (id3 & id4)) ^ 0x7FF) << 3 ) | ((remote2 == RTR)?(1UL<<15):0UL) : ((((id3 | id4) ^ (id3 & id4)) ^ 0x1FFFFFFF) << 0 ) | ((remote2 == RTR)?(1UL<<15):0UL) ) & 0xFFFF;
  1124. mask |= (1UL<<30) | (1UL<<14);
  1125. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide1 == EXT ? 1 : 0) << 30) | ((ide2 == EXT ? 1 : 0) << 14) | /* STD IDs / EXT IDs */
  1126. ((remote1 == RTR ? 1 : 0) << 31) | ((remote2 == RTR ? 1 : 0) << 15) | /* remote frames */
  1127. (ide1 == EXT ? ((id1 >> (29 - 14)) << 16) : ((id1 & 0x7FF) << 19)) | /* first ID is EXT or STD? */
  1128. (ide2 == EXT ? ((id3 >> (29 - 14)) << 0 ) : ((id3 & 0x7FF) << 3 )) ; /* second ID is EXT or STD? */
  1129. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1130. }
  1131. /* #################################################################################### */
  1132. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1133. return 1;
  1134. }
  1135. FCTP_FUNC bool FCTP_OPT::setFIFOFilterRange(uint8_t filter, uint32_t id1, uint32_t id2, const FLEXCAN_IDE &ide1, const FLEXCAN_IDE &remote1, uint32_t id3, uint32_t id4, const FLEXCAN_IDE &ide2, const FLEXCAN_IDE &remote2) {
  1136. if ( !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN )) return 0; /* FIFO not enabled. */
  1137. if ( filter > 31 ) return 0; /* multi-id & ranges are not allowed */
  1138. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1139. if ( filter >= max_fifo_filters ) return 0;
  1140. if ( id1 > id2 || ((id2 > id1) && (id2 - id1 > 1000)) || !id1 || !id2 ) return 0; /* don't play around... */
  1141. if ( id3 > id4 || ((id4 > id3) && (id4 - id3 > 1000)) || !id3 || !id4 ) return 0; /* don't play around... */
  1142. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1143. FLEXCAN_EnterFreezeMode();
  1144. /* ##################################### TABLE B ###################################### */
  1145. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) {
  1146. uint32_t stage1 = id1, stage2 = id1;
  1147. for ( uint32_t i = id1 + 1; i <= id2; i++ ) {
  1148. stage1 |= i; stage2 &= i;
  1149. }
  1150. uint32_t mask = ( ide1 != EXT ) ? ((((stage1 | stage2) ^ (stage1 & stage2)) ^ 0x7FF) << 19 ) | ((remote1 == RTR)?(1UL<<31):0UL) : ((((stage1 | stage2) ^ (stage1 & stage2)) ^ 0x1FFFFFFF) << 16 ) | ((remote1 == RTR)?(1UL<<31):0UL);
  1151. stage1 = stage2 = id3;
  1152. for ( uint32_t i = id3 + 1; i <= id4; i++ ) {
  1153. stage1 |= i; stage2 &= i;
  1154. }
  1155. mask |= (( ide2 != EXT ) ? ((((stage1 | stage2) ^ (stage1 & stage2)) ^ 0x7FF) << 3 ) | ((remote2 == RTR)?(1UL<<15):0UL) : ((((stage1 | stage2) ^ (stage1 & stage2)) ^ 0x1FFFFFFF) << 0 ) | ((remote2 == RTR)?(1UL<<15):0UL) ) & 0xFFFF;
  1156. mask |= (1UL<<30) | (1UL<<14);
  1157. FLEXCANb_IDFLT_TAB(_bus, filter) = ((ide1 == EXT ? 1 : 0) << 30) | ((ide2 == EXT ? 1 : 0) << 14) | /* STD IDs / EXT IDs */
  1158. ((remote1 == RTR ? 1 : 0) << 31) | ((remote2 == RTR ? 1 : 0) << 15) | /* remote frames */
  1159. (ide1 == EXT ? ((id1 >> (29 - 14)) << 16) : ((id1 & 0x7FF) << 19)) | /* first ID is EXT or STD? */
  1160. (ide2 == EXT ? ((id3 >> (29 - 14)) << 0 ) : ((id3 & 0x7FF) << 3 )) ; /* second ID is EXT or STD? */
  1161. FLEXCANb_RXIMR(_bus, filter) = mask; // (RXIMR)
  1162. }
  1163. /* #################################################################################### */
  1164. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1165. return 1;
  1166. }
  1167. FCTP_FUNC void FCTP_OPT::setFIFOFilterTable(FLEXCAN_FIFOTABLE letter) {
  1168. bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
  1169. FLEXCAN_EnterFreezeMode();
  1170. FLEXCANb_MCR(_bus) = (FLEXCANb_MCR(_bus) & 0xFFFFFCFF) | FLEXCAN_MCR_IDAM(letter);
  1171. if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 0 ) FLEXCANb_RXFGMASK(_bus) = 0x3FFFFFFF;
  1172. else if ( ((FLEXCANb_MCR(_bus) & FLEXCAN_MCR_IDAM_MASK) >> FLEXCAN_MCR_IDAM_BIT_NO) == 1 ) FLEXCANb_RXFGMASK(_bus) = 0x7FFF7FFF;
  1173. if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
  1174. }
  1175. FCTP_FUNC void FCTP_OPT::filter_store(FLEXCAN_FILTER_TABLE type, FLEXCAN_MAILBOX mb_num, uint32_t id_count, uint32_t id1, uint32_t id2, uint32_t id3, uint32_t id4, uint32_t id5) {
  1176. mb_filter_table[mb_num][0] = mb_num; // first 7 bits reserved for MB
  1177. mb_filter_table[mb_num][0] |= (id_count << 7); // we store the quantity of ids after the mailboxes
  1178. /* bit 28: filter enabled */
  1179. mb_filter_table[mb_num][0] |= (type << 29); // we reserve 3 upper bits for type
  1180. volatile uint32_t *mbxAddr = &(*(volatile uint32_t*)(_bus + 0x80 + (mb_num * 0x10)));
  1181. mb_filter_table[mb_num][0] |= ( ((mbxAddr[0] & 0x600000) ? 1UL : 0UL) << 27); /* extended flag check */
  1182. mb_filter_table[mb_num][1] = id1; // id1
  1183. mb_filter_table[mb_num][2] = id2; // id2
  1184. mb_filter_table[mb_num][3] = id3; // id3
  1185. mb_filter_table[mb_num][4] = id4; // id4
  1186. mb_filter_table[mb_num][5] = id5; // id5
  1187. }
  1188. FCTP_FUNC volatile void FCTP_OPT::frame_distribution(CAN_message_t &msg) {
  1189. if ( !distribution ) return; /* distribution not enabled */
  1190. CAN_message_t frame = msg;
  1191. if ( FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FEN ) {
  1192. uint8_t max_fifo_filters = (((FLEXCANb_CTRL2(_bus) >> FLEXCAN_CTRL2_RFFN_BIT_NO) & 0xF) + 1) * 8; // 8->128
  1193. for (uint8_t i = 0; i < max_fifo_filters; i++) { /* check fifo filters */
  1194. if ( msg.mb == FIFO ) break; // don't distribute to fifo if fifo was the source
  1195. if ( !(fifo_filter_table[i][0] & 0xE0000000) ) continue; // skip unset filters
  1196. if ( (fifo_filter_table[i][0] >> 29) == FLEXCAN_MULTI ) {
  1197. if ( (bool)(fifo_filter_table[i][0] & (1UL << 16)) != msg.flags.extended ) continue; /* extended flag check */
  1198. for ( uint8_t p = 0; p < ((fifo_filter_table[i][0] & 0x380) >> 7); p++) {
  1199. if ( frame.id == fifo_filter_table[i][p+1] ) {
  1200. frame.mb = FIFO;
  1201. struct2queueRx(frame);
  1202. }
  1203. }
  1204. }
  1205. else if ( (fifo_filter_table[i][0] >> 29) == FLEXCAN_RANGE ) {
  1206. if ( (bool)(fifo_filter_table[i][0] & (1UL << 16)) != msg.flags.extended ) continue; /* extended flag check */
  1207. if ( frame.id >= fifo_filter_table[i][1] && frame.id <= fifo_filter_table[i][2] ) {
  1208. frame.mb = FIFO;
  1209. struct2queueRx(frame);
  1210. }
  1211. }
  1212. } /* end of fifo scan */
  1213. } /* end of fifo checking */
  1214. for ( uint8_t i = mailboxOffset(); i < FLEXCANb_MAXMB_SIZE(_bus); i++ ) {
  1215. if ( msg.mb == i ) continue; // don't distribute to same mailbox
  1216. if ( !(mb_filter_table[i][0] & 0xE0000000) ) continue; // skip unset filters
  1217. if ( (bool)(mb_filter_table[i][0] & (1UL << 27)) != msg.flags.extended ) continue; /* extended flag check */
  1218. if ( (mb_filter_table[i][0] >> 29) == FLEXCAN_MULTI ) {
  1219. for ( uint8_t p = 0; p < ((mb_filter_table[i][0] & 0x380) >> 7); p++) {
  1220. if ( frame.id == mb_filter_table[i][p+1] ) {
  1221. frame.mb = i;
  1222. struct2queueRx(frame);
  1223. }
  1224. }
  1225. }
  1226. else if ( (mb_filter_table[i][0] >> 29) == FLEXCAN_RANGE ) {
  1227. if ( frame.id >= mb_filter_table[i][1] && frame.id <= mb_filter_table[i][2] ) {
  1228. frame.mb = i;
  1229. struct2queueRx(frame);
  1230. }
  1231. }
  1232. } /* end of mb scan */
  1233. }
  1234. extern void __attribute__((weak)) ext_output1(const CAN_message_t &msg);
  1235. extern void __attribute__((weak)) ext_output2(const CAN_message_t &msg);
  1236. extern void __attribute__((weak)) ext_output3(const CAN_message_t &msg);