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.

234 Zeilen
7.9KB

  1. // -------------------------------------------------------------
  2. // a simple Arduino Teensy 3.1/3.2/3.6 CAN driver
  3. // by teachop
  4. // dual CAN support for MK66FX1M0 by Pawelsky
  5. //
  6. #ifndef __FLEXCAN_H__
  7. #define __FLEXCAN_H__
  8. #include <Arduino.h>
  9. #define FlexCAN_MAILBOX_TX_BUFFER_SUPPORT // helper definition for handling different FlexCAN revisions
  10. #define FlexCAN_DYNAMIC_BUFFER_SUPPORT // helper definition for handling different FlexCAN revisions
  11. #if !defined(SIZE_RX_BUFFER)
  12. #define SIZE_RX_BUFFER 32 // receive incoming ring buffer size
  13. #endif
  14. #if !defined(SIZE_TX_BUFFER)
  15. #define SIZE_TX_BUFFER 16 // transmit ring buffer size
  16. #endif
  17. #define SIZE_LISTENERS 4 // number of classes that can register as listeners on each CAN bus
  18. #define NUM_MAILBOXES 16 // architecture specific but all Teensy 3.x boards have 16 mailboxes
  19. #define IRQ_PRIORITY 64 // 0 = highest, 255 = lowest
  20. #define COLLECT_CAN_STATS
  21. typedef struct CAN_message_t {
  22. uint32_t id; // can identifier
  23. uint16_t timestamp; // FlexCAN time when message arrived
  24. struct {
  25. uint8_t extended:1; // identifier is extended (29-bit)
  26. uint8_t remote:1; // remote transmission request packet type
  27. uint8_t overrun:1; // message overrun
  28. uint8_t reserved:5;
  29. } flags;
  30. uint8_t len; // length of data
  31. uint8_t buf[8];
  32. } CAN_message_t;
  33. typedef struct CAN_filter_t {
  34. uint32_t id;
  35. struct {
  36. uint8_t extended:1; // identifier is extended (29-bit)
  37. uint8_t remote:1; // remote transmission request packet type
  38. uint8_t reserved:6;
  39. } flags;
  40. } CAN_filter_t;
  41. // statistics about the CAN interface
  42. typedef struct CAN_stats_t {
  43. bool enabled; // enable collecting statistics
  44. uint32_t ringRxMax; // number of entries in the ring buffer
  45. uint32_t ringRxHighWater; // maximum entries used in the ring buffer
  46. uint32_t ringRxFramesLost; // total number of frames lost
  47. uint32_t ringTxMax; // number of entries in the ring buffer
  48. uint32_t ringTxHighWater; // maximum entries used in the ring buffer
  49. struct {
  50. uint32_t refCount; // mailbox reference (use) count
  51. uint32_t overrunCount; // mailbox message overrun count
  52. } mb[NUM_MAILBOXES];
  53. } CAN_stats_t;
  54. // ring buffer data structure
  55. typedef struct ringbuffer_t {
  56. volatile uint16_t head;
  57. volatile uint16_t tail;
  58. uint16_t size;
  59. volatile CAN_message_t *buffer;
  60. } ringbuffer_t;
  61. // for backwards compatibility with previous structure members
  62. #define ext flags.extended
  63. #define rtr flags.remote
  64. class CANListener
  65. {
  66. public:
  67. CANListener ();
  68. virtual bool frameHandler (CAN_message_t &frame, int mailbox, uint8_t controller);
  69. virtual void txHandler (int mailbox, uint8_t controller);
  70. void attachMBHandler (uint8_t mailBox);
  71. void detachMBHandler (uint8_t mailBox);
  72. void attachGeneralHandler (void);
  73. void detachGeneralHandler (void);
  74. private:
  75. uint32_t callbacksActive; // bitfield indicating which callbacks are installed (for object oriented callbacks only)
  76. friend class FlexCAN; // class has to have access to the the guts of this one
  77. };
  78. // -------------------------------------------------------------
  79. class FlexCAN
  80. {
  81. private:
  82. uint32_t flexcanBase;
  83. struct CAN_filter_t MBFilters[NUM_MAILBOXES];
  84. static struct CAN_filter_t defaultMask;
  85. void mailbox_int_handler (uint8_t mb, uint32_t ul_status);
  86. CANListener *listener[SIZE_LISTENERS];
  87. ringbuffer_t txRing;
  88. volatile CAN_message_t *tx_buffer;
  89. ringbuffer_t rxRing;
  90. volatile CAN_message_t *rx_buffer;
  91. ringbuffer_t * txRings[NUM_MAILBOXES];
  92. bool IrqEnabled;
  93. uint32_t IrqMessage;
  94. void writeTxRegisters (const CAN_message_t &msg, uint8_t buffer);
  95. void readRxRegisters (CAN_message_t &msg, uint8_t buffer);
  96. void initRingBuffer (ringbuffer_t &ring, volatile CAN_message_t *buffer, uint32_t size);
  97. bool addToRingBuffer (ringbuffer_t &ring, const CAN_message_t &msg);
  98. bool removeFromRingBuffer (ringbuffer_t &ring, CAN_message_t &msg);
  99. bool isRingBufferEmpty (ringbuffer_t &ring);
  100. uint32_t ringBufferCount (ringbuffer_t &ring);
  101. void irqLock() { IrqEnabled=NVIC_IS_ENABLED(IrqMessage); NVIC_DISABLE_IRQ(IrqMessage); }
  102. void irqRelease() { if (IrqEnabled) NVIC_ENABLE_IRQ(IrqMessage); }
  103. void initializeBuffers();
  104. bool isInitialized() { return tx_buffer!=0; }
  105. void setPins(uint8_t txAlt, uint8_t rxAlt);
  106. void setBaudRate(uint32_t baud);
  107. void softReset();
  108. void halt();
  109. void exitHalt();
  110. void freeze();
  111. void waitFrozen();
  112. void waitNotFrozen();
  113. void waitReady();
  114. bool isFrozen();
  115. bool usesGlobalTxRing(uint8_t mbox) { return (mbox<getNumMailBoxes()?txRings[mbox]==0:true); }
  116. bool isTxBox(uint8_t mbox) { return (mbox>=getFirstTxBox() && mbox<getNumMailBoxes() ); }
  117. #ifdef COLLECT_CAN_STATS
  118. CAN_stats_t stats;
  119. #endif
  120. protected:
  121. uint8_t numTxMailboxes;
  122. uint16_t sizeRxBuffer;
  123. uint16_t sizeTxBuffer;
  124. public:
  125. FlexCAN (uint8_t id = 0);
  126. // Before begin, you can define rx buffer size. Default is SIZE_RX_BUFFER. This does not have effect after begin.
  127. void setRxBufferSize(uint16_t size) { if (!isInitialized() ) sizeRxBuffer=size; }
  128. // Before begin, you can define global tx buffer size. Default is SIZE_TX_BUFFER. This does not have effect after begin.
  129. void setTxBufferSize(uint16_t size) { if (!isInitialized() ) sizeTxBuffer=size; }
  130. // You can define mailbox specific tx buffer size. This can be defined only once per mailbox.
  131. // As default prioritized messages will not be buffered. If you define buffer size for mail box, the messages will be
  132. // buffered to own buffer, if necessary.
  133. void setMailBoxTxBufferSize(uint8_t mbox, uint16_t size);
  134. inline uint8_t getFirstTxBox() { return getNumMailBoxes()-numTxMailboxes; }
  135. inline uint8_t getLastTxBox() { return getNumMailBoxes()-1; }
  136. inline uint8_t getNumMailBoxes() { return NUM_MAILBOXES; }
  137. inline uint8_t getNumRxBoxes() { return getNumMailBoxes()-numTxMailboxes; }
  138. void begin (uint32_t baud = 250000, const CAN_filter_t &mask = defaultMask, uint8_t txAlt = 0, uint8_t rxAlt = 0);
  139. void setFilter (const CAN_filter_t &filter, uint8_t n);
  140. bool getFilter (CAN_filter_t &filter, uint8_t n);
  141. void setMask (uint32_t mask, uint8_t n);
  142. void end (void);
  143. uint32_t available (void);
  144. int write (const CAN_message_t &msg);
  145. int write (const CAN_message_t &msg, uint8_t n);
  146. int read (CAN_message_t &msg);
  147. uint32_t rxBufferOverruns (void)
  148. {
  149. return stats.ringRxFramesLost;
  150. };
  151. #ifdef COLLECT_CAN_STATS
  152. void startStats (void)
  153. {
  154. stats.enabled = true;
  155. };
  156. void stopStats (void)
  157. {
  158. stats.enabled = false;
  159. };
  160. void clearStats (void);
  161. CAN_stats_t getStats (void)
  162. {
  163. return stats;
  164. };
  165. #endif
  166. //new functionality added to header but not yet implemented. Fix me
  167. void setListenOnly (bool mode); //pass true to go into listen only mode, false to be in normal mode
  168. bool attachObj (CANListener *listener);
  169. bool detachObj (CANListener *listener);
  170. //int watchFor(); //allow anything through
  171. //int watchFor(uint32_t id); //allow just this ID through (automatic determination of extended status)
  172. //int watchFor(uint32_t id, uint32_t mask); //allow a range of ids through
  173. //int watchForRange(uint32_t id1, uint32_t id2); //try to allow the range from id1 to id2 - automatically determine base ID and mask
  174. uint8_t setNumTxBoxes (uint8_t txboxes);
  175. // Obsolete, for compatibility with version provided with Teensyduino
  176. uint8_t setNumTXBoxes (uint8_t txboxes) { return setNumTxBoxes(txboxes); }
  177. void message_isr (void);
  178. void bus_off_isr (void);
  179. void error_isr (void);
  180. void tx_warn_isr (void);
  181. void rx_warn_isr (void);
  182. void wakeup_isr (void);
  183. };
  184. extern FlexCAN Can0;
  185. #ifdef __MK66FX1M0__
  186. extern FlexCAN Can1;
  187. #endif
  188. #endif // __FLEXCAN_H__