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 #include "em_can.h"
32 #include "sl_common.h"
33 #include "sl_assert.h"
34 #include "em_cmu.h"
35 #include <stddef.h>
36 
37 #if defined(CAN_COUNT) && (CAN_COUNT > 0)
38 
39 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
40 
41 /* Macros to use for the ID field in the CANn_MIRx_ARB register as an 11 bit
42  * standard ID. The register field can be used for both an 11 bit standard
43  * ID and a 29 bit extended ID. */
44 #define _CAN_MIR_ARB_STD_ID_SHIFT         18
45 #define _CAN_MIR_MASK_STD_SHIFT           18
46 #define _CAN_MIR_ARB_STD_ID_MASK          0x1FFC0000UL
47 #define _CAN_MIR_ARB_STD_ID_MAX           0x7FFUL // = 2^11 - 1
48 
49 #if (CAN_COUNT == 2)
50 #define CAN_VALID(can)  ((can == CAN0) || (can == CAN1))
51 #elif (CAN_COUNT == 1)
52 #define CAN_VALID(can)  (can == CAN0)
53 #else
54 #error "The actual number of CAN busses is not supported."
55 #endif
56 
57 /** @endcond */
58 
59 /***************************************************************************//**
60  * @addtogroup can CAN - Controller Area Network
61  * @brief Controller Area Network API
62  *
63  * @details The Controller Area Network Interface Bus (CAN) implements a
64  * multi-master serial bus for connecting microcontrollers and devices, also
65  * known as nodes, to communicate with each other in applications without a host
66  * computer. CAN is a message-based protocol, designed originally for automotive
67  * applications, but also used in many other scenarios.
68  * The complexity of a node can range from a simple I/O device up to an
69  * embedded computer with a CAN interface and sophisticated software. The node
70  * may also be a gateway allowing a standard computer to communicate over a USB
71  * or Ethernet port to the devices on a CAN network. Devices are connected to
72  * the bus through a host processor, a CAN controller, and a CAN transceiver.
73  *
74  * @include em_can_send_example.c
75  *
76  * @{
77  ******************************************************************************/
78 
79 /*******************************************************************************
80  **************************   GLOBAL FUNCTIONS   *******************************
81  ******************************************************************************/
82 
83 /***************************************************************************//**
84  * @brief
85  *   Initialize CAN.
86  *
87  * @param[in] can
88  *   A pointer to the CAN peripheral register block.
89  *
90  * @param[in] init
91  *   A pointer to the CAN initialization structure.
92  ******************************************************************************/
CAN_Init(CAN_TypeDef * can,const CAN_Init_TypeDef * init)93 void CAN_Init(CAN_TypeDef *can, const CAN_Init_TypeDef *init)
94 {
95   EFM_ASSERT(CAN_VALID(can));
96 
97   CAN_Enable(can, false);
98   can->CTRL = _CAN_CTRL_TEST_MASK;
99   can->TEST = _CAN_TEST_RESETVALUE;
100   if (init->resetMessages) {
101     CAN_ResetMessages(can, 0);
102   }
103   can->CTRL = CAN_CTRL_INIT;
104   CAN_SetBitTiming(can,
105                    init->bitrate,
106                    init->propagationTimeSegment,
107                    init->phaseBufferSegment1,
108                    init->phaseBufferSegment2,
109                    init->synchronisationJumpWidth);
110   CAN_Enable(can, init->enable);
111 }
112 
113 /***************************************************************************//**
114  * @brief
115  *   Get the CAN module frequency.
116  *
117  * @details
118  *   An internal prescaler of 2 is inside the CAN module.
119  *
120  * @param[in] can
121  *   A pointer to the CAN peripheral register block.
122  *
123  * @return
124  *   A clock value.
125  ******************************************************************************/
CAN_GetClockFrequency(CAN_TypeDef * can)126 uint32_t CAN_GetClockFrequency(CAN_TypeDef *can)
127 {
128 #if defined CAN0
129   if (can == CAN0) {
130     return CMU_ClockFreqGet(cmuClock_CAN0) / 2;
131   }
132 #endif
133 
134 #if defined CAN1
135   if (can == CAN1) {
136     return CMU_ClockFreqGet(cmuClock_CAN1) / 2;
137   }
138 #endif
139   EFM_ASSERT(false);
140   return 0;
141 }
142 
143 /***************************************************************************//**
144  * @brief
145  *   Read a Message Object to find if a message was lost ; reset the
146  *   'Message Lost' flag.
147  *
148  * @param[in] can
149  *   A pointer to the CAN peripheral register block.
150  *
151  * @param[in] interface
152  *   Indicate which Message Interface Register to use.
153  *
154  * @param[in] msgNum
155  *   A message number of the Message Object, [1 - 32].
156  *
157  * @return
158  *   True if a message was lost, false otherwise.
159  ******************************************************************************/
CAN_MessageLost(CAN_TypeDef * can,uint8_t interface,uint8_t msgNum)160 bool CAN_MessageLost(CAN_TypeDef *can, uint8_t interface, uint8_t msgNum)
161 {
162   CAN_MIR_TypeDef * mir = &can->MIR[interface];
163   bool messageLost;
164 
165   /* Make sure msgNum is in the correct range. */
166   EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
167 
168   CAN_ReadyWait(can, interface);
169 
170   /* Set which registers to read from RAM. */
171   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
172                  | CAN_MIR_CMDMASK_CONTROL
173                  | CAN_MIR_CMDMASK_CLRINTPND;
174 
175   /* Send reading request and wait (3 to 6 cpu cycle). */
176   CAN_SendRequest(can, interface, msgNum, true);
177 
178   messageLost = mir->CTRL & _CAN_MIR_CTRL_MESSAGEOF_MASK;
179 
180   if (messageLost) {
181     mir->CMDMASK = CAN_MIR_CMDMASK_WRRD | CAN_MIR_CMDMASK_CONTROL;
182 
183     /* Reset the 'MessageLost' bit. */
184     mir->CTRL &= ~_CAN_MIR_CTRL_MESSAGEOF_MASK;
185 
186     /* Send reading request and wait (3 to 6 cpu cycle). */
187     CAN_SendRequest(can, interface, msgNum, true);
188   }
189 
190   /* Return the state of the MESSAGEOF bit. */
191   return messageLost;
192 }
193 
194 /***************************************************************************//**
195  * @brief
196  *   Set the ROUTE registers.
197  *
198  * @param[in] can
199  *   A pointer to the CAN peripheral register block.
200  *
201  * @param[in] active
202  *   A boolean indicating whether or not to activate the ROUTE registers.
203  *
204  * @param[in] pinRxLoc
205  *   A location of the RX pin.
206  *
207  * @param[in] pinTxLoc
208  *   A location of the TX pin.
209  ******************************************************************************/
CAN_SetRoute(CAN_TypeDef * can,bool active,uint16_t pinRxLoc,uint16_t pinTxLoc)210 void CAN_SetRoute(CAN_TypeDef *can,
211                   bool active,
212                   uint16_t pinRxLoc,
213                   uint16_t pinTxLoc)
214 {
215   if (active) {
216     /* Set the ROUTE register */
217     can->ROUTE = CAN_ROUTE_TXPEN
218                  | (pinRxLoc << _CAN_ROUTE_RXLOC_SHIFT)
219                  | (pinTxLoc << _CAN_ROUTE_TXLOC_SHIFT);
220   } else {
221     /* Deactivate the ROUTE register */
222     can->ROUTE = 0x0;
223   }
224 }
225 
226 /***************************************************************************//**
227  * @brief
228  *   Set the bitrate and its parameters.
229  *
230  * @details
231  *   Multiple parameters need to be properly configured.
232  *   See the reference manual for a detailed description.
233  *   Careful : the BRP (Baud Rate Prescaler) is calculated by:
234  *   'brp = freq / (period * bitrate);'. freq is the frequency of the CAN
235  *   device, period the time of transmission of a bit. The result is an uint32_t.
236  *   Hence it's truncated, causing an approximation error. This error is non
237  *   negligible when the period is high, the bitrate is high, and frequency is low.
238  *
239  * @param[in] can
240  *   A pointer to the CAN peripheral register block.
241  *
242  * @param[in] bitrate
243  *   A wanted bitrate on the CAN bus.
244  *
245  * @param[in] propagationTimeSegment
246  *   A value for the Propagation Time Segment.
247  *
248  * @param[in] phaseBufferSegment1
249  *   A value for the Phase Buffer Segment 1.
250  *
251  * @param[in] phaseBufferSegment2
252  *   A value for the Phase Buffer Segment 2.
253  *
254  * @param[in] synchronisationJumpWidth
255  *   A value for the Synchronization Jump Width.
256  ******************************************************************************/
CAN_SetBitTiming(CAN_TypeDef * can,uint32_t bitrate,uint16_t propagationTimeSegment,uint16_t phaseBufferSegment1,uint16_t phaseBufferSegment2,uint16_t synchronisationJumpWidth)257 void CAN_SetBitTiming(CAN_TypeDef *can,
258                       uint32_t bitrate,
259                       uint16_t propagationTimeSegment,
260                       uint16_t phaseBufferSegment1,
261                       uint16_t phaseBufferSegment2,
262                       uint16_t synchronisationJumpWidth)
263 {
264   uint32_t sum, brp, period, freq, brpHigh, brpLow;
265 
266   /* Verification that the parameters are in range. */
267   EFM_ASSERT((propagationTimeSegment <= 8) && (propagationTimeSegment > 0));
268   EFM_ASSERT((phaseBufferSegment1 <= 8) && (phaseBufferSegment1 > 0));
269   EFM_ASSERT((phaseBufferSegment2 <= 8) && (phaseBufferSegment2 > 0));
270   EFM_ASSERT(bitrate > 0);
271   EFM_ASSERT((synchronisationJumpWidth <= phaseBufferSegment1)
272              && (synchronisationJumpWidth <= phaseBufferSegment2)
273              && (synchronisationJumpWidth > 0));
274 
275   /* propagationTimeSegment is counted as part of phaseBufferSegment1 in the
276      BITTIMING register. */
277   sum = phaseBufferSegment1 + propagationTimeSegment;
278 
279   /* Period is the total length of one CAN bit. 1 is the Sync_seg. */
280   period = 1 + sum + phaseBufferSegment2;
281   freq = CAN_GetClockFrequency(can);
282 
283   brp = freq / (period * bitrate);
284   EFM_ASSERT(brp != 0);
285 
286   /* -1 because the hardware reads 'written value + 1'. */
287   brp = brp - 1;
288 
289   /* brp is divided between two registers. */
290   brpHigh = brp / 64;
291   brpLow = brp % 64;
292 
293   /* Checking register limit. */
294   EFM_ASSERT(brpHigh <= 15);
295 
296   bool enabled = CAN_IsEnabled(can);
297 
298   /* Enable access to the bittiming registers. */
299   can->CTRL |= CAN_CTRL_CCE | CAN_CTRL_INIT;
300 
301   can->BITTIMING = (brpLow << _CAN_BITTIMING_BRP_SHIFT)
302                    | ((synchronisationJumpWidth - 1) << _CAN_BITTIMING_SJW_SHIFT)
303                    | ((sum - 1) << _CAN_BITTIMING_TSEG1_SHIFT)
304                    | ((phaseBufferSegment2 - 1) << _CAN_BITTIMING_TSEG2_SHIFT);
305   can->BRPE = brpHigh;
306 
307   if (enabled) {
308     can->CTRL &= ~(_CAN_CTRL_CCE_MASK | _CAN_CTRL_INIT_MASK);
309   } else {
310     can->CTRL &= ~_CAN_CTRL_CCE_MASK;
311   }
312 }
313 
314 /***************************************************************************//**
315  * @brief
316  *   Set the CAN operation mode.
317  *
318  * @details
319  *   In initialization mode, the CAN module is deactivated. Reset the messages in all
320  *   other modes to be sure that there is no leftover data that
321  *   needs to be configured before use.
322  *
323  * @param[in] can
324  *   A pointer to the CAN peripheral register block.
325  *
326  * @param[in] mode
327  *   Mode of operation : Init, Normal, Loopback, SilentLoopback, Silent, Basic.
328  ******************************************************************************/
CAN_SetMode(CAN_TypeDef * can,CAN_Mode_TypeDef mode)329 void CAN_SetMode(CAN_TypeDef *can, CAN_Mode_TypeDef mode)
330 {
331   switch (mode) {
332     case canModeNormal:
333       can->CTRL |= _CAN_CTRL_TEST_MASK;
334       can->TEST = _CAN_TEST_RESETVALUE;
335       can->CTRL &= ~_CAN_CTRL_TEST_MASK;
336 
337       can->CTRL = _CAN_CTRL_EIE_MASK
338                   | _CAN_CTRL_SIE_MASK
339                   | _CAN_CTRL_IE_MASK;
340       break;
341 
342     case canModeBasic:
343       can->CTRL = _CAN_CTRL_EIE_MASK
344                   | _CAN_CTRL_SIE_MASK
345                   | _CAN_CTRL_IE_MASK
346                   | CAN_CTRL_TEST;
347       can->TEST = CAN_TEST_BASIC;
348       break;
349 
350     case canModeLoopBack:
351       can->CTRL = _CAN_CTRL_EIE_MASK
352                   | _CAN_CTRL_SIE_MASK
353                   | _CAN_CTRL_IE_MASK
354                   | CAN_CTRL_TEST;
355       can->TEST = CAN_TEST_LBACK;
356       break;
357 
358     case canModeSilentLoopBack:
359       can->CTRL = _CAN_CTRL_EIE_MASK
360                   | _CAN_CTRL_SIE_MASK
361                   | _CAN_CTRL_IE_MASK
362                   | CAN_CTRL_TEST;
363       can->TEST = CAN_TEST_LBACK | CAN_TEST_SILENT;
364       break;
365 
366     case canModeSilent:
367       can->CTRL = _CAN_CTRL_EIE_MASK
368                   | _CAN_CTRL_SIE_MASK
369                   | _CAN_CTRL_IE_MASK
370                   | CAN_CTRL_TEST;
371       can->TEST = CAN_TEST_SILENT;
372       break;
373 
374     default:
375       break;
376   }
377 }
378 
379 /***************************************************************************//**
380  * @brief
381  *   Set the ID and the filter for a specific Message Object.
382  *
383  * @details
384  *   The initialization bit has to be 0 to use this function.
385  *
386  * @param[in] can
387  *   A pointer to the CAN peripheral register block.
388  *
389  * @param[in] interface
390  *   Indicate which Message Interface Register to use.
391  *
392  * @param[in] useMask
393  *   A boolean to choose whether or not to use the masks.
394  *
395  * @param[in] message
396  *   A Message Object.
397  *
398  * @param[in] wait
399  *   If true, wait for the end of the transfer between the MIRx registers and
400  *   the RAM to exit. If false, exit immediately, the transfer can still be
401  *   in progress.
402  ******************************************************************************/
CAN_SetIdAndFilter(CAN_TypeDef * can,uint8_t interface,bool useMask,const CAN_MessageObject_TypeDef * message,bool wait)403 void CAN_SetIdAndFilter(CAN_TypeDef *can,
404                         uint8_t interface,
405                         bool useMask,
406                         const CAN_MessageObject_TypeDef *message,
407                         bool wait)
408 {
409   /* Make sure msgNum is in the correct range. */
410   EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
411 
412   CAN_MIR_TypeDef * mir = &can->MIR[interface];
413   CAN_ReadyWait(can, interface);
414 
415   /* Set which registers to read from RAM. */
416   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
417                  | CAN_MIR_CMDMASK_ARBACC
418                  | CAN_MIR_CMDMASK_CONTROL;
419 
420   /* Send reading request and wait (3 to 6 CPU cycle). */
421   CAN_SendRequest(can, interface, message->msgNum, true);
422 
423   /* Reset MSGVAL. */
424   mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
425   mir->ARB &= ~CAN_MIR_ARB_MSGVAL;
426   CAN_SendRequest(can, interface, message->msgNum, true);
427 
428   /* Set which registers to write to RAM. */
429   mir->CMDMASK |= CAN_MIR_CMDMASK_MASKACC;
430 
431   /* Set UMASK bit. */
432   BUS_RegBitWrite(&mir->CTRL, _CAN_MIR_CTRL_UMASK_SHIFT, useMask);
433 
434   /* Configure the ID. */
435   if (message->extended) {
436     EFM_ASSERT(message->id <= _CAN_MIR_ARB_ID_MASK);
437     mir->ARB = (mir->ARB & ~_CAN_MIR_ARB_ID_MASK)
438                | (message->id << _CAN_MIR_ARB_ID_SHIFT)
439                | CAN_MIR_ARB_MSGVAL
440                | CAN_MIR_ARB_XTD_EXT;
441   } else {
442     EFM_ASSERT(message->id <= _CAN_MIR_ARB_STD_ID_MAX);
443     mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_ID_MASK | CAN_MIR_ARB_XTD_STD))
444                | (message->id << _CAN_MIR_ARB_STD_ID_SHIFT)
445                | CAN_MIR_ARB_MSGVAL;
446   }
447 
448   if (message->extendedMask) {
449     mir->MASK = (message->mask << _CAN_MIR_MASK_MASK_SHIFT)
450                 & _CAN_MIR_MASK_MASK_MASK;
451   } else {
452     mir->MASK = (message->mask << _CAN_MIR_MASK_STD_SHIFT)
453                 & _CAN_MIR_ARB_STD_ID_MASK;
454   }
455 
456   /* Configure the masks. */
457   mir->MASK |= (message->extendedMask << _CAN_MIR_MASK_MXTD_SHIFT)
458                | (message->directionMask << _CAN_MIR_MASK_MDIR_SHIFT);
459 
460   /* Send a writing request. */
461   CAN_SendRequest(can, interface, message->msgNum, wait);
462 }
463 
464 /***************************************************************************//**
465  * @brief
466  *   Configure valid, TX/RX, remoteTransfer for a specific Message Object.
467  *
468  * @details
469  *   The initialization bit has to be 0 to use this function.
470  *
471  * @param[in] can
472  *   A pointer to the CAN peripheral register block.
473  *
474  * @param[in] interface
475  *   Indicate which Message Interface Register to use.
476  *
477  * @param[in] msgNum
478  *   A message number of this Message Object, [1 - 32].
479  *
480  * @param[in] valid
481  *   True if the Message Object is valid, false otherwise.
482  *
483  * @param[in] tx
484  *   True if the Message Object is used for transmission, false if used for
485  *   reception.
486  *
487  * @param[in] remoteTransfer
488  *   True if the Message Object is used for remote transmission, false otherwise.
489  *
490  * @param[in] endOfBuffer
491  *   True if it is for a single Message Object or the end of a FIFO buffer,
492  *   false if the Message Object is part of a FIFO buffer and not the last.
493  *
494  * @param[in] wait
495  *   If true, wait for the end of the transfer between the MIRx registers and
496  *   the RAM to exit. If false, exit immediately, the transfer can still be
497  *   in progress.
498  ******************************************************************************/
CAN_ConfigureMessageObject(CAN_TypeDef * can,uint8_t interface,uint8_t msgNum,bool valid,bool tx,bool remoteTransfer,bool endOfBuffer,bool wait)499 void CAN_ConfigureMessageObject(CAN_TypeDef *can,
500                                 uint8_t interface,
501                                 uint8_t msgNum,
502                                 bool valid,
503                                 bool tx,
504                                 bool remoteTransfer,
505                                 bool endOfBuffer,
506                                 bool wait)
507 {
508   CAN_MIR_TypeDef * mir = &can->MIR[interface];
509 
510   /* Make sure msgNum is in correct range. */
511   EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
512 
513   CAN_ReadyWait(can, interface);
514 
515   /* Set which registers to read from RAM. */
516   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
517                  | CAN_MIR_CMDMASK_ARBACC
518                  | CAN_MIR_CMDMASK_CONTROL;
519 
520   /* Send reading request and wait (3 to 6 CPU cycle). */
521   CAN_SendRequest(can, interface, msgNum, true);
522 
523   /* Reset MSGVAL. */
524   mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
525   mir->ARB &= ~CAN_MIR_ARB_MSGVAL;
526   CAN_SendRequest(can, interface, msgNum, true);
527 
528   /* Configure a valid message and direction. */
529   mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_DIR_MASK | _CAN_MIR_ARB_MSGVAL_MASK))
530              | (valid << _CAN_MIR_ARB_MSGVAL_SHIFT)
531              | (tx << _CAN_MIR_ARB_DIR_SHIFT);
532 
533   /* Set EOB bit, RX, and TX interrupts. */
534   mir->CTRL = (endOfBuffer << _CAN_MIR_CTRL_EOB_SHIFT)
535               | _CAN_MIR_CTRL_TXIE_MASK
536               | _CAN_MIR_CTRL_RXIE_MASK
537               | (remoteTransfer << _CAN_MIR_CTRL_RMTEN_SHIFT);
538 
539   /* Send a writing request. */
540   CAN_SendRequest(can, interface, msgNum, wait);
541 }
542 
543 /***************************************************************************//**
544  * @brief
545  *   Send data from the Message Object message.
546  *
547  * @details
548  *   If the message is configured as TX and remoteTransfer = 0, calling this function
549  *   will send the data of this Message Object if its parameters are correct.
550  *   If the message is TX and remoteTransfer = 1, this function will set the data of
551  *   message to RAM and exit. Data will be automatically sent after
552  *   reception of a remote frame.
553  *   If the message is RX and remoteTransfer = 1, this function will send a remote
554  *   frame to the corresponding ID.
555  *   If the message is RX and remoteTransfer = 0, the user shouldn't call this
556  *   function. It will also send a remote frame.
557  *
558  * @param[in] can
559  *   A pointer to the CAN peripheral register block.
560  *
561  * @param[in] interface
562  *   Indicate which Message Interface Register to use.
563  *
564  * @param[in] message
565  *   A Message Object.
566  *
567  * @param[in] wait
568  *   If true, wait for the end of the transfer between the MIRx registers and
569  *   RAM to exit. If false, exit immediately. The transfer can still be
570  *   in progress.
571  ******************************************************************************/
CAN_SendMessage(CAN_TypeDef * can,uint8_t interface,const CAN_MessageObject_TypeDef * message,bool wait)572 void CAN_SendMessage(CAN_TypeDef *can,
573                      uint8_t interface,
574                      const CAN_MessageObject_TypeDef *message,
575                      bool wait)
576 {
577   CAN_MIR_TypeDef * mir = &can->MIR[interface];
578 
579   /* Make sure msgNum is in correct range. */
580   EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
581   /* Make sure dlc is in correct range. */
582   EFM_ASSERT(message->dlc <= _CAN_MIR_CTRL_DLC_MASK);
583 
584   CAN_ReadyWait(can, interface);
585 
586   /* Set LEC to an unused value to be sure it is reset to 0 after sending. */
587   BUS_RegMaskedWrite(&can->STATUS, _CAN_STATUS_LEC_MASK, 0x7);
588 
589   /* Set which registers to read from RAM. */
590   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
591                  | CAN_MIR_CMDMASK_ARBACC
592                  | CAN_MIR_CMDMASK_CONTROL;
593 
594   /* Send a reading request and wait (3 to 6 CPU cycle). */
595   CAN_SendRequest(can, interface, message->msgNum, true);
596 
597   /* Reset MSGVAL. */
598   mir->CMDMASK |= CAN_MIR_CMDMASK_WRRD_WRITE;
599   mir->ARB &= ~CAN_MIR_ARB_MSGVAL;
600   CAN_SendRequest(can, interface, message->msgNum, true);
601 
602   /* Set which registers to write to RAM. */
603   if ( ((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == 0)
604        || (((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == CAN_MIR_CTRL_RMTEN)
605            && ((mir->ARB & _CAN_MIR_ARB_DIR_MASK) == CAN_MIR_ARB_DIR_TX)) ) {
606     mir->CMDMASK |= CAN_MIR_CMDMASK_DATAA
607                     | CAN_MIR_CMDMASK_DATAB;
608 
609     /* Set data. */
610     CAN_WriteData(can, interface, message);
611   }
612 
613   /* If TX = 1 and remoteTransfer = 1, nothing is sent. */
614   if ( ((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == 0)
615        || ((mir->ARB & _CAN_MIR_ARB_DIR_MASK) == CAN_MIR_ARB_DIR_RX)) {
616     mir->CTRL |= CAN_MIR_CTRL_TXRQST;
617     /* DATAVALID is set only if it is not sending a remote message. */
618     if ((mir->CTRL & _CAN_MIR_CTRL_RMTEN_MASK) == 0) {
619       mir->CTRL |= CAN_MIR_CTRL_DATAVALID;
620     }
621   }
622 
623   /* Set the data length code. */
624   mir->CTRL = (mir->CTRL & ~_CAN_MIR_CTRL_DLC_MASK)
625               | message->dlc;
626 
627   /* Configure the ID. */
628   if (message->extended) {
629     EFM_ASSERT(message->id <= _CAN_MIR_ARB_ID_MASK);
630     mir->ARB = (mir->ARB & ~_CAN_MIR_ARB_ID_MASK)
631                | (message->id << _CAN_MIR_ARB_ID_SHIFT)
632                | CAN_MIR_ARB_MSGVAL
633                | CAN_MIR_ARB_XTD_EXT;
634   } else {
635     EFM_ASSERT(message->id <= _CAN_MIR_ARB_STD_ID_MAX);
636     mir->ARB = (mir->ARB & ~(_CAN_MIR_ARB_ID_MASK | _CAN_MIR_ARB_XTD_MASK))
637                | CAN_MIR_ARB_MSGVAL
638                | (message->id << _CAN_MIR_ARB_STD_ID_SHIFT)
639                | CAN_MIR_ARB_XTD_STD;
640   }
641 
642   /* Send a writing request. */
643   CAN_SendRequest(can, interface, message->msgNum, wait);
644 }
645 
646 /***************************************************************************//**
647  * @brief
648  *   Read data and ID from a Message Object in RAM and store it in a message.
649  *
650  * @details
651  *   Read the information from RAM on this Message Object. Data and
652  *   the configuration of the Message Object is read. The information is only
653  *   read if the message stored in the Message Object is new and valid.
654  *
655  * @param[in] can
656  *   A pointer to the CAN peripheral register block.
657  *
658  * @param[in] interface
659  *   Indicate which Message Interface Register to use.
660  *
661  * @param[in] message
662  *   A Message Object.
663  *
664  * @return
665  *   True if the Message Object in RAM holds a new and valid message, which was
666  *   not read earlier, false otherwise.
667  ******************************************************************************/
CAN_ReadMessage(CAN_TypeDef * can,uint8_t interface,CAN_MessageObject_TypeDef * message)668 bool CAN_ReadMessage(CAN_TypeDef *can,
669                      uint8_t interface,
670                      CAN_MessageObject_TypeDef *message)
671 {
672   CAN_MIR_TypeDef * mir = &can->MIR[interface];
673   uint32_t buffer;
674   uint32_t i;
675 
676   /* Make sure msgNum is in correct range. */
677   EFM_ASSERT((message->msgNum > 0) && (message->msgNum <= 32));
678 
679   CAN_ReadyWait(can, interface);
680 
681   /* Set which registers to read from RAM. */
682   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
683                  | CAN_MIR_CMDMASK_MASKACC
684                  | CAN_MIR_CMDMASK_ARBACC
685                  | CAN_MIR_CMDMASK_CONTROL
686                  | CAN_MIR_CMDMASK_CLRINTPND
687                  | CAN_MIR_CMDMASK_TXRQSTNEWDAT
688                  | CAN_MIR_CMDMASK_DATAA
689                  | CAN_MIR_CMDMASK_DATAB;
690 
691   /* Send a reading request and wait (3 to 6 cpu cycle). */
692   CAN_SendRequest(can, interface, message->msgNum, true);
693 
694   if ((mir->CTRL & CAN_MIR_CTRL_DATAVALID) == 0) {
695     return false;
696   }
697 
698   /* Get dlc from the control register. */
699   message->dlc = ((mir->CTRL & _CAN_MIR_CTRL_DLC_MASK) >> _CAN_MIR_CTRL_DLC_SHIFT);
700 
701   /* Make sure dlc is in correct range. */
702   EFM_ASSERT(message->dlc <= 8);
703 
704   /* Get id from the control register */
705   if (message->extended) {
706     message->id = (mir->ARB & _CAN_MIR_ARB_ID_MASK);
707   } else {
708     message->id = ((mir->ARB & _CAN_MIR_ARB_STD_ID_MASK) >> _CAN_MIR_ARB_STD_ID_SHIFT);
709   }
710 
711   /* Copy data from the MIR registers to the Message Object message. */
712   buffer = mir->DATAL;
713   for (i = 0; i < SL_MIN(message->dlc, 4U); ++i) {
714     message->data[i] = buffer & 0xFF;
715     buffer = buffer >> 8;
716   }
717   if (message->dlc > 3) {
718     buffer = mir->DATAH;
719     for (i = 0; i < message->dlc - 4U; ++i) {
720       message->data[i + 4] = buffer & 0xFF;
721       buffer = buffer >> 8;
722     }
723   }
724 
725   return true;
726 }
727 
728 /***************************************************************************//**
729  * @brief
730  *   Abort sending a message.
731  *
732  * @details
733  *   Set the TXRQST of the CTRL register to 0. Doesn't touch data or the
734  *   other parameters. The user can call CAN_SendMessage() to send the object
735  *   after using CAN_AbortSendMessage().
736  *
737  * @param[in] can
738  *   A pointer to the CAN peripheral register block.
739  *
740  * @param[in] interface
741  *   Indicate which Message Interface Register to use.
742  *
743  * @param[in] msgNum
744  *   A message number of this Message Object, [1 - 32].
745  *
746  * @param[in] wait
747  *   If true, wait for the end of the transfer between the MIRx registers and
748  *   the RAM to exit. If false, exit immediately. The transfer can still be
749  *   in progress.
750  ******************************************************************************/
CAN_AbortSendMessage(CAN_TypeDef * can,uint8_t interface,uint8_t msgNum,bool wait)751 void CAN_AbortSendMessage(CAN_TypeDef *can,
752                           uint8_t interface,
753                           uint8_t msgNum,
754                           bool wait)
755 {
756   /* Make sure msgNum is in correct range. */
757   EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
758 
759   CAN_MIR_TypeDef * mir = &can->MIR[interface];
760   CAN_ReadyWait(can, interface);
761 
762   /* Set which registers to read from RAM. */
763   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD_READ
764                  | CAN_MIR_CMDMASK_CONTROL;
765 
766   /* Send a reading request and wait (3 to 6 cpu cycle). */
767   CAN_SendRequest(can, interface, msgNum, true);
768 
769   /* Set which registers to write to RAM. */
770   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD
771                  | CAN_MIR_CMDMASK_CONTROL;
772 
773   /* Set TXRQST bit to 0. */
774   mir->CTRL &= ~_CAN_MIR_CTRL_TXRQST_MASK;
775 
776   /* Send a writing request. */
777   CAN_SendRequest(can, interface, msgNum, wait);
778 }
779 
780 /***************************************************************************//**
781  * @brief
782  *   Reset all Message Objects and set their data to 0.
783  *
784  * @param[in] can
785  *   A pointer to the CAN peripheral register block.
786  *
787  * @param[in] interface
788  *   Indicate which Message Interface Register to use.
789  ******************************************************************************/
CAN_ResetMessages(CAN_TypeDef * can,uint8_t interface)790 void CAN_ResetMessages(CAN_TypeDef *can, uint8_t interface)
791 {
792   CAN_MIR_TypeDef * mir = &can->MIR[interface];
793   CAN_ReadyWait(can, interface);
794 
795   /* Set which registers to read from RAM. */
796   mir->CMDMASK = CAN_MIR_CMDMASK_WRRD
797                  | CAN_MIR_CMDMASK_MASKACC
798                  | CAN_MIR_CMDMASK_ARBACC
799                  | CAN_MIR_CMDMASK_CONTROL
800                  | CAN_MIR_CMDMASK_DATAA
801                  | CAN_MIR_CMDMASK_DATAB;
802 
803   mir->MASK    = _CAN_MIR_MASK_RESETVALUE;
804   mir->ARB     = _CAN_MIR_ARB_RESETVALUE;
805   mir->CTRL    = _CAN_MIR_CTRL_RESETVALUE;
806   mir->DATAL   = 0x00000000;
807   mir->DATAH   = 0x00000000;
808 
809   /* Write each reset Message Object to RAM. */
810   for (int i = 1; i <= 32; ++i) {
811     CAN_SendRequest(can, interface, i, true);
812   }
813 }
814 
815 /***************************************************************************//**
816  * @brief
817  *   Set all CAN registers to RESETVALUE. Leave the CAN device disabled.
818  *
819  * @param[in] can
820  *   A pointer to the CAN peripheral register block.
821  ******************************************************************************/
CAN_Reset(CAN_TypeDef * can)822 void CAN_Reset(CAN_TypeDef *can)
823 {
824   CAN_ReadyWait(can, 0);
825   CAN_ReadyWait(can, 1);
826 
827   CAN_Enable(can, false);
828   can->STATUS = _CAN_STATUS_RESETVALUE;
829 
830   can->CTRL |= _CAN_CTRL_CCE_MASK;
831   can->BITTIMING = _CAN_BITTIMING_RESETVALUE;
832   can->CTRL &= ~_CAN_CTRL_CCE_MASK;
833 
834   can->CTRL |= _CAN_CTRL_TEST_MASK;
835   can->TEST = _CAN_TEST_RESETVALUE;
836   can->CTRL &= ~_CAN_CTRL_TEST_MASK;
837 
838   can->BRPE = _CAN_BRPE_RESETVALUE;
839   can->CONFIG = _CAN_CONFIG_RESETVALUE;
840   can->IF0IFS = _CAN_IF0IFS_RESETVALUE;
841   can->IF0IFC = _CAN_IF0IFC_RESETVALUE;
842   can->IF0IEN = _CAN_IF0IEN_RESETVALUE;
843   can->IF1IFS = _CAN_IF1IF_RESETVALUE;
844   can->IF1IFC = _CAN_IF1IFC_RESETVALUE;
845   can->IF1IEN = _CAN_IF1IEN_RESETVALUE;
846   can->ROUTE = _CAN_ROUTE_RESETVALUE;
847 
848   for (int i = 0; i < 2; i++) {
849     can->MIR[i].CMDMASK = _CAN_MIR_CMDMASK_RESETVALUE;
850     can->MIR[i].MASK = _CAN_MIR_MASK_RESETVALUE;
851     can->MIR[i].ARB = _CAN_MIR_ARB_RESETVALUE;
852     can->MIR[i].CTRL = _CAN_MIR_CTRL_RESETVALUE;
853     can->MIR[i].DATAL = _CAN_MIR_DATAL_RESETVALUE;
854     can->MIR[i].DATAH = _CAN_MIR_DATAH_RESETVALUE;
855     can->MIR[i].CMDREQ = _CAN_MIR_CMDREQ_RESETVALUE;
856   }
857 }
858 
859 /***************************************************************************//**
860  * @brief
861  *   Write data from a message to the MIRx registers.
862  *
863  * @param[in] can
864  *   A pointer to the CAN peripheral register block.
865  *
866  * @param[in] interface
867  *   Indicate which Message Interface Register to use.
868  *
869  * @param[in] message
870  *   A Message Object.
871  ******************************************************************************/
CAN_WriteData(CAN_TypeDef * can,uint8_t interface,const CAN_MessageObject_TypeDef * message)872 void CAN_WriteData(CAN_TypeDef *can,
873                    uint8_t interface,
874                    const CAN_MessageObject_TypeDef *message)
875 {
876   uint32_t tmp;
877   uint8_t data[8] = { 0 };
878   size_t length = SL_MIN(8, message->dlc);
879   CAN_MIR_TypeDef * mir = &can->MIR[interface];
880 
881   for (size_t i = 0; i < length; i++) {
882     data[i] = message->data[i];
883   }
884 
885   CAN_ReadyWait(can, interface);
886 
887   tmp = data[0];
888   tmp |= data[1] << 8;
889   tmp |= data[2] << 16;
890   tmp |= data[3] << 24;
891   mir->DATAL = tmp;
892 
893   tmp = data[4];
894   tmp |= data[5] << 8;
895   tmp |= data[6] << 16;
896   tmp |= data[7] << 24;
897   mir->DATAH = tmp;
898 }
899 
900 /***************************************************************************//**
901  * @brief
902  *   Send a request for writing or reading RAM of the Message Object msgNum.
903  *
904  * @param[in] can
905  *   A pointer to the CAN peripheral register block.
906  *
907  * @param[in] interface
908  *   Indicate which Message Interface Register to use.
909  *
910  * @param[in] msgNum
911  *   A message number of the Message Object, [1 - 32].
912  *
913  * @param[in] wait
914  *   If true, wait for the end of the transfer between the MIRx registers and
915  *   the RAM to exit. If false, exit immediately. The transfer can still be
916  *   in progress.
917  ******************************************************************************/
CAN_SendRequest(CAN_TypeDef * can,uint8_t interface,uint8_t msgNum,bool wait)918 void CAN_SendRequest(CAN_TypeDef *can,
919                      uint8_t interface,
920                      uint8_t msgNum,
921                      bool wait)
922 {
923   CAN_MIR_TypeDef * mir = &can->MIR[interface];
924 
925   /* Make sure msgNum is in correct range. */
926   EFM_ASSERT((msgNum > 0) && (msgNum <= 32));
927 
928   /* Make sure the MIRx registers aren't busy. */
929   CAN_ReadyWait(can, interface);
930 
931   /* Write msgNum to the CMDREQ register. */
932   mir->CMDREQ = msgNum << _CAN_MIR_CMDREQ_MSGNUM_SHIFT;
933 
934   if (wait) {
935     CAN_ReadyWait(can, interface);
936   }
937 }
938 
939 /** @} (end addtogroup can) */
940 
941 #endif /* defined(CAN_COUNT) && (CAN_COUNT > 0) */
942