VMX-pi C++ HAL Library for Raspberry Pi
VMX-pi Robotics Controller & Vision/Motion Processor
VMXCAN.h
1 /* ============================================
2 VMX-pi HAL source code is placed under the MIT license
3 Copyright (c) 2017 Kauai Labs
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
18 THE SOFTWARE.
19 ===============================================
20 */
21 
22 #ifndef VMXCAN_H_
23 #define VMXCAN_H_
24 
25 #include <stdint.h>
26 #include <string.h>
27 #include <thread>
28 #include <map>
29 #include <iterator>
30 #include "VMXErrors.h"
31 #include "VMXTime.h"
32 
33 /* NOTE: Usage Model similar to that found in the WPILIB Suite HAL */
34 
35 #define VMXCAN_IS_FRAME_REMOTE 0x80000000
36 #define VMXCAN_IS_FRAME_11BIT 0x40000000
37 #define VMXCAN_29BIT_MESSAGE_ID_MASK 0x1FFFFFFF
38 #define VMXCAN_11BIT_MESSAGE_ID_MASK 0x000007FF
39 
40 #define VMXCAN_SEND_PERIOD_NO_REPEAT 0
41 #define VMXCAN_SEND_PERIOD_STOP_REPEATING -1
42 
44 typedef struct sVMXCANMessage {
45  uint32_t messageID;
46  uint8_t data[8];
47  uint8_t dataSize;
48 
49  void setData(const uint8_t *p_data_in, uint8_t len) {
50  if (len > 8) {
51  len = 8;
52  }
53  for(int i = 0; i < len; i++ ) {
54  data[i] = p_data_in[i];
55  }
56  }
57  void getData(uint8_t *p_data_out, uint8_t len) {
58  if (len > 8) {
59  len = 8;
60  }
61  for(int i = 0; i < len; i++ ) {
62  p_data_out[i] = data[i];
63  }
64  }
66 
68 typedef struct sVMXTimestampedCANMessage : public sVMXCANMessage {
69  uint32_t timeStampMS;
70  uint64_t sysTimeStampUS;
72 
74  bool retrieved;
76 
79 typedef struct {
85  uint32_t busOffCount;
89  uint32_t txFullCount;
95  bool busWarning;
105  bool busError;
107  bool wake;
111 
112 typedef uint32_t VMXCANReceiveStreamHandle;
113 
114 using namespace std;
115 
116 class CANClient;
117 class VMXCANReceiveStreamManager;
118 
122 class VMXCAN {
123 
124  friend class VMXPi;
125 
126  typedef struct sVMXTimestampedCANMessageRepeating : public sVMXTimestampedCANMessage {
127  uint64_t lastSendTimestampUS;
128  uint32_t repeatEveryMS;
129  } VMXCANTimestampedMessageRepeating;
130 
131 
132  CANClient& can;
133  VMXTime& time;
134  VMXCANReceiveStreamManager *p_stream_mgr;
135  thread * task;
136  bool task_done;
137  bool initialized;
138  thread * repeating_packet_thread_task;
139  bool repeating_packet_thread_task_done;
140  std::map<uint32_t, VMXCANTimestampedMessageRepeating> repeatingMessageMap;
141 
142  VMXCAN(CANClient& can_ref, VMXTime& time_ref);
143  virtual ~VMXCAN();
144  void ReleaseResources();
145 
146  static void CANNewRxDataNotifyHandler(void *param, uint64_t timestamp_us);
147  static int ThreadFunc(VMXCAN *);
148  static int RepeatingPacketThreadFunc(VMXCAN *);
149 
150  bool RemoveFromRepeatingMessageMap(uint32_t);
151  bool AddToRepeatingMessageMap(uint32_t, VMXCANMessage&, uint32_t repeatEveryMS);
152  bool SendMessageInternal(VMXCANMessage& msg, VMXErrorCode *errcode);
153 
154 public:
155  void DisplayMasksAndFilters();
156 
157 public:
158 
159  typedef enum { CAN_BUS_BITRATE_1MBPS, CAN_BUS_BITRATE_500KBPS, CAN_BUS_BITRATE_250KBPS } CANBusBitrate;
160 
182  bool SendMessage(VMXCANMessage& msg, int32_t periodMs, VMXErrorCode *errcode);
183 
184  /* Opens a new VMXCANReceiveStream.
185  *
186  * messageID: The CAN Arb ID for the message of interest. This is basically the Message FILTER.
187  * Since this operates as a filter, all bits in the messageID that are masked in by the
188  * messageMask must match. Using a combination of messageMask and messageID, it is possible
189  * to allow ranges of CAN Arb IDs to be received with a single VMXCANReceiveStream.
190  *
191  * messsageMask: The Message MASK to use for the messages of interest. NOTE: the underlying hardware supports
192  * a total of two masks. If a third VMXCANReceiveStream is opened which has a different Mask than the two
193  * already-opened VMXCANReceiveStreams, the open will fail. To work around this limitation, the masks can be
194  * ANDed together (and the bits cleared during the ANDing should be cleared also in the VMXCANReceiveStream
195  * messageIDs. In this case, it is likely that additional undesired messages may be received; these should be
196  * discarded by the application.
197  *
198  * maxMessages: This is maximum number of received messages to internally buffer for this stream.
199  */
200  bool OpenReceiveStream(VMXCANReceiveStreamHandle& streamHandle, uint32_t messageID, uint32_t messageMask, uint32_t maxMessages, VMXErrorCode *errcode);
201  /* Retrieves recently received data for a VMXCANReceiveStream.
202  *
203  * messages: Pointer to an array VMXCANTimestampedMessage structures. The number of elements in this array
204  * must be greater than or equal to the messagesToRead parameter to avoid memory corruption.
205  *
206  * messagesToRead: The maximum number of messages to be read by this function.
207  *
208  * messagesRead: Output from this function, this indicates the actual number of messages read by this function;
209  * this value will never exceed the value passed in the messagesToRead parameter.
210  *
211  * errcode: If non-null in case of error this will return the error code.
212  */
213  bool ReadReceiveStream(VMXCANReceiveStreamHandle streamHandle, VMXCANTimestampedMessage *messages, uint32_t messagesToRead, uint32_t& messagesRead, VMXErrorCode *errcode);
214 
215  /* Closes a previously-opened VMCANReceiveStream.
216  *
217  * errcode: If non-null in case of error this will return the error code.
218  */
219  bool CloseReceiveStream(VMXCANReceiveStreamHandle streamHandle, VMXErrorCode *errcode);
220 
221  /* Retrieves current CAN Bus statistics and warning/error states.
222  *
223  * errcode: If non-null in case of error this will return the error code.
224  */
225  bool GetCANBUSStatus(VMXCANBusStatus& bus_status, VMXErrorCode *errcode);
226 
227  /* Resets the CAN Transceiver and Controller. Note that this operation will clear any previously-
228  * configured Receive Masks/Filters and other configuration settings. This function sets the
229  * CAN bus bitrate to the default (CAN_BUS_BITRATE_1MBPS).
230  *
231  * errcode: If non-null in case of error this will return the error code.
232  */
233  bool Reset(VMXErrorCode *errcode);
234 
235  /* Resets the CAN Transceiver and Controller. Note that this operation will clear any previously-
236  * configured Receive Masks/Filters and other configuration settings. This function sets the
237  * CAN bus bitrate to the specified bus bitrate.
238  *
239  * can_bus_bitrate: The specified CANBusBitrate to be used after CAN controller is reset.
240  * errcode: If non-null in case of error this will return the error code.
241  */
242  bool ResetBusBitrate(VMXCAN::CANBusBitrate can_bus_bitrate, VMXErrorCode *errcode);
243 
244  /* Empties the Transmit FIFO of any unsent VMXCANMessages.
245  *
246  * errcode: If non-null in case of error this will return the error code.
247  */
248  bool FlushTxFIFO(VMXErrorCode *errcode);
249  /* Empties the Receive FIFO of any unreceived VMXCANMessages.
250  *
251  * errcode: If non-null in case of error this will return the error code.
252  */
253  bool FlushRxFIFO(VMXErrorCode *errcode);
254 
256  typedef enum {
281  VMXCAN_LOOPBACK
282  } VMXCANMode;
283 
284  /* Sets the CAN Controller/Transceiver's current VMXCANMode.
285  *
286  * errcode: If non-null in case of error this will return the error code.
287  */
288  bool SetMode(VMXCANMode mode, VMXErrorCode *errcode);
289 
290  /* Retrieves the CAN Controller/Transceiver's current VMXCANMode.
291  *
292  * errcode: If non-null in case of error this will return the error code.
293  */
294  bool GetMode(VMXCANMode& current_mode, VMXErrorCode *errcode);
295 
296  /* Clears any error conditions in the firmware and the CAN Controller/Transceiver.
297  *
298  * This function must be invoked in order to reset a hardware overflow condition.
299  *
300  * errcode: If non-null in case of error this will return the error code.
301  */
302  bool ClearErrors(VMXErrorCode *errcode);
303 
304  bool RetrieveAllCANData(uint64_t sys_timestamp, VMXErrorCode *errcode); /* Todo: This should be removed from the public interface. */
305 
306  bool EnableReceiveStreamBlackboard(VMXCANReceiveStreamHandle streamHandle, bool enable, VMXErrorCode *errcode);
307 
308  bool IsReceveStreamBlackboardEnabled(VMXCANReceiveStreamHandle streamHandle, bool& enabled, VMXErrorCode *errcode);
309 
310  bool GetBlackboardEntry(VMXCANReceiveStreamHandle streamid, uint32_t messageID, VMXCANTimestampedMessage& msg, uint64_t& sys_timestamp, bool& already_retrieved, VMXErrorCode *errcode);
311 };
312 
313 #endif /* VMXCAN_H_ */
Places the CAN Controller into normal mode, where it may transmit messages onto the CAN Bus...
Definition: VMXCAN.h:270
Top-level Library Class providing access to all VMX-pi functionality.
Definition: VMXPi.h:40
VMXCANMode
Enumeration of VMX CAN operational modes.
Definition: VMXCAN.h:256
uint32_t txFullCount
txFullCount: The number of times that sendMessage failed with a txFifoFull error indicating that mess...
Definition: VMXCAN.h:89
The xVMXCANMessage structure encapsulates a CAN Bus message.
Definition: VMXCAN.h:44
bool busPassiveError
Currently a bus passive condition exists.
Definition: VMXCAN.h:97
uint32_t receiveErrorCount
receiveErrorCount: The count of receive errors as reported by the CAN driver.
Definition: VMXCAN.h:91
Places the CAN Controller into a listen-only mode where it passively listens to the CAN Bus...
Definition: VMXCAN.h:275
bool messageError
Controller message error detected.
Definition: VMXCAN.h:109
Places the CAN Controller into configuration mode, during which the Receive Masks/ Fiters may be modi...
Definition: VMXCAN.h:264
bool busOffError
Currently a bus off condition exists.
Definition: VMXCAN.h:99
Places the CAN Transceiver/Controller into a sleep state, which may be automatically woken from if CA...
Definition: VMXCAN.h:260
bool hwRxOverflow
Hardware-level buffer overflow.
Definition: VMXCAN.h:101
bool busWarning
Currently a bus warning condition exists.
Definition: VMXCAN.h:95
uint32_t busOffCount
busOffCount: The number of times that sendMessage failed with a busOff error indicating that messages...
Definition: VMXCAN.h:85
The VMXTime class provides time management functions, including system timestamps, VMX Real-time Clock access, timer notifications and current thread time-delay.
Definition: VMXTime.h:38
bool swRxOverflow
Firmware-level buffer overflow.
Definition: VMXCAN.h:103
uint32_t transmitErrorCount
transmitErrorCount: The count of transmit errors as reported by the CAN driver.
Definition: VMXCAN.h:93
float percentBusUtilization
Percentage of total CAN bus bandwidth currently utilized.
Definition: VMXCAN.h:81
The sVMXTimestampedCANMessage encapsulates a timestamped CAN Bus message.
Definition: VMXCAN.h:68
The VMXCAN class provides a hardware-abstraction of the VMX-pi CAN functionality. ...
Definition: VMXCAN.h:122
The VMXCANBusStatus structure contains CAN Bus utilitization, status and error information.
Definition: VMXCAN.h:79
bool busError
Transceiver bus error detected.
Definition: VMXCAN.h:105
bool wake
Transceiver wakeup event occurred.
Definition: VMXCAN.h:107