1 /***************************************************************************//**
2  * @file
3  * @brief Controller Area Network API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef EM_CAN_H
32 #define EM_CAN_H
33 
34 #include "em_bus.h"
35 #include "em_device.h"
36 #include <stdbool.h>
37 
38 #if defined(CAN_COUNT) && (CAN_COUNT > 0)
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /***************************************************************************//**
45  * @addtogroup can
46  * @{
47  ******************************************************************************/
48 
49 /*******************************************************************************
50  *******************************   DEFINES   ***********************************
51  ******************************************************************************/
52 
53 /*******************************************************************************
54  ********************************   ENUMS   ************************************
55  ******************************************************************************/
56 
57 /** CAN Status codes. */
58 typedef enum {
59   /** No error occurred during the last CAN bus event. */
60   canErrorNoError  = CAN_STATUS_LEC_NONE,
61 
62   /**
63    * More than 5 equal bits in a sequence have occurred in a part of a received
64    * message where this is not allowed.
65    */
66   canErrorStuff    = CAN_STATUS_LEC_STUFF,
67 
68   /** A fixed format part of a received frame has the wrong format. */
69   canErrorForm     = CAN_STATUS_LEC_FORM,
70 
71   /** The message this CAN Core transmitted was not acknowledged by another node. */
72   canErrorAck      = CAN_STATUS_LEC_ACK,
73 
74   /** A wrong monitored bus value : dominant when the module wants to send a recessive. */
75   canErrorBit1     = CAN_STATUS_LEC_BIT1,
76 
77   /** A wrong monitored bus value : recessive when the module intends to send a dominant. */
78   canErrorBit0     = CAN_STATUS_LEC_BIT0,
79 
80   /** CRC check sum incorrect. */
81   canErrorCrc      = CAN_STATUS_LEC_CRC,
82 
83   /** Unused. No new error since the CPU wrote this value. */
84   canErrorUnused   = CAN_STATUS_LEC_UNUSED
85 } CAN_ErrorCode_TypeDef;
86 
87 /** CAN peripheral mode. */
88 typedef enum {
89   /** CAN peripheral in Normal mode : ready to send and receive messages. */
90   canModeNormal,
91 
92   /** CAN peripheral in Basic mode : no use of the RAM. */
93   canModeBasic,
94 
95   /**
96    * CAN peripheral in Loopback mode : input from the CAN bus is disregarded
97    * and comes from TX instead.
98    */
99   canModeLoopBack,
100 
101   /**
102    * CAN peripheral in SilentLoopback mode : input from the CAN bus is
103    * disregarded and comes from TX instead ; no output on the CAN bus.
104    */
105   canModeSilentLoopBack,
106 
107   /** CAN peripheral in Silent mode : no output on the CAN bus. If required to
108    * send a dominant bit, it's rerouted internally so that the CAN module
109    * monitors it but the CAN bus stays recessive.
110    */
111   canModeSilent
112 } CAN_Mode_TypeDef;
113 
114 /*******************************************************************************
115  *******************************   STRUCTS   ***********************************
116  ******************************************************************************/
117 
118 /** CAN Message Object TypeDef structure. LSBs is used. */
119 typedef struct {
120   /** A message number of this Message Object, [1 - 32]. */
121   uint8_t   msgNum;
122 
123   /** ID extended if true, standard if false.  */
124   bool      extended;
125 
126   /**
127    * ID of the message with 11 bits (standard) or 28 bits (extended).
128    * LSBs are used for both.
129    */
130   uint32_t  id;
131 
132   /** Data Length Code [0 - 8].  */
133   uint8_t   dlc;
134 
135   /** A pointer to data, [0 - 8] bytes.  */
136   uint8_t   data[8];
137 
138   /** A mask for ID filtering. */
139   uint32_t  mask;
140 
141   /** Enable the use of 'extended' value for filtering. */
142   bool      extendedMask;
143 
144   /** Enable the use of 'direction' value for filtering. */
145   bool      directionMask;
146 } CAN_MessageObject_TypeDef;
147 
148 /** CAN initialization structure. */
149 typedef struct {
150   /** True to set the CAN Device in normal mode after initialization. */
151   bool      enable;
152 
153   /** True to reset messages during initialization. */
154   bool      resetMessages;
155 
156   /** Default bitrate. */
157   uint32_t  bitrate;
158 
159   /** Default Propagation Time Segment. */
160   uint8_t   propagationTimeSegment;
161 
162   /** Default Phase Buffer Segment 1. */
163   uint8_t   phaseBufferSegment1;
164 
165   /** Default Phase Buffer Segment 2. */
166   uint8_t   phaseBufferSegment2;
167 
168   /** Default Synchronization Jump Width. */
169   uint8_t   synchronisationJumpWidth;
170 } CAN_Init_TypeDef;
171 
172 /**
173  * Default initialization of CAN_Init_TypeDef. The total duration of a bit with
174  * these default parameters is 10 tq (time quantum : tq = brp/fsys, brp being
175  * the baudrate prescaler and being set according to the wanted bitrate, fsys
176  * beeing the CAN device frequency).
177  */
178 #define CAN_INIT_DEFAULT                                                      \
179   {                                                                           \
180     true,     /** Set the CAN Device in normal mode after initialization.  */ \
181     true,     /** Reset messages during initialization.         */            \
182     100000,   /** Set bitrate to 100 000                        */            \
183     1,        /** Set the Propagation Time Segment to 1.         */           \
184     4,        /** Set the Phase Buffer Segment 1 to 4.           */           \
185     4,        /** Set the Phase Buffer Segment 2 to 4.           */           \
186     1         /** Set the Synchronization Jump Width to 1.       */           \
187   }
188 
189 /*******************************************************************************
190  *****************************   PROTOTYPES   **********************************
191  ******************************************************************************/
192 
193 void CAN_Init(CAN_TypeDef *can, const CAN_Init_TypeDef *init);
194 
195 uint32_t CAN_GetClockFrequency(CAN_TypeDef *can);
196 
197 bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum);
198 
199 void CAN_SetRoute(CAN_TypeDef *can,
200                   bool active,
201                   uint16_t pinRxLoc,
202                   uint16_t pinTxLoc);
203 
204 void CAN_SetBitTiming(CAN_TypeDef *can,
205                       uint32_t bitrate,
206                       uint16_t propagationTimeSegment,
207                       uint16_t phaseBufferSegment1,
208                       uint16_t phaseBufferSegment2,
209                       uint16_t synchronisationJumpWidth);
210 
211 void CAN_SetMode(CAN_TypeDef *can, CAN_Mode_TypeDef mode);
212 
213 void CAN_SetIdAndFilter(CAN_TypeDef *can,
214                         uint8_t interface,
215                         bool useMask,
216                         const CAN_MessageObject_TypeDef *message,
217                         bool wait);
218 
219 void CAN_ConfigureMessageObject(CAN_TypeDef *can,
220                                 uint8_t interface,
221                                 uint8_t msgNum,
222                                 bool valid,
223                                 bool tx,
224                                 bool remoteTransfer,
225                                 bool endOfBuffer,
226                                 bool wait);
227 
228 void CAN_SendMessage(CAN_TypeDef *can,
229                      uint8_t interface,
230                      const CAN_MessageObject_TypeDef *message,
231                      bool wait);
232 
233 bool CAN_ReadMessage(CAN_TypeDef *can,
234                      uint8_t interface,
235                      CAN_MessageObject_TypeDef *message);
236 
237 void CAN_AbortSendMessage(CAN_TypeDef *can,
238                           uint8_t interface,
239                           uint8_t msgNum,
240                           bool wait);
241 
242 void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface);
243 
244 void CAN_Reset(CAN_TypeDef *can);
245 
246 void CAN_WriteData(CAN_TypeDef *can,
247                    uint8_t interface,
248                    const CAN_MessageObject_TypeDef *message);
249 
250 void CAN_SendRequest(CAN_TypeDef *can,
251                      uint8_t interface,
252                      uint8_t msgNum,
253                      bool wait);
254 
255 /***************************************************************************//**
256  * @brief
257  *   Enable the Host Controller to send messages.
258  *
259  * @param[in] can
260  *   A pointer to the CAN peripheral register block.
261  *
262  * @param[in] enable
263  *   True to enable CAN device, false to disable it. If the CAN device is
264  *   enabled, it goes to normal mode (the default working mode).
265  ******************************************************************************/
CAN_Enable(CAN_TypeDef * can,bool enable)266 __STATIC_INLINE void CAN_Enable(CAN_TypeDef *can, bool enable)
267 {
268   BUS_RegBitWrite(&can->CTRL, _CAN_CTRL_INIT_SHIFT, (enable ? 0 : 1));
269 }
270 
271 /***************************************************************************//**
272  * @brief
273  *   Give the communication capabilities state.
274  *
275  * @param[in] can
276  *   A pointer to the CAN peripheral register block.
277  *
278  * @return
279  *   True if the Host Controller can send messages, false otherwise.
280  ******************************************************************************/
CAN_IsEnabled(CAN_TypeDef * can)281 __STATIC_INLINE bool CAN_IsEnabled(CAN_TypeDef *can)
282 {
283   return (can->CTRL & _CAN_CTRL_INIT_MASK) == 0;
284 }
285 
286 /***************************************************************************//**
287  * @brief
288  *   Waiting function.
289  *
290  * @param[in] can
291  *   A pointer to the CAN peripheral register block.
292  *
293  * @param[in] interface
294  *   Indicate which Message Interface Register to use.
295  *
296  ******************************************************************************/
CAN_ReadyWait(CAN_TypeDef * can,uint8_t interface)297 __STATIC_INLINE void CAN_ReadyWait(CAN_TypeDef *can,
298                                    uint8_t interface)
299 {
300   while ((_CAN_MIR_CMDREQ_BUSY_MASK & can->MIR[interface].CMDREQ) != 0) {
301   }
302 }
303 
304 /***************************************************************************//**
305  * @brief
306  *   Get the last error code and clear its register.
307  *
308  * @param[in] can
309  *   Pointer to CAN peripheral register block.
310  *
311  * @return
312  *   return Last error code.
313  ******************************************************************************/
CAN_GetLastErrorCode(CAN_TypeDef * can)314 __STATIC_INLINE CAN_ErrorCode_TypeDef CAN_GetLastErrorCode(CAN_TypeDef *can)
315 {
316   CAN_ErrorCode_TypeDef errorCode = (CAN_ErrorCode_TypeDef)
317                                     (can->STATUS & _CAN_STATUS_LEC_MASK);
318   can->STATUS |= ~_CAN_STATUS_LEC_MASK;
319   return errorCode;
320 }
321 
322 /***************************************************************************//**
323  * @brief
324  *   Indicate which message objects have received new data.
325  *
326  * @param[in] can
327  *   A pointer to the CAN peripheral register block.
328  *
329  * @return
330  *   State of MESSAGEDATA register indicating which message objects have received
331  *   new data.
332  ******************************************************************************/
CAN_HasNewdata(CAN_TypeDef * can)333 __STATIC_INLINE uint32_t CAN_HasNewdata(CAN_TypeDef *can)
334 {
335   return can->MESSAGEDATA;
336 }
337 
338 /***************************************************************************//**
339  * @brief
340  *   Clear one or more pending CAN status interrupts.
341  *
342  * @param[in] can
343  *   A pointer to the CAN peripheral register block.
344  *
345  * @param[in] flags
346  *   Pending CAN status interrupt source(s) to clear.
347  ******************************************************************************/
CAN_StatusIntClear(CAN_TypeDef * can,uint32_t flags)348 __STATIC_INLINE void CAN_StatusIntClear(CAN_TypeDef *can, uint32_t flags)
349 {
350   can->IF1IFC = flags;
351 }
352 
353 /***************************************************************************//**
354  * @brief
355  *   Disable CAN status interrupts.
356  *
357  * @param[in] can
358  *   A pointer to the CAN peripheral register block.
359  *
360  * @param[in] flags
361  *   CAN status interrupt source(s) to disable.
362  ******************************************************************************/
CAN_StatusIntDisable(CAN_TypeDef * can,uint32_t flags)363 __STATIC_INLINE void CAN_StatusIntDisable(CAN_TypeDef *can, uint32_t flags)
364 {
365   can->IF1IEN &= ~flags;
366 }
367 
368 /***************************************************************************//**
369  * @brief
370  *   Enable CAN status interrupts.
371  *
372  * @param[in] can
373  *   A pointer to the CAN peripheral register block.
374  *
375  * @param[in] flags
376  *   CAN status interrupt source(s) to enable.
377  ******************************************************************************/
CAN_StatusIntEnable(CAN_TypeDef * can,uint32_t flags)378 __STATIC_INLINE void CAN_StatusIntEnable(CAN_TypeDef *can, uint32_t flags)
379 {
380   can->IF1IEN |= flags;
381 }
382 
383 /***************************************************************************//**
384  * @brief
385  *   Get pending CAN status interrupt flags.
386  *
387  * @note
388  *   This function does not clear event bits.
389  *
390  * @param[in] can
391  *   A pointer to the CAN peripheral register block.
392  *
393  * @return
394  *   CAN interrupt source(s) pending.
395  ******************************************************************************/
CAN_StatusIntGet(CAN_TypeDef * can)396 __STATIC_INLINE uint32_t CAN_StatusIntGet(CAN_TypeDef *can)
397 {
398   return can->IF1IF;
399 }
400 
401 /***************************************************************************//**
402  * @brief
403  *   Get pending and enabled CAN status interrupt flags.
404  *
405  * @note
406  *   This function does not clear event bits.
407  *
408  * @param[in] can
409  *   A pointer to the CAN peripheral register block.
410  *
411  * @return
412  *   CAN interrupt source(s) pending and enabled.
413  ******************************************************************************/
CAN_StatusIntGetEnabled(CAN_TypeDef * can)414 __STATIC_INLINE uint32_t CAN_StatusIntGetEnabled(CAN_TypeDef *can)
415 {
416   uint32_t ien;
417 
418   ien = can->IF1IEN;
419   return can->IF1IF & ien;
420 }
421 
422 /***************************************************************************//**
423  * @brief
424  *   Set one or more CAN status interrupts.
425  *
426  * @param[in] can
427  *   A pointer to the CAN peripheral register block.
428  *
429  * @param[in] flags
430  *   CAN status interrupt source(s) to set to pending.
431  ******************************************************************************/
CAN_StatusIntSet(CAN_TypeDef * can,uint32_t flags)432 __STATIC_INLINE void CAN_StatusIntSet(CAN_TypeDef *can, uint32_t flags)
433 {
434   can->IF1IFS = flags;
435 }
436 
437 /***************************************************************************//**
438  * @brief
439  *   Get CAN status.
440  *
441  * @param[in] can
442  *   A pointer to the CAN peripheral register block.
443  *
444  * @return
445  *   A value of CAN register STATUS.
446  ******************************************************************************/
CAN_StatusGet(CAN_TypeDef * can)447 __STATIC_INLINE uint32_t CAN_StatusGet(CAN_TypeDef *can)
448 {
449   return can->STATUS & ~_CAN_STATUS_LEC_MASK;
450 }
451 
452 /***************************************************************************//**
453  * @brief
454  *   Clear CAN status.
455  *
456  * @param[in] can
457  *   A pointer to the CAN peripheral register block.
458  *
459  * @param[in] flags
460  *   CAN status bits to clear.
461  ******************************************************************************/
CAN_StatusClear(CAN_TypeDef * can,uint32_t flags)462 __STATIC_INLINE void CAN_StatusClear(CAN_TypeDef *can, uint32_t flags)
463 {
464   can->STATUS &= ~flags;
465 }
466 
467 /***************************************************************************//**
468  * @brief
469  *   Get the error count.
470  *
471  * @param[in] can
472  *   A pointer to the CAN peripheral register block.
473  *
474  * @return
475  *   Error count.
476  ******************************************************************************/
CAN_GetErrorCount(CAN_TypeDef * can)477 __STATIC_INLINE uint32_t CAN_GetErrorCount(CAN_TypeDef *can)
478 {
479   return can->ERRCNT;
480 }
481 
482 /***************************************************************************//**
483  * @brief
484  *   Clear one or more pending CAN message interrupts.
485  *
486  * @param[in] can
487  *   A pointer to the CAN peripheral register block.
488  *
489  * @param[in] flags
490  *   Pending CAN message interrupt source(s) to clear.
491  ******************************************************************************/
CAN_MessageIntClear(CAN_TypeDef * can,uint32_t flags)492 __STATIC_INLINE void CAN_MessageIntClear(CAN_TypeDef *can, uint32_t flags)
493 {
494   can->IF0IFC = flags;
495 }
496 
497 /***************************************************************************//**
498  * @brief
499  *   Disable CAN message interrupts.
500  *
501  * @param[in] can
502  *   A pointer to the CAN peripheral register block.
503  *
504  * @param[in] flags
505  *   CAN message interrupt source(s) to disable.
506  ******************************************************************************/
CAN_MessageIntDisable(CAN_TypeDef * can,uint32_t flags)507 __STATIC_INLINE void CAN_MessageIntDisable(CAN_TypeDef *can, uint32_t flags)
508 {
509   can->IF0IEN &= ~flags;
510 }
511 
512 /***************************************************************************//**
513  * @brief
514  *   Enable CAN message interrupts.
515  *
516  * @param[in] can
517  *   A pointer to the CAN peripheral register block.
518  *
519  * @param[in] flags
520  *   CAN message interrupt source(s) to enable.
521  ******************************************************************************/
CAN_MessageIntEnable(CAN_TypeDef * can,uint32_t flags)522 __STATIC_INLINE void CAN_MessageIntEnable(CAN_TypeDef *can, uint32_t flags)
523 {
524   can->IF0IEN |= flags;
525 }
526 
527 /***************************************************************************//**
528  * @brief
529  *   Get pending CAN message interrupt flags.
530  *
531  * @note
532  *   This function does not clear event bits.
533  *
534  * @param[in] can
535  *   A pointer to the CAN peripheral register block.
536  *
537  * @return
538  *   CAN message interrupt source(s) pending.
539  ******************************************************************************/
CAN_MessageIntGet(CAN_TypeDef * can)540 __STATIC_INLINE uint32_t CAN_MessageIntGet(CAN_TypeDef *can)
541 {
542   return can->IF0IF;
543 }
544 
545 /***************************************************************************//**
546  * @brief
547  *   Get CAN message interrupt flags that are pending and enabled.
548  *
549  * @note
550  *   This function does not clear event bits.
551  *
552  * @param[in] can
553  *   A pointer to the CAN peripheral register block.
554  *
555  * @return
556  *   CAN message interrupt source(s) pending and enabled.
557  ******************************************************************************/
CAN_MessageIntGetEnabled(CAN_TypeDef * can)558 __STATIC_INLINE uint32_t CAN_MessageIntGetEnabled(CAN_TypeDef *can)
559 {
560   uint32_t ien;
561 
562   ien = can->IF0IEN;
563   return can->IF0IF & ien;
564 }
565 
566 /***************************************************************************//**
567  * @brief
568  *   Set one or more CAN message interrupts.
569  *
570  * @param[in] can
571  *   A pointer to the CAN peripheral register block.
572  *
573  * @param[in] flags
574  *   CAN message interrupt source(s) to set as pending.
575  ******************************************************************************/
CAN_MessageIntSet(CAN_TypeDef * can,uint32_t flags)576 __STATIC_INLINE void CAN_MessageIntSet(CAN_TypeDef *can, uint32_t flags)
577 {
578   can->IF0IFS = flags;
579 }
580 
581 /** @} (end addtogroup can) */
582 
583 #ifdef __cplusplus
584 }
585 #endif
586 
587 #endif /* defined(CAN_COUNT) && (CAN_COUNT > 0) */
588 #endif /* EM_CAN_H */
589