flexcan_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
65 #include "flexcan_hw_access.h"
66 #include "flexcan_irq.h"
67 #include "interrupt_manager.h"
68 #include "clock_manager.h"
69 
70 /*******************************************************************************
71  * Definitions
72  ******************************************************************************/
73 
74 #define FLEXCAN_MB_HANDLE_RXFIFO 0U
75 
76 /* CAN bit timing values */
77 #define FLEXCAN_NUM_TQ_MIN 8U
78 #define FLEXCAN_NUM_TQ_MAX 26U
79 #define FLEXCAN_PRESDIV_MAX 256U
80 #define FLEXCAN_PSEG1_MAX 8U
81 #define FLEXCAN_PSEG2_MIN 1U
82 #define FLEXCAN_PSEG2_MAX 8U
83 #define FLEXCAN_PROPSEG_MAX 8U
84 #define FLEXCAN_TSEG1_MIN 2U
85 #define FLEXCAN_TSEG1_MAX 17U
86 #define FLEXCAN_TSEG2_MIN 2U
87 #define FLEXCAN_TSEG2_MAX 9U
88 #define FLEXCAN_RJW_MAX 3U
89 
90 /*******************************************************************************
91  * Variables
92  ******************************************************************************/
93 
94 /* Table of base addresses for CAN instances. */
96 
97 /* Tables to save CAN IRQ enum numbers defined in CMSIS header file. */
98 #if FEATURE_CAN_HAS_WAKE_UP_IRQ
100 #endif
105 
106 /* Pointer to runtime state structure.*/
108 
109 /*******************************************************************************
110  * Private Functions
111  ******************************************************************************/
113  uint8_t instance,
114  uint8_t mb_idx,
115  const flexcan_data_info_t *tx_info,
116  uint32_t msg_id,
117  const uint8_t *mb_data,
118  bool isBlocking
119  );
121  uint8_t instance,
122  uint8_t mb_idx,
123  flexcan_msgbuff_t *data,
124  bool isBlocking
125  );
127  uint8_t instance,
128  flexcan_msgbuff_t *data,
129  bool isBlocking
130  );
131 static void FLEXCAN_CompleteTransfer(uint8_t instance, uint32_t mb_idx);
132 static void FLEXCAN_CompleteRxMessageFifoData(uint8_t instance);
133 #if FEATURE_CAN_HAS_DMA_ENABLE
134 static void FLEXCAN_CompleteRxFifoDataDMA(void *parameter,
135  edma_chn_status_t status);
136 static void FLEXCAN_BitrateToTimeSeg(uint32_t bitrate,
137  uint32_t clkFreq,
138  flexcan_time_segment_t *timeSeg);
139 #endif
140 /*******************************************************************************
141  * Code
142  ******************************************************************************/
143 
144 /*FUNCTION**********************************************************************
145  *
146  * Function Name : FLEXCAN_DRV_SetBitrate
147  * Description : Set FlexCAN baudrate.
148  * This function will set up all the time segment values for classical frames or the
149  * extended time segments for the arbitration phase of FD frames. Those time segment
150  * values are passed in by the user and are based on the required baudrate.
151  *
152  * Implements : FLEXCAN_DRV_SetBitrate_Activity
153  *END**************************************************************************/
154 void FLEXCAN_DRV_SetBitrate(uint8_t instance, const flexcan_time_segment_t *bitrate)
155 {
156  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
157  DEV_ASSERT(bitrate != NULL);
158 
159  CAN_Type * base = g_flexcanBase[instance];
160 #if FEATURE_CAN_HAS_FD
161  bool fdEnabled = FLEXCAN_IsFDEnabled(base);
162 #endif
163 
164  FLEXCAN_EnterFreezeMode(base);
165 
166 #if FEATURE_CAN_HAS_FD
167  if (fdEnabled)
168  {
169  /* Set extended time segments*/
170  FLEXCAN_SetExtendedTimeSegments(base, bitrate);
171  }
172  else
173 #endif
174  {
175  /* Set time segments*/
176  FLEXCAN_SetTimeSegments(base, bitrate);
177  }
178 
179  FLEXCAN_ExitFreezeMode(base);
180 }
181 
182 #if FEATURE_CAN_HAS_FD
183 /*FUNCTION**********************************************************************
184  *
185  * Function Name : FLEXCAN_DRV_SetBitrateCbt
186  * Description : Set FlexCAN bitrate.
187  * This function will set up all the time segment values for the data phase of
188  * FD frames. Those time segment values are passed in by the user and are based
189  * on the required baudrate.
190  *
191  * Implements : FLEXCAN_DRV_SetBitrateCbt_Activity
192  *END**************************************************************************/
193 void FLEXCAN_DRV_SetBitrateCbt(uint8_t instance, const flexcan_time_segment_t *bitrate)
194 {
195  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
196  DEV_ASSERT(bitrate != NULL);
197 
198  CAN_Type * base = g_flexcanBase[instance];
199 
200  FLEXCAN_EnterFreezeMode(base);
201 
202  /* Set time segments*/
203  FLEXCAN_SetFDTimeSegments(base, bitrate);
204 
205  FLEXCAN_ExitFreezeMode(base);
206 }
207 #endif
208 
209 /*FUNCTION**********************************************************************
210  *
211  * Function Name : FLEXCAN_DRV_GetBitrate
212  * Description : Get FlexCAN baudrate.
213  * This function will be return the current bit rate settings for classical frames
214  * or the arbitration phase of FD frames.
215  *
216  * Implements : FLEXCAN_DRV_GetBitrate_Activity
217  *END**************************************************************************/
218 void FLEXCAN_DRV_GetBitrate(uint8_t instance, flexcan_time_segment_t *bitrate)
219 {
220  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
221  DEV_ASSERT(bitrate != NULL);
222 
223  CAN_Type * base = g_flexcanBase[instance];
224 
225  FLEXCAN_EnterFreezeMode(base);
226 
227  /* Get the time segments*/
228  FLEXCAN_GetTimeSegments(base, bitrate);
229 
230  FLEXCAN_ExitFreezeMode(base);
231 }
232 
233 #if FEATURE_CAN_HAS_FD
234 /*FUNCTION**********************************************************************
235  *
236  * Function Name : FLEXCAN_DRV_GetBitrateFD
237  * Description : Get FlexCAN baudrate.
238  * This function will be return the current bit rate settings for the data phase
239  * of FD frames.
240  *
241  * Implements : FLEXCAN_DRV_GetBitrateFD_Activity
242  *END**************************************************************************/
243 void FLEXCAN_DRV_GetBitrateFD(uint8_t instance, flexcan_time_segment_t *bitrate)
244 {
245  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
246  DEV_ASSERT(bitrate != NULL);
247 
248  CAN_Type * base = g_flexcanBase[instance];
249 
250  FLEXCAN_EnterFreezeMode(base);
251 
252  /* Get the time segments*/
253  FLEXCAN_GetFDTimeSegments(base, bitrate);
254 
255  FLEXCAN_ExitFreezeMode(base);
256 }
257 #endif
258 
259 /*FUNCTION**********************************************************************
260  *
261  * Function Name : FLEXCAN_DRV_SetMasktype
262  * Description : Set RX masking type.
263  * This function will set RX masking type as RX global mask or RX individual
264  * mask.
265  *
266  * Implements : FLEXCAN_DRV_SetRxMaskType_Activity
267  *END**************************************************************************/
269 {
270  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
271 
272  CAN_Type * base = g_flexcanBase[instance];
273 
274  FLEXCAN_EnterFreezeMode(base);
275 
276  FLEXCAN_SetRxMaskType(base, type);
277 
278  FLEXCAN_ExitFreezeMode(base);
279 }
280 
281 /*FUNCTION**********************************************************************
282  *
283  * Function Name : FLEXCAN_DRV_SetRxFifoGlobalMask
284  * Description : Set Rx FIFO global mask as the 11-bit standard mask or the
285  * 29-bit extended mask.
286  *
287  * Implements : FLEXCAN_DRV_SetRxFifoGlobalMask_Activity
288  *END**************************************************************************/
290  uint8_t instance,
292  uint32_t mask)
293 {
294  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
295 
296  CAN_Type * base = g_flexcanBase[instance];
297 
298  FLEXCAN_EnterFreezeMode(base);
299 
300  if (id_type == FLEXCAN_MSG_ID_STD)
301  {
302  /* Set standard global mask for RX FIOF*/
303  FLEXCAN_SetRxFifoGlobalStdMask(base, mask);
304  }
305  else if (id_type == FLEXCAN_MSG_ID_EXT)
306  {
307  /* Set extended global mask for RX FIFO*/
308  FLEXCAN_SetRxFifoGlobalExtMask(base, mask);
309  }
310  else {
311  /* Should not get here */
312  }
313 
314  FLEXCAN_ExitFreezeMode(base);
315 }
316 
317 /*FUNCTION**********************************************************************
318  *
319  * Function Name : FLEXCAN_DRV_SetRxMbGlobalMask
320  * Description : Set Rx Message Buffer global mask as the 11-bit standard mask
321  * or the 29-bit extended mask.
322  *
323  * Implements : FLEXCAN_DRV_SetRxMbGlobalMask_Activity
324  *END**************************************************************************/
326  uint8_t instance,
328  uint32_t mask)
329 {
330  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
331 
332  CAN_Type * base = g_flexcanBase[instance];
333 
334  FLEXCAN_EnterFreezeMode(base);
335 
336  if (id_type == FLEXCAN_MSG_ID_STD)
337  {
338  /* Set standard global mask for RX MB*/
339  FLEXCAN_SetRxMsgBuffGlobalStdMask(base, mask);
340  }
341  else if (id_type == FLEXCAN_MSG_ID_EXT)
342  {
343  /* Set extended global mask for RX MB*/
344  FLEXCAN_SetRxMsgBuffGlobalExtMask(base, mask);
345  }
346  else {
347  /* Should not get here */
348  }
349 
350  FLEXCAN_ExitFreezeMode(base);
351 }
352 
353 /*FUNCTION**********************************************************************
354  *
355  * Function Name : FLEXCAN_DRV_SetRxMb14Mask
356  * Description : Set Rx Message Buffer 14 mask as the 11-bit standard mask
357  * or the 29-bit extended mask.
358  *
359  * Implements : FLEXCAN_DRV_SetRxMb14Mask_Activity
360  *END**************************************************************************/
362  uint8_t instance,
364  uint32_t mask)
365 {
366  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
367 
368  CAN_Type * base = g_flexcanBase[instance];
369 
370  FLEXCAN_EnterFreezeMode(base);
371 
372  if (id_type == FLEXCAN_MSG_ID_STD)
373  {
374  /* Set standard global mask for RX MB*/
375  FLEXCAN_SetRxMsgBuff14StdMask(base, mask);
376  }
377  else if (id_type == FLEXCAN_MSG_ID_EXT)
378  {
379  /* Set extended global mask for RX MB*/
380  FLEXCAN_SetRxMsgBuff14ExtMask(base, mask);
381  }
382  else {
383  /* Should not get here */
384  }
385 
386  FLEXCAN_ExitFreezeMode(base);
387 }
388 
389 /*FUNCTION**********************************************************************
390  *
391  * Function Name : FLEXCAN_DRV_SetRxMb15Mask
392  * Description : Set Rx Message Buffer 15 mask as the 11-bit standard mask
393  * or the 29-bit extended mask.
394  *
395  * Implements : FLEXCAN_DRV_SetRxMb15Mask_Activity
396  *END**************************************************************************/
398  uint8_t instance,
400  uint32_t mask)
401 {
402  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
403 
404  CAN_Type * base = g_flexcanBase[instance];
405 
406  FLEXCAN_EnterFreezeMode(base);
407 
408  if (id_type == FLEXCAN_MSG_ID_STD)
409  {
410  /* Set standard global mask for RX MB*/
411  FLEXCAN_SetRxMsgBuff15StdMask(base, mask);
412  }
413  else if (id_type == FLEXCAN_MSG_ID_EXT)
414  {
415  /* Set extended global mask for RX MB*/
416  FLEXCAN_SetRxMsgBuff15ExtMask(base, mask);
417  }
418  else {
419  /* Should not get here */
420  }
421 
422  FLEXCAN_ExitFreezeMode(base);
423 }
424 
425 /*FUNCTION**********************************************************************
426  *
427  * Function Name : FLEXCAN_DRV_SetRxIndividualMask
428  * Description : Set Rx individual mask as the 11-bit standard mask or the
429  * 29-bit extended mask.
430  *
431  * Implements : FLEXCAN_DRV_SetRxIndividualMask_Activity
432  *END**************************************************************************/
434  uint8_t instance,
436  uint8_t mb_idx,
437  uint32_t mask)
438 {
439  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
440 
441  CAN_Type * base = g_flexcanBase[instance];
442 
443  FLEXCAN_EnterFreezeMode(base);
444 
445  if (mb_idx > FLEXCAN_GetMaxMsgBuffNum(base))
446  {
447  FLEXCAN_ExitFreezeMode(base);
449  }
450 
451  if (id_type == FLEXCAN_MSG_ID_STD)
452  {
453  /* Set standard individual mask*/
454  FLEXCAN_SetRxIndividualStdMask(base, mb_idx, mask);
455  }
456  else if (id_type == FLEXCAN_MSG_ID_EXT)
457  {
458  /* Set extended individual mask*/
459  FLEXCAN_SetRxIndividualExtMask(base, mb_idx, mask);
460  }
461  else {
462  /* Should not get here */
463  }
464 
465  FLEXCAN_ExitFreezeMode(base);
466 
467  return STATUS_SUCCESS;
468 }
469 
470 /*FUNCTION**********************************************************************
471  *
472  * Function Name : FLEXCAN_DRV_Init
473  * Description : Initialize FlexCAN driver.
474  * This function will select a source clock, reset FlexCAN module, set maximum
475  * number of message buffers, initialize all message buffers as inactive, enable
476  * RX FIFO if needed, mask all mask bits, disable all MB interrupts, enable
477  * FlexCAN normal mode, and enable all the error interrupts if needed.
478  *
479  * Implements : FLEXCAN_DRV_Init_Activity
480  *END**************************************************************************/
482  uint8_t instance,
483  flexcan_state_t *state,
484  const flexcan_user_config_t *data)
485 {
486  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
487  DEV_ASSERT(state != NULL);
488 #ifdef ERRATA_E10595
489  if (instance != 0U)
490  {
491  DEV_ASSERT((MC_ME->GS & MC_ME_GS_S_FXOSC_MASK) != 0U);
492  }
493 #endif
494 
495  status_t result;
496  CAN_Type * base = g_flexcanBase[instance];
497  flexcan_time_segment_t bitrate;
498  status_t osifStat;
499  uint32_t i, j;
500  /* To enter Disable Mode requires FreezMode first */
501  FLEXCAN_EnterFreezeMode(base);
502  FLEXCAN_Disable(base);
503 
504 #if FEATURE_CAN_HAS_PE_CLKSRC_SELECT
505  /* Select a source clock for the FlexCAN engine */
506  FLEXCAN_SelectClock(base, data->pe_clock);
507 #endif
508 
509  /* Enable the CAN clock */
510  FLEXCAN_Enable(base);
511 
512  FLEXCAN_EnterFreezeMode(base);
513 
514  /* Initialize FLEXCAN device */
515  FLEXCAN_Init(base);
516 
517 #ifdef ERRATA_E10368
518 #if FEATURE_CAN_HAS_FD
519  if (data->fd_enable)
520  {
521  flexcan_msgbuff_code_status_t messageBuff={
522  .code = FLEXCAN_TX_REMOTE,
523  .msgIdType = FLEXCAN_MSG_ID_STD,
524  .dataLen = 1U,
525  .fd_enable = false,
526  .fd_padding = 0U,
527  .enable_brs = false
528  };
529  uint8_t dummy_data[16];
530  /* Enable Self Reception */
531  FLEXCAN_SetSelfReception(base, true);
532 
533  /* Select Loopback mode */
534  FLEXCAN_SetOperationMode(base, FLEXCAN_LOOPBACK_MODE);
535  /* Dummy transmission on MB0 */
536  (void)FLEXCAN_SetTxMsgBuff(base, 0U, &messageBuff, 0x1U, dummy_data);
537  FLEXCAN_SetFDEnabled(base, true);
538  bitrate = data->bitrate;
539  FLEXCAN_SetExtendedTimeSegments(base, &bitrate);
540  bitrate = data->bitrate_cbt;
541  FLEXCAN_SetFDTimeSegments(base, &bitrate);
542  FLEXCAN_ExitFreezeMode(base);
543  /* Wait transmission of MB0 to complete */
544  while((base->IFLAG1 & 0x1U) != 0x1U) {};
545  /* Clear Transmission Complete */
546  base->IFLAG1 = base->IFLAG1 | 0x1U;
547  FLEXCAN_EnterFreezeMode(base);
548  }
549 #endif /* FEATURE_CAN_HAS_FD */
550 #endif /* ERRATA_E10368 */
551 
552 #if FEATURE_CAN_HAS_FD
553  /* Enable/Disable FD and check FD was set as expected. Setting FD as enabled
554  * might fail if the current CAN instance does not support FD. */
555  FLEXCAN_SetFDEnabled(base, data->fd_enable);
556  if (FLEXCAN_IsFDEnabled(base) != data->fd_enable)
557  {
558  return STATUS_ERROR;
559  }
560 
561  /* If the FD feature is enabled, enable the Stuff Bit Count, in order to be
562  * ISO-compliant. */
563  FLEXCAN_SetStuffBitCount(base, data->fd_enable);
564 #endif
565 
566  /* Disable the self reception feature if FlexCAN is not in loopback mode. */
567  if (data->flexcanMode != FLEXCAN_LOOPBACK_MODE)
568  {
569  FLEXCAN_SetSelfReception(base, false);
570  }
571 
572  /* Enable RxFIFO feature, if requested. This might fail if the FD mode is
573  * enabled. */
574  if (data->is_rx_fifo_needed)
575  {
576  result = FLEXCAN_EnableRxFifo(base, (uint32_t)data->num_id_filters);
577  if (result != STATUS_SUCCESS)
578  {
579  return result;
580  }
581  }
582 
583 #if FEATURE_CAN_HAS_DMA_ENABLE
584  /* Enable DMA support for RxFIFO transfer, if requested. */
586  {
587  if (FLEXCAN_IsRxFifoEnabled(base))
588  {
589  FLEXCAN_SetRxFifoDMA(base, true);
590  }
591  else
592  {
593  return STATUS_ERROR;
594  }
595  }
596 #endif
597 
598  /* Select mode */
599  FLEXCAN_SetOperationMode(base, data->flexcanMode);
600 
601 #if FEATURE_CAN_HAS_FD
602  /* Set payload size. */
603  FLEXCAN_SetPayloadSize(base, data->payload);
604 #endif
605 
606  result = FLEXCAN_SetMaxMsgBuffNum(base, data->max_num_mb);
607  if (result != STATUS_SUCCESS)
608  {
609  return result;
610  }
611 
612 #if FEATURE_CAN_HAS_FD
613  /* Set bit rate. */
614  if (FLEXCAN_IsFDEnabled(base))
615  {
616  bitrate = data->bitrate;
617  FLEXCAN_SetExtendedTimeSegments(base, &bitrate);
618  bitrate = data->bitrate_cbt;
619  FLEXCAN_SetFDTimeSegments(base, &bitrate);
620  }
621  else
622 #endif
623  {
624  bitrate = data->bitrate;
625  FLEXCAN_SetTimeSegments(base, &bitrate);
626  }
627 
628  FLEXCAN_ExitFreezeMode(base);
629 
630  /* Enable FlexCAN interrupts.*/
631 #if FEATURE_CAN_HAS_WAKE_UP_IRQ
632  if (g_flexcanWakeUpIrqId[instance] != NotAvail_IRQn)
633  {
635  }
636 #endif
639  for (i = 0; i < FEATURE_CAN_MB_IRQS_MAX_COUNT; i++)
640  {
642  {
644  }
645  }
646 
647  for (i = 0; i < FEATURE_CAN_MAX_MB_NUM; i++)
648  {
649  osifStat = OSIF_SemaCreate(&state->mbs[i].mbSema, 0U);
650  if (osifStat != STATUS_SUCCESS)
651  {
652  for (j = 0; j < i; j++)
653  {
654  (void)OSIF_SemaDestroy(&state->mbs[j].mbSema);
655  }
656  return STATUS_ERROR;
657  }
658  state->mbs[i].isBlocking = false;
659  state->mbs[i].mb_message = NULL;
660  state->mbs[i].state = FLEXCAN_MB_IDLE;
661  }
662 
663  /* Store transfer type and DMA channel number used in transfer */
664  state->transferType = data->transfer_type;
665 #if FEATURE_CAN_HAS_DMA_ENABLE
666  state->rxFifoDMAChannel = data->rxFifoDMAChannel;
667 #endif
668 
669  /* Save runtime structure pointers so irq handler can point to the correct state structure */
670  g_flexcanStatePtr[instance] = state;
671 
672  return (STATUS_SUCCESS);
673 }
674 
675 /*FUNCTION**********************************************************************
676  *
677  * Function Name : FLEXCAN_DRV_ConfigTxMb
678  * Description : Configure a Tx message buffer.
679  * This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
680  * the function will make sure if the MB requested is not occupied by RX FIFO
681  * and ID filter table. Then this function will set up the message buffer fields,
682  * configure the message buffer code for Tx buffer as INACTIVE, and enable the
683  * Message Buffer interrupt.
684  *
685  * Implements : FLEXCAN_DRV_ConfigTxMb_Activity
686  *END**************************************************************************/
688  uint8_t instance,
689  uint8_t mb_idx,
690  const flexcan_data_info_t *tx_info,
691  uint32_t msg_id)
692 {
693  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
694  DEV_ASSERT(tx_info != NULL);
695 
696  flexcan_msgbuff_code_status_t cs;
697  CAN_Type * base = g_flexcanBase[instance];
698 
699  /* Initialize transmit mb*/
700  cs.dataLen = tx_info->data_length;
701  cs.msgIdType = tx_info->msg_id_type;
702  if (tx_info->is_remote)
703  {
704  cs.code = (uint32_t)FLEXCAN_TX_REMOTE;
705  }
706  else
707  {
708  cs.code = (uint32_t)FLEXCAN_TX_INACTIVE;
709  }
710  return FLEXCAN_SetTxMsgBuff(base, mb_idx, &cs, msg_id, NULL);
711 }
712 
713 /*FUNCTION**********************************************************************
714  *
715  * Function Name : FLEXCAN_DRV_ConfigRemoteResponseMb
716  * Description : Configures a transmit message buffer for remote frame
717  * response. This function will first check if RX FIFO is enabled. If RX FIFO is
718  * enabled, the function will make sure if the MB requested is not occupied by
719  * the RX FIFO and ID filter table. Then this function will set up the message
720  * buffer fields, configure the message buffer code for Tx buffer as RX_RANSWER,
721  * and enable the Message Buffer interrupt.
722  *
723  * Implements : FLEXCAN_DRV_ConfigRemoteResponseMb_Activity
724  *END**************************************************************************/
726  uint8_t instance,
727  uint8_t mb_idx,
728  const flexcan_data_info_t *tx_info,
729  uint32_t msg_id,
730  const uint8_t *mb_data)
731 {
732  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
733  DEV_ASSERT(tx_info != NULL);
734 
735  flexcan_msgbuff_code_status_t cs;
736  CAN_Type * base = g_flexcanBase[instance];
737 
738  /* Initialize transmit mb*/
739  cs.dataLen = tx_info->data_length;
740  cs.msgIdType = tx_info->msg_id_type;
741  cs.code = (uint32_t)FLEXCAN_RX_RANSWER;
742 
743  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
744 
745  return FLEXCAN_SetTxMsgBuff(base, mb_idx, &cs, msg_id, mb_data);
746 }
747 
748 /*FUNCTION**********************************************************************
749  *
750  * Function Name : FLEXCAN_DRV_SendBlocking
751  * Description : This function sends a CAN frame using a configured message
752  * buffer. The function blocks until either the frame was sent, or the specified
753  * timeout expired.
754  *
755  * Implements : FLEXCAN_DRV_SendBlocking_Activity
756  *END**************************************************************************/
758  uint8_t instance,
759  uint8_t mb_idx,
760  const flexcan_data_info_t *tx_info,
761  uint32_t msg_id,
762  const uint8_t *mb_data,
763  uint32_t timeout_ms)
764 {
765  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
766  DEV_ASSERT(tx_info != NULL);
767 
768  status_t result;
769  flexcan_state_t * state = g_flexcanStatePtr[instance];
770  CAN_Type * base = g_flexcanBase[instance];
771 
772  result = FLEXCAN_StartSendData(instance, mb_idx, tx_info, msg_id, mb_data, true);
773 
774  if (result == STATUS_SUCCESS)
775  {
776  status_t status;
777 
778  /* Enable message buffer interrupt*/
779  (void)FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, true);
780 
781  status = OSIF_SemaWait(&state->mbs[mb_idx].mbSema, timeout_ms);
782 
783  if (status == STATUS_TIMEOUT)
784  {
785  /* If the flag is set Successful transmission else report TimeOut */
786  if (FLEXCAN_GetMsgBuffIntStatusFlag(base,mb_idx) == (uint8_t)0U)
787  {
788  result = STATUS_TIMEOUT;
789  }
790  /* Disable message buffer interrupt */
791  (void)FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, false);
792  }
793 
794  state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
795  }
796 
797  return result;
798 }
799 
800 /*FUNCTION**********************************************************************
801  *
802  * Function Name : FLEXCAN_DRV_Send
803  * Description : This function sends a CAN frame using a configured message
804  * buffer. The function returns immediately. If a callback is installed, it will
805  * be invoked after the frame was sent.
806  *
807  * Implements : FLEXCAN_DRV_Send_Activity
808  *END**************************************************************************/
810  uint8_t instance,
811  uint8_t mb_idx,
812  const flexcan_data_info_t *tx_info,
813  uint32_t msg_id,
814  const uint8_t *mb_data)
815 {
816  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
817  DEV_ASSERT(tx_info != NULL);
818 
819  status_t result;
820  CAN_Type * base = g_flexcanBase[instance];
821 
822  result = FLEXCAN_StartSendData(instance, mb_idx, tx_info, msg_id, mb_data, false);
823  if(result == STATUS_SUCCESS)
824  {
825  /* Enable message buffer interrupt*/
826  result = FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, true);
827  }
828 
829  return result;
830 }
831 
832 /*FUNCTION**********************************************************************
833  *
834  * Function Name : FLEXCAN_DRV_ConfigMb
835  * Description : Configure a Rx message buffer.
836  * This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
837  * the function will make sure if the MB requested is not occupied by RX FIFO
838  * and ID filter table. Then this function will set up the message buffer fields,
839  * configure the message buffer code for Rx message buffer as NOT_USED, enable
840  * the Message Buffer interrupt, configure the message buffer code for Rx
841  * message buffer as INACTIVE, copy user's buffer into the message buffer data
842  * area, and configure the message buffer code for Rx message buffer as EMPTY.
843  *
844  * Implements : FLEXCAN_DRV_ConfigRxMb_Activity
845  *END**************************************************************************/
847  uint8_t instance,
848  uint8_t mb_idx,
849  const flexcan_data_info_t *rx_info,
850  uint32_t msg_id)
851 {
852  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
853  DEV_ASSERT(rx_info != NULL);
854 
855  status_t result;
856  flexcan_msgbuff_code_status_t cs;
857  CAN_Type * base = g_flexcanBase[instance];
858 
859  cs.dataLen = rx_info->data_length;
860  cs.msgIdType = rx_info->msg_id_type;
861 #if FEATURE_CAN_HAS_FD
862  cs.fd_enable = rx_info->fd_enable;
863 #endif
864  /* Initialize rx mb*/
865  cs.code = (uint32_t)FLEXCAN_RX_NOT_USED;
866  result = FLEXCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
867  if (result != STATUS_SUCCESS)
868  {
869  return result;
870  }
871 
872  /* Initialize receive MB*/
873  cs.code = (uint32_t)FLEXCAN_RX_INACTIVE;
874  result = FLEXCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
875  if (result != STATUS_SUCCESS)
876  {
877  return result;
878  }
879 
880  /* Set up FlexCAN message buffer fields for receiving data*/
881  cs.code = (uint32_t)FLEXCAN_RX_EMPTY;
882  return FLEXCAN_SetRxMsgBuff(base, mb_idx, &cs, msg_id);
883 }
884 
885 /*FUNCTION**********************************************************************
886  *
887  * Function Name : FLEXCAN_DRV_ConfigRxFifo
888  * Description : Confgure RX FIFO ID filter table elements.
889  * This function will confgure RX FIFO ID filter table elements, and enable RX
890  * FIFO interrupts.
891  *
892  * Implements : FLEXCAN_DRV_ConfigRxFifo_Activity
893  *END**************************************************************************/
895  uint8_t instance,
897  const flexcan_id_table_t *id_filter_table)
898 {
899  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
900 
901  CAN_Type * base = g_flexcanBase[instance];
902 
903  FLEXCAN_EnterFreezeMode(base);
904 
905  /* Initialize rx fifo*/
906  FLEXCAN_SetRxFifoFilter(base, id_format, id_filter_table);
907 
908  FLEXCAN_ExitFreezeMode(base);
909 }
910 
911 /*FUNCTION**********************************************************************
912  *
913  * Function Name : FLEXCAN_DRV_ReceiveBlocking
914  * Description : This function receives a CAN frame into a configured message
915  * buffer. The function blocks until either a frame was received, or the
916  * specified timeout expired.
917  *
918  * Implements : FLEXCAN_DRV_ReceiveBlocking_Activity
919  *END**************************************************************************/
921  uint8_t instance,
922  uint8_t mb_idx,
923  flexcan_msgbuff_t *data,
924  uint32_t timeout_ms)
925 {
926  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
927 
928  status_t result;
929  flexcan_state_t * state = g_flexcanStatePtr[instance];
930  CAN_Type * base = g_flexcanBase[instance];
931 
932  result = FLEXCAN_StartRxMessageBufferData(instance, mb_idx, data, true);
933 
934  if(result == STATUS_SUCCESS)
935  {
936  status_t status;
937 
938  status = OSIF_SemaWait(&state->mbs[mb_idx].mbSema, timeout_ms);
939 
940  if (status == STATUS_TIMEOUT)
941  {
942  /* If the flag is set Successful reception else report TimeOut */
943  if(FLEXCAN_GetMsgBuffIntStatusFlag(base,mb_idx) == (uint8_t)0U)
944  {
945  result = STATUS_TIMEOUT;
946  }
947  /* Disable message buffer interrupt */
948  (void)FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, false);
949  }
950 
951  state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
952  }
953 
954  return result;
955 }
956 
957 /*FUNCTION**********************************************************************
958  *
959  * Function Name : FLEXCAN_DRV_Receive
960  * Description : This function receives a CAN frame into a configured message
961  * buffer. The function returns immediately. If a callback is installed, it will
962  * be invoked after the frame was received and read into the specified buffer.
963  *
964  * Implements : FLEXCAN_DRV_Receive_Activity
965  *END**************************************************************************/
967  uint8_t instance,
968  uint8_t mb_idx,
969  flexcan_msgbuff_t *data)
970 {
971  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
972 
973  status_t result;
974 
975  result = FLEXCAN_StartRxMessageBufferData(instance, mb_idx, data, false);
976 
977  return result;
978 }
979 
980 /*FUNCTION**********************************************************************
981  *
982  * Function Name : FLEXCAN_DRV_RxFifoBlocking
983  * Description : This function receives a CAN frame using the Rx FIFO. The
984  * function blocks until either a frame was received, or the specified timeout
985  * expired.
986  *
987  * Implements : FLEXCAN_DRV_RxFifoBlocking_Activity
988  *END**************************************************************************/
990  uint8_t instance,
991  flexcan_msgbuff_t *data,
992  uint32_t timeout_ms)
993 {
994  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
995 
996  status_t result;
997  flexcan_state_t * state = g_flexcanStatePtr[instance];
998  CAN_Type * base = g_flexcanBase[instance];
999 
1000  result = FLEXCAN_StartRxMessageFifoData(instance, data, true);
1001 
1002  if (result == STATUS_SUCCESS)
1003  {
1004  result = OSIF_SemaWait(&state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mbSema, timeout_ms);
1005 
1006  if (result == STATUS_TIMEOUT)
1007  {
1008  /* If the flag is set Successful reception else report TimeOut */
1009  if (FLEXCAN_GetMsgBuffIntStatusFlag(base,FEATURE_CAN_RXFIFO_FRAME_AVAILABLE) == (uint8_t)0U)
1010  {
1011  result = STATUS_TIMEOUT;
1012  }
1013  /* Disable RX FIFO interrupts*/
1014  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_FRAME_AVAILABLE, false);
1015  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_WARNING, false);
1016  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_OVERFLOW, false);
1017  }
1018 
1020  }
1021 
1022  return result;
1023 }
1024 
1025 /*FUNCTION**********************************************************************
1026  *
1027  * Function Name : FLEXCAN_DRV_RxFifo
1028  * Description : This function receives a CAN frame using the Rx FIFO. The
1029  * function returns immediately. If a callback is installed, it will be invoked
1030  * after the frame was received and read into the specified buffer.
1031  *
1032  * Implements : FLEXCAN_DRV_RxFifo_Activity
1033  *END**************************************************************************/
1035  uint8_t instance,
1036  flexcan_msgbuff_t *data)
1037 {
1038  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1039 
1040  status_t result;
1041 
1042  result = FLEXCAN_StartRxMessageFifoData(instance, data, false);
1043 
1044  return result;
1045 }
1046 
1047 /*FUNCTION**********************************************************************
1048  *
1049  * Function Name : FLEXCAN_DRV_Deinit
1050  * Description : Shutdown a FlexCAN module.
1051  * This function will disable all FlexCAN interrupts, and disable the FlexCAN.
1052  *
1053  * Implements : FLEXCAN_DRV_Deinit_Activity
1054  *END**************************************************************************/
1055 status_t FLEXCAN_DRV_Deinit(uint8_t instance)
1056 {
1057  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1058 
1059  CAN_Type * base = g_flexcanBase[instance];
1060  const flexcan_state_t * state = g_flexcanStatePtr[instance];
1061  status_t result = STATUS_SUCCESS;
1062  status_t osifStat;
1063  uint32_t i;
1064 
1065  /* Disable FlexCAN interrupts.*/
1066  if (state->error_callback != NULL)
1067  {
1068  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_ERR, false);
1069  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_RX_WARNING, false);
1070  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_TX_WARNING, false);
1071  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_BUSOFF, false);
1072  }
1073 
1074 #if FEATURE_CAN_HAS_WAKE_UP_IRQ
1075  if (g_flexcanWakeUpIrqId[instance] != NotAvail_IRQn)
1076  {
1078  }
1079 #endif
1082  for (i = 0; i < FEATURE_CAN_MB_IRQS_MAX_COUNT; i++)
1083  {
1084  if (g_flexcanOredMessageBufferIrqId[i][instance] != NotAvail_IRQn)
1085  {
1087  }
1088  }
1089  /* Enter Freeze Mode Required before to enter Disabled Mode */
1090  FLEXCAN_EnterFreezeMode(g_flexcanBase[instance]);
1091  /* Disable FlexCAN.*/
1092  FLEXCAN_Disable(g_flexcanBase[instance]);
1093 
1094  for (i = 0; i < FEATURE_CAN_MAX_MB_NUM; i++)
1095  {
1096  osifStat = OSIF_SemaDestroy(&state->mbs[i].mbSema);
1097  if (osifStat != STATUS_SUCCESS)
1098  {
1099  result = STATUS_ERROR;
1100  }
1101  }
1102 
1103  return result;
1104 }
1105 
1106 #if FEATURE_CAN_HAS_FD
1107 /*FUNCTION**********************************************************************
1108  *
1109  * Function Name : FLEXCAN_DRV_SetTDCOffset
1110  * Description : Enables/Disables the Transceiver Delay Compensation feature and sets
1111  * the Transceiver Delay Compensation Offset.
1112  *
1113  * Implements : FLEXCAN_DRV_SetTDCOffset_Activity
1114  *END**************************************************************************/
1115 void FLEXCAN_DRV_SetTDCOffset(uint8_t instance, bool enable, uint8_t offset)
1116 {
1117  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1118 
1119  CAN_Type * base = g_flexcanBase[instance];
1120 
1121  FLEXCAN_EnterFreezeMode(base);
1122 
1123  /* Enable/Disable TDC and set the TDC Offset */
1124  FLEXCAN_SetTDCOffset(base, enable, offset);
1125 
1126  FLEXCAN_ExitFreezeMode(base);
1127 }
1128 
1129 /*FUNCTION**********************************************************************
1130  *
1131  * Function Name : FLEXCAN_DRV_GetTDCValue
1132  * Description : Gets the value of the Transceiver Delay Compensation.
1133  *
1134  * Implements : FLEXCAN_DRV_GetTDCValue_Activity
1135  *END**************************************************************************/
1136 uint8_t FLEXCAN_DRV_GetTDCValue(uint8_t instance)
1137 {
1138  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1139 
1140  const CAN_Type * base = g_flexcanBase[instance];
1141 
1142  return (uint8_t)((base->FDCTRL & CAN_FDCTRL_TDCVAL_MASK) >> CAN_FDCTRL_TDCVAL_SHIFT);
1143 }
1144 
1145 /*FUNCTION**********************************************************************
1146  *
1147  * Function Name : FLEXCAN_DRV_GetTDCFail
1148  * Description : Gets the value of the TDC Fail flag.
1149  *
1150  * Implements : FLEXCAN_DRV_GetTDCFail_Activity
1151  *END**************************************************************************/
1152 bool FLEXCAN_DRV_GetTDCFail(uint8_t instance)
1153 {
1154  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1155 
1156  const CAN_Type * base = g_flexcanBase[instance];
1157 
1158  return (((base->FDCTRL & CAN_FDCTRL_TDCFAIL_MASK) >> CAN_FDCTRL_TDCFAIL_SHIFT) != 0U);
1159 }
1160 
1161 /*FUNCTION**********************************************************************
1162  *
1163  * Function Name : FLEXCAN_DRV_ClearTDCFail
1164  * Description : Clears the TDC Fail flag.
1165  *
1166  * Implements : FLEXCAN_DRV_ClearTDCFail_Activity
1167  *END**************************************************************************/
1168 void FLEXCAN_DRV_ClearTDCFail(uint8_t instance)
1169 {
1170  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1171 
1172  CAN_Type * base = g_flexcanBase[instance];
1173 
1174  base->FDCTRL = base->FDCTRL | CAN_FDCTRL_TDCFAIL_MASK;
1175 }
1176 #endif
1177 
1178 /*FUNCTION**********************************************************************
1179  *
1180  * Function Name : FLEXCAN_IRQHandler
1181  * Description : Interrupt handler for FLEXCAN.
1182  * This handler read data from MB or FIFO, and then clear the interrupt flags.
1183  * This is not a public API as it is called whenever an interrupt occurs.
1184  *
1185  *END**************************************************************************/
1186 void FLEXCAN_IRQHandler(uint8_t instance)
1187 {
1188  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1189 
1190  uint32_t flag_reg = 0;
1191  CAN_Type * base = g_flexcanBase[instance];
1192  flexcan_state_t * state = g_flexcanStatePtr[instance];
1193  status_t result = STATUS_SUCCESS;
1194 
1195  /* Get the interrupts that are enabled and ready */
1196  uint32_t mb_idx = 0;
1197  flag_reg = FLEXCAN_GetMsgBuffIntStatusFlag(base, mb_idx);
1198 
1199  while ((flag_reg & 1U) == 0U)
1200  {
1201  mb_idx++;
1202  flag_reg = FLEXCAN_GetMsgBuffIntStatusFlag(base, mb_idx);
1203 
1204  if (mb_idx > FEATURE_CAN_MAX_MB_NUM)
1205  {
1206  break;
1207  }
1208  }
1209 
1210  /* Check Tx/Rx interrupt flag and clear the interrupt */
1211  if(flag_reg != 0U)
1212  {
1213  bool rxfifoEnabled = FLEXCAN_IsRxFifoEnabled(base);
1214 
1215  if ((mb_idx == FEATURE_CAN_RXFIFO_FRAME_AVAILABLE) && rxfifoEnabled)
1216  {
1218  {
1219  /* Get RX FIFO field values */
1220  FLEXCAN_ReadRxFifo(base, state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mb_message);
1221 
1222  /* Complete receive data */
1224  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1225 
1226  /* Invoke callback */
1227  if (state->callback != NULL)
1228  {
1229  state->callback(instance,
1232  state);
1233  }
1234  }
1235  }
1236  else if ((mb_idx == FEATURE_CAN_RXFIFO_WARNING) && rxfifoEnabled)
1237  {
1238  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1239 
1240  /* Invoke callback */
1241  if (state->callback != NULL)
1242  {
1243  state->callback(instance,
1246  state);
1247  }
1248  }
1249  else if ((mb_idx == FEATURE_CAN_RXFIFO_OVERFLOW) && rxfifoEnabled)
1250  {
1251  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1252 
1253  /* Invoke callback */
1254  if (state->callback != NULL)
1255  {
1256  state->callback(instance,
1259  state);
1260  }
1261  }
1262  else
1263  {
1264  /* Check mailbox completed reception */
1265  if (state->mbs[mb_idx].state == FLEXCAN_MB_RX_BUSY)
1266  {
1267  /* Lock RX message buffer and RX FIFO*/
1268  result = FLEXCAN_LockRxMsgBuff(base, mb_idx);
1269  if (result == STATUS_SUCCESS)
1270  {
1271  /* Get RX MB field values*/
1272  result = FLEXCAN_GetMsgBuff(base, mb_idx, state->mbs[mb_idx].mb_message);
1273  }
1274  if (result == STATUS_SUCCESS)
1275  {
1276  /* Unlock RX message buffer and RX FIFO*/
1277  FLEXCAN_UnlockRxMsgBuff(base);
1278 
1279  /* Complete receive data */
1280  FLEXCAN_CompleteTransfer(instance, mb_idx);
1281  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1282 
1283  /* Invoke callback */
1284  if (state->callback != NULL)
1285  {
1286  state->callback(instance, FLEXCAN_EVENT_RX_COMPLETE, mb_idx, state);
1287  }
1288  }
1289  }
1290  }
1291 
1292  /* Check mailbox completed transmission */
1293  if (state->mbs[mb_idx].state == FLEXCAN_MB_TX_BUSY)
1294  {
1295  /* Complete transmit data */
1296  FLEXCAN_CompleteTransfer(instance, mb_idx);
1297 
1298  if (state->mbs[mb_idx].isRemote)
1299  {
1300  /* If the frame was a remote frame, clear the flag only if the response was
1301  * not received yet. If the response was received, leave the flag set in order
1302  * to be handled when the user calls FLEXCAN_DRV_RxMessageBuffer. */
1303  flexcan_msgbuff_t mb;
1304  (void) FLEXCAN_LockRxMsgBuff(base, mb_idx);
1305  (void) FLEXCAN_GetMsgBuff(base, mb_idx, &mb);
1306  FLEXCAN_UnlockRxMsgBuff(base);
1307 
1308  if (((mb.cs & CAN_CS_CODE_MASK) >> CAN_CS_CODE_SHIFT) == (uint32_t)FLEXCAN_RX_EMPTY)
1309  {
1310  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1311  }
1312  }
1313  else
1314  {
1315  FLEXCAN_ClearMsgBuffIntStatusFlag(base, mb_idx);
1316  }
1317 
1318  /* Invoke callback */
1319  if (state->callback != NULL)
1320  {
1321  state->callback(instance, FLEXCAN_EVENT_TX_COMPLETE, mb_idx, state);
1322  }
1323  }
1324  }
1325  else
1326  {
1327 #if FEATURE_CAN_HAS_PRETENDED_NETWORKING
1328  uint8_t wtof = FLEXCAN_GetWTOF(base);
1329  uint8_t wumf = FLEXCAN_GetWUMF(base);
1330 
1331  /* Check if wake-up event occurred */
1332  if ((wtof != 0U) || (wumf != 0U))
1333  {
1334  FLEXCAN_WakeUpHandler(instance);
1335  }
1336 #endif
1337  uint32_t ecr = FLEXCAN_GetErrorCounters(base);
1338 
1339  /* Check if any error occurred */
1340  if (ecr != 0U)
1341  {
1342  FLEXCAN_Error_IRQHandler(instance);
1343  }
1344  }
1345 
1346  return;
1347 }
1348 
1349 /*FUNCTION**********************************************************************
1350  *
1351  * Function Name : FLEXCAN_Error_IRQHandler
1352  * Description : Error interrupt handler for FLEXCAN.
1353  * This handler read data from MB or FIFO, and then clear the interrupt flags.
1354  * This is not a public API as it is called whenever an interrupt occurs.
1355  *
1356  *END**************************************************************************/
1357 void FLEXCAN_Error_IRQHandler(uint8_t instance)
1358 {
1359  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1360 
1361  CAN_Type * base = g_flexcanBase[instance];
1362  flexcan_state_t * state = g_flexcanStatePtr[instance];
1363 
1364  /* Invoke callback */
1365  if (state->error_callback != NULL)
1366  {
1367  state->error_callback(instance, FLEXCAN_EVENT_ERROR, state);
1368  }
1369 
1370  /* Clear all other interrupts in ESR1 register (Error, Busoff, Wakeup) */
1371  FLEXCAN_ClearErrIntStatusFlag(base);
1372 
1373  return;
1374 }
1375 
1376 #if FEATURE_CAN_HAS_WAKE_UP_IRQ
1377 
1378 /*FUNCTION**********************************************************************
1379  *
1380  * Function Name : FLEXCAN_WakeUpHandler
1381  * Description : Wake up handler for FLEXCAN.
1382  * This handler verifies the event which caused the wake up and invokes the
1383  * user callback, if configured.
1384  * This is not a public API as it is called whenever an wake up event occurs.
1385  *
1386  *END**************************************************************************/
1387 void FLEXCAN_WakeUpHandler(uint8_t instance)
1388 {
1389  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1390 
1391  CAN_Type * base = g_flexcanBase[instance];
1392  flexcan_state_t * state = g_flexcanStatePtr[instance];
1393 
1394  /* Invoke callback */
1395  if (state->callback != NULL)
1396  {
1397 #if FEATURE_CAN_HAS_PRETENDED_NETWORKING
1398  if (FLEXCAN_IsPNEnabled(base))
1399  {
1400  if (FLEXCAN_GetWTOF(base) != 0U)
1401  {
1402  FLEXCAN_ClearWTOF(base);
1403  state->callback(instance, FLEXCAN_EVENT_WAKEUP_TIMEOUT, 0U, state);
1404  }
1405  if (FLEXCAN_GetWUMF(base) != 0U)
1406  {
1407  FLEXCAN_ClearWUMF(base);
1408  state->callback(instance, FLEXCAN_EVENT_WAKEUP_MATCH, 0U, state);
1409  }
1410  }
1411 #endif
1412 
1413 #if FEATURE_CAN_HAS_SELF_WAKE_UP
1414  if (FLEXCAN_IsSelfWakeUpEnabled(base))
1415  {
1416  if (FLEXCAN_GetWAKINT(base) != 0U)
1417  {
1418  FLEXCAN_ClearWAKINT(base);
1419  state->callback(instance, FLEXCAN_EVENT_SELF_WAKEUP, 0U, state);
1420  }
1421  }
1422 #endif
1423  }
1424 }
1425 #endif /* FEATURE_CAN_HAS_WAKE_UP_IRQ */
1426 
1427 /*FUNCTION**********************************************************************
1428  *
1429  * Function Name : FLEXCAN_DRV_GetTransferStatus
1430  * Description : This function returns whether the previous FLEXCAN receive is
1431  * completed.
1432  * When performing a non-blocking receive, the user can call this function to
1433  * ascertain the state of the current receive progress: in progress (or busy)
1434  * or complete (success).
1435  *
1436  * Implements : FLEXCAN_DRV_GetTransferStatus_Activity
1437  *END**************************************************************************/
1438 status_t FLEXCAN_DRV_GetTransferStatus(uint8_t instance, uint8_t mb_idx)
1439 {
1440  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1441 
1442  const flexcan_state_t * state = g_flexcanStatePtr[instance];
1443  status_t status;
1444 
1445  if (state->mbs[mb_idx].state == FLEXCAN_MB_IDLE)
1446  {
1447  status = STATUS_SUCCESS;
1448  }
1449  else
1450  {
1451  status = STATUS_BUSY;
1452  }
1453 
1454  return status;
1455 }
1456 
1457 /*FUNCTION**********************************************************************
1458  *
1459  * Function Name : FLEXCAN_DRV_GetErrorStatus
1460  * Description : Reports various error conditions detected in the reception and
1461  * transmission of a CAN frame and some general status of the device.
1462  *
1463  * Implements : FLEXCAN_DRV_GetErrorStatus_Activity
1464  *END**************************************************************************/
1465 uint32_t FLEXCAN_DRV_GetErrorStatus(uint8_t instance)
1466 {
1467  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1468 
1469  const CAN_Type * base = g_flexcanBase[instance];
1470 
1471  return ((uint32_t)(base->ESR1));
1472 }
1473 
1474 /*FUNCTION**********************************************************************
1475  *
1476  * Function Name : FLEXCAN_DRV_AbortTransfer
1477  * Description : This function shuts down the FLEXCAN by disabling interrupts and
1478  * the transmitter/receiver.
1479  * This function disables the FLEXCAN interrupts, disables the transmitter and
1480  * receiver.
1481  *
1482  * Implements : FLEXCAN_DRV_AbortTransfer_Activity
1483  *END**************************************************************************/
1484 status_t FLEXCAN_DRV_AbortTransfer(uint8_t instance, uint8_t mb_idx)
1485 {
1486  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1487 
1488  const flexcan_state_t * state = g_flexcanStatePtr[instance];
1489  CAN_Type * base = g_flexcanBase[instance];
1490 
1491  /* Check if a transfer is running. */
1492  if (state->mbs[mb_idx].state == FLEXCAN_MB_IDLE)
1493  {
1495  }
1496 
1497  if (state->mbs[mb_idx].state == FLEXCAN_MB_TX_BUSY)
1498  {
1499  FLEXCAN_AbortTxMsgBuff(base, mb_idx);
1500  }
1501 
1502  /* Stop the running transfer. */
1503  FLEXCAN_CompleteTransfer(instance, mb_idx);
1504 
1505  return STATUS_SUCCESS;
1506 }
1507 
1508 /*FUNCTION**********************************************************************
1509  *
1510  * Function Name : FLEXCAN_DRV_StartSendData
1511  * Description : Initiate (start) a transmit by beginning the process of
1512  * sending data.
1513  * This is not a public API as it is called from other driver functions.
1514  *
1515  *END**************************************************************************/
1517  uint8_t instance,
1518  uint8_t mb_idx,
1519  const flexcan_data_info_t *tx_info,
1520  uint32_t msg_id,
1521  const uint8_t *mb_data,
1522  bool isBlocking
1523  )
1524 {
1525  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1526  DEV_ASSERT(tx_info != NULL);
1527 
1528  status_t result;
1529  flexcan_msgbuff_code_status_t cs;
1530  flexcan_state_t * state = g_flexcanStatePtr[instance];
1531  CAN_Type * base = g_flexcanBase[instance];
1532 
1533  if (state->mbs[mb_idx].state != FLEXCAN_MB_IDLE)
1534  {
1535  return STATUS_BUSY;
1536  }
1537  state->mbs[mb_idx].state = FLEXCAN_MB_TX_BUSY;
1538  state->mbs[mb_idx].isBlocking = isBlocking;
1539  state->mbs[mb_idx].isRemote = tx_info->is_remote;
1540 
1541  cs.dataLen = tx_info->data_length;
1542  cs.msgIdType = tx_info->msg_id_type;
1543 
1544 #if FEATURE_CAN_HAS_FD
1545  cs.fd_enable = tx_info->fd_enable;
1546  cs.fd_padding = tx_info->fd_padding;
1547  cs.enable_brs = tx_info->enable_brs;
1548 #endif
1549 
1550  if (tx_info->is_remote)
1551  {
1552  cs.code = (uint32_t)FLEXCAN_TX_REMOTE;
1553  }
1554  else
1555  {
1556  cs.code = (uint32_t)FLEXCAN_TX_DATA;
1557  }
1558  result = FLEXCAN_SetTxMsgBuff(base, mb_idx, &cs, msg_id, mb_data);
1559 
1560  if (result != STATUS_SUCCESS)
1561  {
1562  state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
1563  }
1564 
1565  return result;
1566 }
1567 
1568 /*FUNCTION**********************************************************************
1569  *
1570  * Function Name : FLEXCAN_DRV_StartRxMessageBufferData
1571  * Description : Initiate (start) a receive by beginning the process of
1572  * receiving data and enabling the interrupt.
1573  * This is not a public API as it is called from other driver functions.
1574  *
1575  *END**************************************************************************/
1577  uint8_t instance,
1578  uint8_t mb_idx,
1579  flexcan_msgbuff_t *data,
1580  bool isBlocking
1581  )
1582 {
1583  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1584 
1585  status_t result = STATUS_SUCCESS;
1586  CAN_Type * base = g_flexcanBase[instance];
1587  flexcan_state_t * state = g_flexcanStatePtr[instance];
1588 
1589  /* Start receiving mailbox */
1590  if(state->mbs[mb_idx].state != FLEXCAN_MB_IDLE)
1591  {
1592  return STATUS_BUSY;
1593  }
1594  state->mbs[mb_idx].state = FLEXCAN_MB_RX_BUSY;
1595  state->mbs[mb_idx].mb_message = data;
1596  state->mbs[mb_idx].isBlocking = isBlocking;
1597 
1598  /* Enable MB interrupt*/
1599  result = FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, true);
1600 
1601  if (result != STATUS_SUCCESS)
1602  {
1603  state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
1604  }
1605 
1606  return result;
1607 }
1608 
1609 
1610 /*FUNCTION**********************************************************************
1611  *
1612  * Function Name : FLEXCAN_DRV_StartRxMessageFifoData
1613  * Description : Initiate (start) a receive by beginning the process of
1614  * receiving data and enabling the interrupt.
1615  * This is not a public API as it is called from other driver functions.
1616  *
1617  *END**************************************************************************/
1619  uint8_t instance,
1620  flexcan_msgbuff_t *data,
1621  bool isBlocking
1622  )
1623 {
1624  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1625 
1626  CAN_Type * base = g_flexcanBase[instance];
1627  flexcan_state_t * state = g_flexcanStatePtr[instance];
1628 #if FEATURE_CAN_HAS_DMA_ENABLE
1629  status_t edmaStat;
1630 #endif
1631 
1632  /* Start receiving fifo */
1634  {
1635  return STATUS_BUSY;
1636  }
1637  /* Check if RxFIFO feature is enabled */
1638  if (!FLEXCAN_IsRxFifoEnabled(base))
1639  {
1640  return STATUS_ERROR;
1641  }
1642 
1644 
1645  state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].isBlocking = isBlocking;
1646 
1647  /* This will get filled by the interrupt handler */
1648  state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mb_message = data;
1649 
1650 #if FEATURE_CAN_HAS_DMA_ENABLE
1651  if (state->transferType == FLEXCAN_RXFIFO_USING_DMA)
1652  {
1653  status_t edmaStatus;
1654 
1655  edmaStatus = EDMA_DRV_InstallCallback(state->rxFifoDMAChannel,
1657  (void *)((uint32_t)instance));
1658 
1659  if (edmaStatus != STATUS_SUCCESS)
1660  {
1662  return STATUS_ERROR;
1663  }
1664 
1667  (uint32_t)(base->RAMn),
1668  (uint32_t)(state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mb_message),
1670  16U);
1671 
1672  if (edmaStatus != STATUS_SUCCESS)
1673  {
1675  return STATUS_ERROR;
1676  }
1677 
1678  edmaStat = EDMA_DRV_StartChannel(state->rxFifoDMAChannel);
1679  if (edmaStat != STATUS_SUCCESS)
1680  {
1682  return STATUS_ERROR;
1683  }
1684  }
1685 #endif
1686 
1687  /* Enable RX FIFO interrupts*/
1688  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_FRAME_AVAILABLE, true);
1689  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_WARNING, true);
1690  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_OVERFLOW, true);
1691 
1692  return STATUS_SUCCESS;
1693 }
1694 
1695 /*FUNCTION**********************************************************************
1696  *
1697  * Function Name : FLEXCAN_DRV_CompleteTransfer
1698  * Description : Finish up a transmit by completing the process of sending
1699  * data and disabling the interrupt.
1700  * This is not a public API as it is called from other driver functions.
1701  *
1702  *END**************************************************************************/
1703 static void FLEXCAN_CompleteTransfer(uint8_t instance, uint32_t mb_idx)
1704 {
1705  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1706 
1707  CAN_Type * base = g_flexcanBase[instance];
1708  flexcan_state_t * state = g_flexcanStatePtr[instance];
1709 
1710  /* Disable the transmitter data register empty interrupt */
1711  (void)FLEXCAN_SetMsgBuffIntCmd(base, mb_idx, false);
1712 
1713  /* Update the information of the module driver state */
1714  if (state->mbs[mb_idx].isBlocking)
1715  {
1716  (void)OSIF_SemaPost(&state->mbs[mb_idx].mbSema);
1717  }
1718  state->mbs[mb_idx].state = FLEXCAN_MB_IDLE;
1719 }
1720 
1721 #if FEATURE_CAN_HAS_DMA_ENABLE
1722 /*FUNCTION**********************************************************************
1723  *
1724  * Function Name : FLEXCAN_DRV_CompleteRxFifoDataDMA
1725  * Description : Finish up a DMA transfer (this is just a wrapper over
1726  * FLEXCAN_DRV_CompleteRxMessageFifoData).
1727  * This is not a public API as it is called from other driver functions.
1728  *
1729  *END**************************************************************************/
1730 static void FLEXCAN_CompleteRxFifoDataDMA(void *parameter, edma_chn_status_t status)
1731 {
1732  uint32_t instance = (uint32_t)parameter;
1733  (void)status;
1734 
1735  FLEXCAN_CompleteRxMessageFifoData((uint8_t)instance);
1736 }
1737 #endif
1738 
1739 /*FUNCTION**********************************************************************
1740  *
1741  * Function Name : FLEXCAN_DRV_CompleteRxMessageFifoData
1742  * Description : Finish up a receive by completing the process of receiving
1743  * data and disabling the interrupt.
1744  * This is not a public API as it is called from other driver functions.
1745  *
1746  *END**************************************************************************/
1747 static void FLEXCAN_CompleteRxMessageFifoData(uint8_t instance)
1748 {
1749  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1750 
1751  CAN_Type * base = g_flexcanBase[instance];
1752  flexcan_state_t * state = g_flexcanStatePtr[instance];
1753 
1755  {
1756  /* Disable RX FIFO interrupts*/
1757  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_FRAME_AVAILABLE, false);
1758  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_WARNING, false);
1759  (void)FLEXCAN_SetMsgBuffIntCmd(base, FEATURE_CAN_RXFIFO_OVERFLOW, false);
1760  }
1761 #if FEATURE_CAN_HAS_DMA_ENABLE
1762  else
1763  {
1764  flexcan_msgbuff_t *fifo_message = state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mb_message;
1765  uint32_t *msgData_32 = (uint32_t *)fifo_message->data;
1766 
1767  (void) EDMA_DRV_StopChannel(state->rxFifoDMAChannel);
1768  /* Adjust the ID if it is not extended */
1769  if (((fifo_message->cs) & CAN_CS_IDE_MASK) == 0U)
1770  {
1771  fifo_message->msgId = fifo_message->msgId >> CAN_ID_STD_SHIFT;
1772  }
1773  /* Extract the data length */
1774  fifo_message->dataLen = (uint8_t)((fifo_message->cs & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
1775  /* Reverse the endianness */
1776  FlexcanSwapBytesInWord(msgData_32[0], msgData_32[0]);
1777  FlexcanSwapBytesInWord(msgData_32[1], msgData_32[1]);
1778  }
1779 #endif
1780  /* Clear fifo message*/
1781  state->mbs[FLEXCAN_MB_HANDLE_RXFIFO].mb_message = NULL;
1782 
1783  /* Update status for receive by using fifo*/
1785  {
1787  }
1789 }
1790 
1791 /*FUNCTION**********************************************************************
1792  *
1793  * Function Name : FLEXCAN_DRV_InstallEventCallback
1794  * Description : Installs a callback function for the IRQ handler.
1795  *
1796  * Implements : FLEXCAN_DRV_InstallEventCallback_Activity
1797  *END**************************************************************************/
1798 void FLEXCAN_DRV_InstallEventCallback(uint8_t instance,
1799  flexcan_callback_t callback,
1800  void *callbackParam)
1801 {
1802  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1803 
1804  flexcan_state_t * state = g_flexcanStatePtr[instance];
1805 
1806  state->callback = callback;
1807  state->callbackParam = callbackParam;
1808 }
1809 
1810 /*FUNCTION**********************************************************************
1811  *
1812  * Function Name : FLEXCAN_DRV_InstallErrorCallback
1813  * Description : Installs an error callback function for the IRQ handler and enables/disables
1814  * error interrupts.
1815  *
1816  * Implements : FLEXCAN_DRV_InstallErrorCallback_Activity
1817  *END**************************************************************************/
1818 void FLEXCAN_DRV_InstallErrorCallback(uint8_t instance,
1819  flexcan_error_callback_t callback,
1820  void *callbackParam)
1821 {
1822  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1823 
1824  CAN_Type * base = g_flexcanBase[instance];
1825  flexcan_state_t * state = g_flexcanStatePtr[instance];
1826 
1827  state->error_callback = callback;
1828  state->errorCallbackParam = callbackParam;
1829 
1830  if (callback != NULL)
1831  {
1832  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_ERR, true);
1833  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_RX_WARNING, true);
1834  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_TX_WARNING, true);
1835  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_BUSOFF, true);
1836  }
1837  else
1838  {
1839  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_ERR, false);
1840  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_RX_WARNING, false);
1841  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_TX_WARNING, false);
1842  FLEXCAN_SetErrIntCmd(base, FLEXCAN_INT_BUSOFF, false);
1843  }
1844 }
1845 
1846 #if FEATURE_CAN_HAS_PRETENDED_NETWORKING
1847 
1848 /*FUNCTION**********************************************************************
1849  *
1850  * Function Name : FLEXCAN_DRV_ConfigPN
1851  * Description : Configures Pretended Networking settings.
1852  *
1853  * Implements : FLEXCAN_DRV_ConfigPN_Activity
1854  *END**************************************************************************/
1855 void FLEXCAN_DRV_ConfigPN(uint8_t instance, bool enable, const flexcan_pn_config_t *pnConfig)
1856 {
1857  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1858 
1859  CAN_Type * base = g_flexcanBase[instance];
1860 
1861  FLEXCAN_EnterFreezeMode(base);
1862 
1863  if (enable)
1864  {
1865  FLEXCAN_ConfigPN(base, pnConfig);
1866 #if FEATURE_CAN_HAS_SELF_WAKE_UP
1867  (void)FLEXCAN_SetSelfWakeUp(base, false);
1868 #endif
1869  }
1870 
1871  FLEXCAN_SetPN(base, enable);
1872 
1873  FLEXCAN_ExitFreezeMode(base);
1874 }
1875 
1876 /*FUNCTION**********************************************************************
1877  *
1878  * Function Name : FLEXCAN_DRV_GetWMB
1879  * Description : Extracts one of the frames which triggered the wake up event.
1880  *
1881  * Implements : FLEXCAN_DRV_GetWMB_Activity
1882  *END**************************************************************************/
1883 void FLEXCAN_DRV_GetWMB(uint8_t instance, uint8_t wmbIndex, flexcan_msgbuff_t *wmb)
1884 {
1885  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1886  DEV_ASSERT(wmb != NULL);
1887 
1888  uint32_t *tmp, wmbData;
1889  const CAN_Type *base = g_flexcanBase[instance];
1890 
1891  tmp = (uint32_t *)&wmb->data[0];
1892  wmbData = base->WMB[wmbIndex].WMBn_D03;
1893  REV_BYTES_32(wmbData, *tmp);
1894 
1895  tmp = (uint32_t *)&wmb->data[4];
1896  wmbData = base->WMB[wmbIndex].WMBn_D47;
1897  REV_BYTES_32(wmbData, *tmp);
1898 
1899  wmb->cs = base->WMB[wmbIndex].WMBn_CS;
1900 
1901  if ((wmb->cs & CAN_CS_IDE_MASK) != 0U)
1902  {
1903  wmb->msgId = base->WMB[wmbIndex].WMBn_ID;
1904  }
1905  else
1906  {
1907  wmb->msgId = base->WMB[wmbIndex].WMBn_ID >> CAN_ID_STD_SHIFT;
1908  }
1909 
1910  wmb->dataLen = (uint8_t)((wmb->cs & CAN_CS_DLC_MASK) >> 16);
1911 }
1912 
1913 #endif /* FEATURE_CAN_HAS_PRETENDED_NETWORKING */
1914 
1915 #if FEATURE_CAN_HAS_SELF_WAKE_UP
1916 
1917 /*FUNCTION**********************************************************************
1918  *
1919  * Function Name : FLEXCAN_DRV_ConfigSelfWakeUp
1920  * Description : Enables/Disables Self Wake Up mode and low pass filter
1921  * applied to Rx input.
1922  *
1923  * Implements : FLEXCAN_DRV_ConfigSelfWakeUp_Activity
1924  *END**************************************************************************/
1925 status_t FLEXCAN_DRV_ConfigSelfWakeUp(uint8_t instance, bool enable, bool lowPassFilterEn)
1926 {
1927  DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
1928 
1929  CAN_Type *base = g_flexcanBase[instance];
1930  status_t status = STATUS_SUCCESS;
1931 
1932  /* Enable Self Wake Up */
1933  status = FLEXCAN_SetSelfWakeUp(base, enable);
1934 
1935  if (status == STATUS_SUCCESS)
1936  {
1937  FLEXCAN_EnterFreezeMode(base);
1938 
1939  /* Enable Low Pass Filter */
1940  FLEXCAN_SetWakSrc(base, lowPassFilterEn);
1941 
1942  FLEXCAN_ExitFreezeMode(base);
1943  }
1944 
1945  return status;
1946 }
1947 
1948 #endif /* FEATURE_CAN_HAS_SELF_WAKE_UP */
1949 
1950 /*FUNCTION**********************************************************************
1951  *
1952  * Function Name : FLEXCAN_BitrateToTimeSeg
1953  * Description : Converts a bitrate (kbit/s) in time segment values for
1954  * standard CAN frame.
1955  *
1956  *END**************************************************************************/
1957 static void FLEXCAN_BitrateToTimeSeg(uint32_t bitrate,
1958  uint32_t clkFreq,
1959  flexcan_time_segment_t *timeSeg)
1960 {
1961  uint32_t dBitrate, tmpBitrate, dBitrateMin, tmpPresdiv, tmpSample,
1962  dSampleMin, dSample, samplePoint, numTq, pseg1, pseg2, propseg,
1963  presdiv, tSeg1, tSeg2, tmpPseg1, tmpPseg2, tmpPropseg;
1964 
1965  presdiv = 0U;
1966  propseg = 0U;
1967  pseg1 = 0U;
1968  pseg2 = 0U;
1969 
1970  dSampleMin = 100U;
1971  dBitrateMin = 1000000U;
1972  samplePoint = 88U;
1973 
1974  for (tmpPresdiv = 0U; tmpPresdiv < FLEXCAN_PRESDIV_MAX; tmpPresdiv++) {
1975 
1976  /* Compute the number of time quanta in 1 bit time */
1977  numTq = clkFreq / ((tmpPresdiv + 1U) * bitrate);
1978  /* Compute the real bitrate resulted */
1979  tmpBitrate = clkFreq / ((tmpPresdiv + 1U) * numTq);
1980 
1981  /* The number of time quanta in 1 bit time must be lower than the one supported */
1982  if ((numTq >= FLEXCAN_NUM_TQ_MIN) && (numTq < FLEXCAN_NUM_TQ_MAX)) {
1983  /* Compute time segments based on the value of the sampling point */
1984  tSeg1 = (numTq * samplePoint / 100U) - 1U;
1985  tSeg2 = numTq - 1U - tSeg1;
1986 
1987  /* Adjust time segment 1 and time segment 2 */
1988  while ((tSeg1 >= FLEXCAN_TSEG1_MAX) || (tSeg2 < FLEXCAN_TSEG2_MIN))
1989  {
1990  tSeg2 = tSeg2 + 1U;
1991  tSeg1 = tSeg1 - 1U;
1992  }
1993 
1994  tmpPseg2 = tSeg2 - 1U;
1995 
1996  /* Start from pseg1 = pseg2 and adjust until propseg is valid */
1997  tmpPseg1 = tmpPseg2;
1998  tmpPropseg = tSeg1 - tmpPseg1 - 2U;
1999 
2000  while (tmpPropseg <= 0U)
2001  {
2002  tmpPropseg = tmpPropseg + 1U;
2003  tmpPseg1 = tmpPseg1 - 1U;
2004  }
2005  while (tmpPropseg >= FLEXCAN_PROPSEG_MAX)
2006  {
2007  tmpPropseg = tmpPropseg - 1U;
2008  tmpPseg1 = tmpPseg1 + 1U;
2009  }
2010 
2011  if ((tSeg1 >= FLEXCAN_TSEG1_MAX) || (tSeg2 >= FLEXCAN_TSEG2_MAX) ||
2012  (tSeg2 < FLEXCAN_TSEG2_MIN) || (tSeg1 < FLEXCAN_TSEG1_MIN))
2013  {
2014  continue;
2015  }
2016  if ((tmpPropseg >= FLEXCAN_PROPSEG_MAX) ||
2017  (tmpPseg1 >= FLEXCAN_PSEG1_MAX) ||
2018  (tmpPseg2 < FLEXCAN_PSEG2_MIN) ||
2019  (tmpPseg2 >= FLEXCAN_PSEG2_MAX))
2020  {
2021  continue;
2022  }
2023 
2024  tmpSample = ((tSeg1 + 1U) * 100U) / numTq;
2025  dSample = (tmpSample > samplePoint) ? (tmpSample - samplePoint) : (samplePoint - tmpSample);
2026  dBitrate = (tmpBitrate > bitrate) ? (tmpBitrate - bitrate) : (bitrate - tmpBitrate);
2027 
2028  if ((dBitrate < dBitrateMin) ||
2029  ((dBitrate == dBitrateMin) && (dSample < dSampleMin)))
2030  {
2031  dSampleMin = dSample;
2032  dBitrateMin = dBitrate;
2033  pseg1 = tmpPseg1;
2034  pseg2 = tmpPseg2;
2035  presdiv = tmpPresdiv;
2036  propseg = tmpPropseg;
2037 
2038  if ((dBitrate == 0U) && (dSample <= 1U))
2039  {
2040  break;
2041  }
2042  }
2043  }
2044  }
2045 
2046  timeSeg->phaseSeg1 = pseg1;
2047  timeSeg->phaseSeg2 = pseg2;
2048  timeSeg->preDivider = presdiv;
2049  timeSeg->propSeg = propseg;
2050  timeSeg->rJumpwidth = (pseg1 < FLEXCAN_RJW_MAX) ? pseg1 : FLEXCAN_RJW_MAX;
2051 }
2052 
2053 /*FUNCTION**********************************************************************
2054  *
2055  * Function Name : FLEXCAN_DRV_GetDefaultConfig
2056  * Description : Gets the default configuration structure
2057  *
2058  * Implements : FLEXCAN_DRV_GetDefaultConfig_Activity
2059  *END**************************************************************************/
2061 {
2062  /* Checks input parameter. */
2063  DEV_ASSERT(config != NULL);
2064 
2065  uint32_t clkFreq;
2066  flexcan_time_segment_t timeSeg;
2067 
2068  /* Get the PE clock frequency */
2070  /* Time segments computed for PE bitrate = 500 Kbit/s, sample point = 87.5 */
2071  FLEXCAN_BitrateToTimeSeg(500000U, clkFreq, &timeSeg);
2072 
2073  /* Maximum number of message buffers */
2074  config->max_num_mb = 16;
2075  /* Rx FIFO is disabled */
2076  config->is_rx_fifo_needed = false;
2077  /* Number of Rx FIFO ID filters */
2079  /* Normal operation mode */
2080  config->flexcanMode = FLEXCAN_NORMAL_MODE;
2081 #if FEATURE_CAN_HAS_PE_CLKSRC_SELECT
2082  /* Protocol engine clock is System Oscillator div 2 */
2083  config->pe_clock = FLEXCAN_CLK_SOURCE_OSC;
2084 #endif
2085  /* Time segments for the arbitration phase */
2086  config->bitrate = timeSeg;
2087 #if FEATURE_CAN_HAS_FD
2088  /* Payload size */
2089  config->payload = FLEXCAN_PAYLOAD_SIZE_8;
2090  /* Flexible data rate is disabled */
2091  config->fd_enable = false;
2092  /* Time segments for the data phase of FD frames */
2093  config->bitrate_cbt = timeSeg;
2094 #endif
2095  /* Rx FIFO transfer type */
2097 #if FEATURE_CAN_HAS_DMA_ENABLE
2098  /* Rx FIFO DMA channel */
2099  config->rxFifoDMAChannel = 0U;
2100 #endif
2101 }
2102 
2103 /*******************************************************************************
2104  * EOF
2105  ******************************************************************************/
struct CAN_Type::@0 WMB[4u]
volatile const uint32_t WMBn_ID
Definition: S32K118.h:829
status_t FLEXCAN_DRV_Receive(uint8_t instance, uint8_t mb_idx, flexcan_msgbuff_t *data)
Receives a CAN frame using the specified message buffer.
void FLEXCAN_DRV_GetBitrateFD(uint8_t instance, flexcan_time_segment_t *bitrate)
Gets the FlexCAN bit rate for the data phase of FD frames (BRS enabled).
status_t FLEXCAN_DRV_Deinit(uint8_t instance)
Shuts down a FlexCAN instance.
Internal driver state information.
flexcan_msgbuff_id_type_t
FlexCAN Message Buffer ID type Implements : flexcan_msgbuff_id_type_t_Class.
void FLEXCAN_DRV_GetWMB(uint8_t instance, uint8_t wmbIndex, flexcan_msgbuff_t *wmb)
Extracts one of the frames which triggered the wake up event.
status_t EDMA_DRV_InstallCallback(uint8_t virtualChannel, edma_callback_t callback, void *parameter)
Registers the callback function and the parameter for eDMA channel.
Definition: edma_driver.c:336
#define CAN_BASE_PTRS
Definition: S32K118.h:851
flexcan_operation_modes_t flexcanMode
#define FLEXCAN_TSEG2_MAX
#define FEATURE_CAN_MB_IRQS_MAX_COUNT
flexcan_fd_payload_size_t payload
status_t FLEXCAN_DRV_ConfigTxMb(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *tx_info, uint32_t msg_id)
FlexCAN transmit message buffer field configuration.
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
void FLEXCAN_DRV_GetDefaultConfig(flexcan_user_config_t *config)
Gets the default configuration structure.
flexcan_time_segment_t bitrate
static const IRQn_Type g_flexcanErrorIrqId[]
void * callbackParam
flexcan_rx_mask_type_t
FlexCAN Rx mask type. Implements : flexcan_rx_mask_type_t_Class.
#define REV_BYTES_32(a, b)
Reverse byte order in a word.
Definition: s32_core_cm0.h:103
status_t EDMA_DRV_ConfigSingleBlockTransfer(uint8_t virtualChannel, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, edma_transfer_size_t transferSize, uint32_t dataBufferSize)
Configures a simple single block data transfer with DMA.
Definition: edma_driver.c:554
flexcan_rx_fifo_id_filter_num_t num_id_filters
void FLEXCAN_DRV_SetTDCOffset(uint8_t instance, bool enable, uint8_t offset)
Enables/Disables the Transceiver Delay Compensation feature and sets the Transceiver Delay Compensati...
#define FLEXCAN_TSEG1_MIN
static status_t FLEXCAN_StartRxMessageFifoData(uint8_t instance, flexcan_msgbuff_t *data, bool isBlocking)
volatile uint32_t FDCTRL
Definition: S32K118.h:834
status_t FLEXCAN_DRV_RxFifo(uint8_t instance, flexcan_msgbuff_t *data)
Receives a CAN frame using the message FIFO.
#define FLEXCAN_PROPSEG_MAX
static flexcan_state_t * g_flexcanStatePtr[(1u)]
uint8_t data[64]
#define CAN_Error_IRQS
Definition: S32K118.h:872
void FLEXCAN_DRV_ConfigRxFifo(uint8_t instance, flexcan_rx_fifo_id_element_format_t id_format, const flexcan_id_table_t *id_filter_table)
FlexCAN Rx FIFO field configuration.
#define CAN_FDCTRL_TDCFAIL_MASK
Definition: S32K118.h:1531
status_t FLEXCAN_DRV_GetTransferStatus(uint8_t instance, uint8_t mb_idx)
Returns whether the previous FlexCAN transfer has finished.
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
flexcan_msgbuff_id_type_t msg_id_type
#define FLEXCAN_PRESDIV_MAX
#define FEATURE_CAN_RXFIFO_WARNING
#define FLEXCAN_PSEG2_MIN
static const IRQn_Type g_flexcanOredMessageBufferIrqId[(2U)][(1u)]
#define CAN_Wake_Up_IRQS
Definition: S32K118.h:871
void FLEXCAN_DRV_InstallEventCallback(uint8_t instance, flexcan_callback_t callback, void *callbackParam)
Installs a callback function for the IRQ handler.
status_t EDMA_DRV_StopChannel(uint8_t virtualChannel)
Stops the eDMA channel.
Definition: edma_driver.c:952
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
#define FLEXCAN_MB_HANDLE_RXFIFO
#define CAN_INSTANCE_COUNT
Definition: S32K118.h:840
static void FLEXCAN_CompleteTransfer(uint8_t instance, uint32_t mb_idx)
#define DEV_ASSERT(x)
Definition: devassert.h:77
void FLEXCAN_DRV_ClearTDCFail(uint8_t instance)
Clears the TDC Fail flag.
static status_t FLEXCAN_StartSendData(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *tx_info, uint32_t msg_id, const uint8_t *mb_data, bool isBlocking)
volatile uint32_t IFLAG1
Definition: S32K118.h:803
edma_chn_status_t
Channel status for eDMA channel.
Definition: edma_driver.h:255
flexcan_rxfifo_transfer_type_t transferType
#define FEATURE_CAN_MAX_MB_NUM
status_t FLEXCAN_DRV_AbortTransfer(uint8_t instance, uint8_t mb_idx)
Ends a non-blocking FlexCAN transfer early.
static void FLEXCAN_CompleteRxFifoDataDMA(void *parameter, edma_chn_status_t status)
#define FEATURE_CAN_MB_IRQS
static const IRQn_Type g_flexcanBusOffIrqId[]
void FLEXCAN_DRV_SetRxMb15Mask(uint8_t instance, flexcan_msgbuff_id_type_t id_type, uint32_t mask)
Sets the FlexCAN Rx MB 15 mask (standard or extended).
uint8_t rxFifoDMAChannel
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
void FLEXCAN_DRV_SetRxMaskType(uint8_t instance, flexcan_rx_mask_type_t type)
Sets the Rx masking type.
volatile flexcan_mb_state_t state
FlexCAN bitrate related structures Implements : flexcan_time_segment_t_Class.
volatile uint32_t RAMn[128u]
Definition: S32K118.h:812
#define FLEXCAN_PSEG2_MAX
void * errorCallbackParam
status_t FLEXCAN_DRV_ConfigRxMb(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *rx_info, uint32_t msg_id)
FlexCAN receive message buffer field configuration.
#define FLEXCAN_NUM_TQ_MIN
static void FLEXCAN_BitrateToTimeSeg(uint32_t bitrate, uint32_t clkFreq, flexcan_time_segment_t *timeSeg)
status_t FLEXCAN_DRV_ConfigRemoteResponseMb(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *tx_info, uint32_t msg_id, const uint8_t *mb_data)
Configures a transmit message buffer for remote frame response.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K118.h:188
void(* callback)(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, struct FlexCANState *driverState)
#define FEATURE_CAN_RXFIFO_OVERFLOW
void FLEXCAN_DRV_InstallErrorCallback(uint8_t instance, flexcan_error_callback_t callback, void *callbackParam)
Installs an error callback function for the IRQ handler and enables error interrupts.
flexcan_mb_handle_t mbs[(32U)]
bool FLEXCAN_DRV_GetTDCFail(uint8_t instance)
Gets the value of the TDC Fail flag.
FlexCAN message buffer structure Implements : flexcan_msgbuff_t_Class.
volatile const uint32_t WMBn_D03
Definition: S32K118.h:830
volatile const uint32_t WMBn_CS
Definition: S32K118.h:828
flexcan_rx_fifo_id_element_format_t
ID formats for Rx FIFO Implements : flexcan_rx_fifo_id_element_format_t_Class.
status_t FLEXCAN_DRV_SendBlocking(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *tx_info, uint32_t msg_id, const uint8_t *mb_data, uint32_t timeout_ms)
Sends a CAN frame using the specified message buffer, in a blocking manner.
void(* error_callback)(uint8_t instance, flexcan_event_type_t eventType, struct FlexCANState *driverState)
#define CAN_FDCTRL_TDCVAL_MASK
Definition: S32K118.h:1523
void FLEXCAN_Error_IRQHandler(uint8_t instance)
Error interrupt handler for a FlexCAN instance.
FlexCAN Rx FIFO ID filter table structure Implements : flexcan_id_table_t_Class.
status_t FLEXCAN_DRV_RxFifoBlocking(uint8_t instance, flexcan_msgbuff_t *data, uint32_t timeout_ms)
Receives a CAN frame using the message FIFO, in a blocking manner.
flexcan_time_segment_t bitrate_cbt
flexcan_rxfifo_transfer_type_t transfer_type
Pretended Networking configuration structure Implements : flexcan_pn_config_t_Class.
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
uint8_t FLEXCAN_DRV_GetTDCValue(uint8_t instance)
Gets the value of the Transceiver Delay Compensation.
#define CAN_FDCTRL_TDCFAIL_SHIFT
Definition: S32K118.h:1532
void FLEXCAN_DRV_SetRxFifoGlobalMask(uint8_t instance, flexcan_msgbuff_id_type_t id_type, uint32_t mask)
Sets the FlexCAN Rx FIFO global mask (standard or extended).
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
static CAN_Type *const g_flexcanBase[]
status_t FLEXCAN_DRV_ReceiveBlocking(uint8_t instance, uint8_t mb_idx, flexcan_msgbuff_t *data, uint32_t timeout_ms)
Receives a CAN frame using the specified message buffer, in a blocking manner.
static status_t FLEXCAN_StartRxMessageBufferData(uint8_t instance, uint8_t mb_idx, flexcan_msgbuff_t *data, bool isBlocking)
status_t EDMA_DRV_StartChannel(uint8_t virtualChannel)
Starts an eDMA channel.
Definition: edma_driver.c:921
void FLEXCAN_DRV_SetBitrateCbt(uint8_t instance, const flexcan_time_segment_t *bitrate)
Sets the FlexCAN bit rate for the data phase of FD frames (BRS enabled).
#define FLEXCAN_NUM_TQ_MAX
void FLEXCAN_IRQHandler(uint8_t instance)
Interrupt handler for a FlexCAN instance.
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
flexcan_msgbuff_t * mb_message
uint32_t FLEXCAN_DRV_GetErrorStatus(uint8_t instance)
Returns reported error conditions.
#define FEATURE_CAN_RXFIFO_FRAME_AVAILABLE
#define FEATURE_CAN_PE_OSC_CLK_NAME
void FLEXCAN_DRV_SetRxMbGlobalMask(uint8_t instance, flexcan_msgbuff_id_type_t id_type, uint32_t mask)
Sets the FlexCAN Rx MB global mask (standard or extended).
FlexCAN data info from user Implements : flexcan_data_info_t_Class.
#define CAN_Bus_Off_IRQS
Definition: S32K118.h:873
status_t FLEXCAN_DRV_Init(uint8_t instance, flexcan_state_t *state, const flexcan_user_config_t *data)
Initializes the FlexCAN peripheral.
#define FLEXCAN_RJW_MAX
static const IRQn_Type g_flexcanWakeUpIrqId[]
void FLEXCAN_WakeUpHandler(uint8_t instance)
Wake up handler for a FlexCAN instance.
void(* flexcan_error_callback_t)(uint8_t instance, flexcan_event_type_t eventType, flexcan_state_t *flexcanState)
FlexCAN Driver error callback function type Implements : flexcan_error_callback_t_Class.
status_t FLEXCAN_DRV_Send(uint8_t instance, uint8_t mb_idx, const flexcan_data_info_t *tx_info, uint32_t msg_id, const uint8_t *mb_data)
Sends a CAN frame using the specified message buffer.
status_t FLEXCAN_DRV_SetRxIndividualMask(uint8_t instance, flexcan_msgbuff_id_type_t id_type, uint8_t mb_idx, uint32_t mask)
Sets the FlexCAN Rx individual mask (standard or extended).
void(* flexcan_callback_t)(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, flexcan_state_t *flexcanState)
FlexCAN Driver callback function type Implements : flexcan_callback_t_Class.
volatile const uint32_t WMBn_D47
Definition: S32K118.h:831
#define FLEXCAN_PSEG1_MAX
#define FLEXCAN_TSEG1_MAX
volatile uint32_t ESR1
Definition: S32K118.h:799
#define CAN_FDCTRL_TDCVAL_SHIFT
Definition: S32K118.h:1524
#define FLEXCAN_TSEG2_MIN
void FLEXCAN_DRV_SetBitrate(uint8_t instance, const flexcan_time_segment_t *bitrate)
Sets the FlexCAN bit rate for standard frames or the arbitration phase of FD frames.
static void FLEXCAN_CompleteRxMessageFifoData(uint8_t instance)
flexcan_clk_source_t pe_clock
FlexCAN configuration.
void FLEXCAN_DRV_SetRxMb14Mask(uint8_t instance, flexcan_msgbuff_id_type_t id_type, uint32_t mask)
Sets the FlexCAN Rx MB 14 mask (standard or extended).
void FLEXCAN_DRV_GetBitrate(uint8_t instance, flexcan_time_segment_t *bitrate)
Gets the FlexCAN bit rate for standard frames or the arbitration phase of FD frames.
void FLEXCAN_DRV_ConfigPN(uint8_t instance, bool enable, const flexcan_pn_config_t *pnConfig)
Configures Pretended Networking settings.