]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/drv/canfd/src/canfd.c
4ae2aef216fc09350f30a65a9b723dd3d98c80d7
[processor-sdk/pdk.git] / packages / ti / drv / canfd / src / canfd.c
1 /**
2  *   @file  canfd.c
3  *
4  *   @brief
5  *      The file implements the Controller Area Network Driver Flexible data
6  *      for TPR12.
7  *
8  *  \par
9  *  NOTE:
10  *      (C) Copyright 2020 Texas Instruments, Inc.
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *
16  *    Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  *
19  *    Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the
22  *    distribution.
23  *
24  *    Neither the name of Texas Instruments Incorporated nor the names of
25  *    its contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
41 /**************************************************************************
42  *************************** Include Files ********************************
43  **************************************************************************/
44 #include <stdint.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <ti/osal/osal.h>
48 #include <ti/osal/MemoryP.h>
49 #include <ti/osal/DebugP.h>
50 #include <ti/drv/canfd/soc/canfd_soc.h>
51 #include "canfd_internal.h"
53 #define MINUS_ONE                                                           (-1)
55 static void CANFD_processFIFOElements(CANFD_DriverMCB* ptrCanFdMCB, MCAN_RxFIFONum fifoNum);
56 static void CANFD_MCANInt0Isr (uintptr_t arg);
57 static void CANFD_MCANInt1Isr (uintptr_t arg);
58 static void CANFD_configMessageRAM(const CANFD_DriverMCB* ptrCanFdMCB, const CANFD_MCANMsgRAMCfgParams* configParams, int32_t* errCode);
60 /**
61  *  @b Description
62  *  @n
63  *      Function processes the Rx FIFO and calls application callback function to receive data.
64  *
65  *  @param[in]  ptrCanFdMCB
66  *      Pointer to the CANFD driver MCB
67  *  @param[in]  fifoNum
68  *      Rx FiFO number
69  *
70  *  @retval
71  *      Success -   Handle to the CAN Driver
72  *  @retval
73  *      Error   -   NULL
74  */
76 static void CANFD_processFIFOElements(CANFD_DriverMCB* ptrCanFdMCB, MCAN_RxFIFONum fifoNum)
77 {
78     MCAN_RxFIFOStatus       fifoStatus;
79     uint32_t                fillLevel;
80     uint32_t                index;
81     CANFD_MessageObject*    ptrCanMsgObj;
82     uint32_t                baseAddr;
84     baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
86     /* Get the FIFO status */
87     fifoStatus.num = (uint32_t)fifoNum;
88     MCAN_getRxFIFOStatus(baseAddr, &fifoStatus);
89     fillLevel = fifoStatus.fillLvl;
91     for(index = 0; index < fillLevel; index++)
92     {
93         MCAN_readMsgRam(baseAddr, MCAN_MEM_TYPE_FIFO, fifoStatus.getIdx, (uint32_t)fifoNum, &ptrCanFdMCB->rxBuffElem);
95         /* Get the message object pointer */
96         ptrCanMsgObj = ptrCanFdMCB->rxMapping[ptrCanFdMCB->rxBuffElem.fidx];
98         /* Increment the number of interrupts received */
99         ptrCanMsgObj->interruptsRxed++;
101         /* Call the registered callback. */
102         ptrCanFdMCB->appDataCallBack((CANFD_MsgObjHandle)ptrCanMsgObj, CANFD_Reason_RX);
104         /* Acknowledge the data read */
105         MCAN_writeRxFIFOAck(baseAddr, (uint32_t)fifoNum, fifoStatus.getIdx);
107         MCAN_getRxFIFOStatus(baseAddr, &fifoStatus);
108     }
111 /**
112  *  @b Description
113  *  @n
114  *      The function is the registered interrupt 0 ISR for the CANFD Driver.
115  *
116  *  @param[in]  arg
117  *      Argument which is registered with the OS while registering the ISR
118  *
119  *  \ingroup CANFD_DRIVER_INTERNAL_FUNCTION
120  *
121  *  @retval
122  *      Not applicable
123  */
124 static void CANFD_MCANInt0Isr (uintptr_t arg)
126     CANFD_MessageObject*    ptrCanMsgObj;
127     CANFD_DriverMCB*        ptrCanFdMCB;
128     uint32_t                baseAddr;
129     uint32_t                intrStatus;
130     uint32_t                index, status, buffIndex;
131     MCAN_RxNewDataStatus    newDataStatus;
133     /* Get the pointer to the CAN Driver Block */
134     ptrCanFdMCB = (CANFD_DriverMCB*)arg;
136     /* Increment the number of interrupts received */
137     ptrCanFdMCB->interrupts++;
138     baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
140     intrStatus = MCAN_getIntrStatus(baseAddr);
141     MCAN_clearIntrStatus(baseAddr, intrStatus);
143     /* Process Bus-Off condition */
144     if ((intrStatus & MCAN_INTR_SRC_BUS_OFF_STATUS) == MCAN_INTR_SRC_BUS_OFF_STATUS)
145     {
146         /* Increment the number of interrupts received */
147         ptrCanFdMCB->busOffInterrupts++;
149         ptrCanFdMCB->state = CANFD_DriverState_STOPPED;
151         /* Call the registered callback. */
152         if (ptrCanFdMCB->appErrCallBack != NULL)
153         {
154             ptrCanFdMCB->appErrCallBack((CANFD_Handle)ptrCanFdMCB, CANFD_Reason_BUSOFF, NULL);
155         }
156     }
158     /* Process Protocol error in data phase condition */
159     if ((intrStatus & MCAN_INTR_SRC_PROTOCOL_ERR_DATA) == MCAN_INTR_SRC_PROTOCOL_ERR_DATA)
160     {
161         /* Increment the number of interrupts received */
162         ptrCanFdMCB->protoDataErrInterrupts++;
164         /* Call the registered callback. */
165         if (ptrCanFdMCB->appErrCallBack != NULL)
166         {
167             ptrCanFdMCB->appErrCallBack((CANFD_Handle)ptrCanFdMCB, CANFD_Reason_PROTOCOL_ERR_DATA_PHASE, NULL);
168         }
169     }
171     /* Process Protocol error in arbitration phase condition */
172     if ((intrStatus & MCAN_INTR_SRC_PROTOCOL_ERR_ARB) == MCAN_INTR_SRC_PROTOCOL_ERR_ARB)
173     {
174         /* Increment the number of interrupts received */
175         ptrCanFdMCB->protoArbErrInterrupts++;
177         /* Call the registered callback. */
178         if (ptrCanFdMCB->appErrCallBack != NULL)
179         {
180             ptrCanFdMCB->appErrCallBack((CANFD_Handle)ptrCanFdMCB, CANFD_Reason_PROTOCOL_ERR_ARB_PHASE, NULL);
181         }
182     }
184     /* Process Transmit complete interrrupt */
185     if ((intrStatus & MCAN_INTR_SRC_TRANS_COMPLETE) == MCAN_INTR_SRC_TRANS_COMPLETE)
186     {
187         status = MCAN_getTxBufTransmissionStatus(baseAddr);
189         /* Process all 32 Tx buffers */
190         for(index = 0; index < MCAN_MAX_TX_BUFFERS; index++)
191         {
192             buffIndex = ((uint32_t)1U << index);
193             if(buffIndex == (status & buffIndex))
194             {
195                 /* Get the message object pointer */
196                 ptrCanMsgObj = ptrCanFdMCB->txMapping[index];
198                 /* Increment the number of interrupts received */
199                 ptrCanMsgObj->interruptsRxed++;
201                 if(ptrCanFdMCB->txStatus[ptrCanMsgObj->txElement] == 1)
202                 {
203                     ptrCanFdMCB->txStatus[ptrCanMsgObj->txElement] = 0;
205                     /* Call the registered callback. */
206                     ptrCanFdMCB->appDataCallBack((CANFD_MsgObjHandle)ptrCanMsgObj, CANFD_Reason_TX_COMPLETION);
207                 }
208             }
209             status = (status & ~buffIndex);
210             if (status == 0)
211             {
212                 break;
213             }
214         }
215     }
217     /* Process Receive buffer interrupt */
218     if ((intrStatus & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG) == MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG)
219     {
220         /* Get the new data status */
221         MCAN_getNewDataStatus(baseAddr, &newDataStatus);
223         /* Clear NewData status to accept new messages */
224         MCAN_clearNewDataStatus(baseAddr, &newDataStatus);
226         /* Process the low 32 buffers */
227         status = newDataStatus.statusLow;
228         index = 0;
229         while (status != 0)
230         {
231             if ((status & 1U) == 1U)
232             {
233                 /* Get the message object pointer */
234                 ptrCanMsgObj = ptrCanFdMCB->rxMapping[index];
236                 /* Increment the number of interrupts received */
237                 ptrCanMsgObj->interruptsRxed++;
239                 /* Read the pending data */
240                 MCAN_readMsgRam(baseAddr, ptrCanMsgObj->memType, ptrCanMsgObj->rxElement, 0, &ptrCanFdMCB->rxBuffElem);
242                 /* Call the registered callback. */
243                 ptrCanFdMCB->appDataCallBack((CANFD_MsgObjHandle)ptrCanMsgObj, CANFD_Reason_RX);
244             }
245             index++;
246             status = (status >> 1U);
247         }
248     }
250     /* Process Receive FIFO interrupts */
251     if ((intrStatus & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG) == MCAN_INTR_SRC_RX_FIFO0_NEW_MSG)
252     {
253         /* Process FIFO 0 */
254         CANFD_processFIFOElements(ptrCanFdMCB, MCAN_RX_FIFO_NUM_0);
255     }
257     if ((intrStatus & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG) == MCAN_INTR_SRC_RX_FIFO1_NEW_MSG)
258     {
259         /* Process FIFO 1 */
260         CANFD_processFIFOElements(ptrCanFdMCB, MCAN_RX_FIFO_NUM_1);
261     }
263     /* Process Transmit cancel interrrupt */
264     if ((intrStatus & MCAN_INTR_SRC_TRANS_CANCEL_FINISH) == MCAN_INTR_SRC_TRANS_CANCEL_FINISH)
265     {
266         status = MCAN_txBufCancellationStatus(baseAddr);
268         /* Process all 32 Tx buffers */
269         for(index = 0; index < MCAN_MAX_TX_BUFFERS; index++)
270         {
271             buffIndex = ((uint32_t)1U << index);
272             if(buffIndex == (status & buffIndex))
273             {
274                 /* Get the message object pointer */
275                 ptrCanMsgObj = ptrCanFdMCB->txMapping[index];
277                 /* Increment the number of interrupts received */
278                 ptrCanMsgObj->interruptsRxed++;
280                 if(ptrCanFdMCB->txStatus[ptrCanMsgObj->txElement] == 1)
281                 {
282                     ptrCanFdMCB->txStatus[ptrCanMsgObj->txElement] = 0;
284                     /* Call the registered callback. */
285                     ptrCanFdMCB->appDataCallBack((CANFD_MsgObjHandle)ptrCanMsgObj, CANFD_Reason_TX_CANCELED);
286                 }
287             }
288             status = (status & ~buffIndex);
289             if (status == 0)
290             {
291                 break;
292             }
293         }
294     }
296     return;
299 /**
300  *  @b Description
301  *  @n
302  *      The function is the registered interrupt 1 ISR for the CANFD Driver.
303  *
304  *  @param[in]  arg
305  *      Argument which is registered with the OS while registering the ISR
306  *
307  *  \ingroup CANFD_DRIVER_INTERNAL_FUNCTION
308  *
309  *  @retval
310  *      Not applicable
311  */
312 static void CANFD_MCANInt1Isr (uintptr_t arg)
314     CANFD_DriverMCB*    ptrCanFdMCB;
315     uint32_t            baseAddr;
316     MCAN_ECCErrStatus   errStatusResp;
318     /* Get the pointer to the CAN Driver Block */
319     ptrCanFdMCB = (CANFD_DriverMCB*)arg;
320     baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
322     /* Increment the number of interrupts received */
323     ptrCanFdMCB->eccInterrupts++;
325     /* Read ECC error status */
326     MCAN_eccGetErrorStatus(baseAddr, &errStatusResp);
327     if (errStatusResp.secErr == 1U)
328     {
329         MCAN_eccClearErrorStatus(baseAddr, CANFD_MCANECCErrType_SEC);
330     }
331     if (errStatusResp.dedErr == 1U)
332     {
333         MCAN_eccClearErrorStatus(baseAddr, CANFD_MCANECCErrType_DED);
334     }
336     /* Call the registered callback. */
337     if (ptrCanFdMCB->appErrCallBack != NULL)
338     {
339         CANFD_ErrStatusResp errStatusInfo;
341         errStatusInfo.u.eccErrStatus.bit1 = errStatusResp.bit1;
342         errStatusInfo.u.eccErrStatus.bit2 = errStatusResp.bit2;
343         errStatusInfo.u.eccErrStatus.dedErr = errStatusResp.dedErr;
344         errStatusInfo.u.eccErrStatus.row    = errStatusResp.row;
345         errStatusInfo.u.eccErrStatus.secErr = errStatusResp.secErr;
346         ptrCanFdMCB->appErrCallBack((CANFD_Handle)ptrCanFdMCB, CANFD_Reason_ECC_ERROR, &errStatusInfo);
347     }
349     MCAN_eccWriteEOI(baseAddr, CANFD_MCANECCErrType_SEC);
350     MCAN_eccWriteEOI(baseAddr, CANFD_MCANECCErrType_DED);
352     return;
355 /**
356  *  @b Description
357  *  @n
358  *      Function initializes the CANFD driver instance with the specified hardware attributes.
359  *      It resets and configures the MCAN module, sets up the Message RAM and ECC Aggregator.
360  *      It configures the CANFD driver with the control parameters.
361  *
362  *  @param[in]  ptrCanFdMCB
363  *      Pointer to the CANFD driver MCB
364  *  @param[in]  configParams
365  *      CAN module configuration parameters
366  *  @param[out]  errCode
367  *      Error code populated on error
368  *
369  *  @retval
370  *      Success -   Handle to the CAN Driver
371  *  @retval
372  *      Error   -   NULL
373  */
375 static void CANFD_configMessageRAM(const CANFD_DriverMCB* ptrCanFdMCB, const CANFD_MCANMsgRAMCfgParams* configParams, int32_t* errCode)
377     MCAN_MsgRAMConfigParams msgRAMConfigParams;
378     uint32_t                startAddr;
380     /* Compute the start Address and populate the Message RAM configuration parameters */
381     startAddr = 0;
383     /* 11-bit filter configuration */
384     msgRAMConfigParams.flssa = startAddr;
385     msgRAMConfigParams.lss = configParams->lss;
387     /* 29-bit filter configuration */
388     startAddr += ((configParams->lss + 1U) * MCAN_MSG_RAM_STD_ELEM_SIZE * 4U);
389     msgRAMConfigParams.flesa = startAddr;
390     msgRAMConfigParams.lse = configParams->lse;
392     /* Tx buffer configuration */
393     startAddr += ((configParams->lse + 1U) * MCAN_MSG_RAM_EXT_ELEM_SIZE * 4U);
394     msgRAMConfigParams.txStartAddr = startAddr;
395     msgRAMConfigParams.txBufNum = configParams->txBufNum;
396     msgRAMConfigParams.txFIFOSize = configParams->txFIFOSize;
397     msgRAMConfigParams.txBufMode = 1U;
398     msgRAMConfigParams.txBufElemSize = CANFD_MCANElemSize_64BYTES;
400     /* Tx Event FIFO configuration */
401     msgRAMConfigParams.txEventFIFOStartAddr = 0;
402     msgRAMConfigParams.txEventFIFOSize = 0;
403     msgRAMConfigParams.txEventFIFOWaterMark = 0;
405     /* Rx FIFO 0 configuration */
406     startAddr += ((configParams->txBufNum + 1U) * MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
407     startAddr += ((configParams->txFIFOSize + 1U) * MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
408     msgRAMConfigParams.rxFIFO0startAddr = startAddr;
409     msgRAMConfigParams.rxFIFO0size = configParams->rxFIFO0size;
410     msgRAMConfigParams.rxFIFO0waterMark = 0;
411     msgRAMConfigParams.rxFIFO0ElemSize = CANFD_MCANElemSize_64BYTES;
412     msgRAMConfigParams.rxFIFO0OpMode = configParams->rxFIFO0OpMode;
414     /* Rx FIFO 1 configuration */
415     startAddr += ((configParams->rxFIFO0size + 1U) * MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
416     msgRAMConfigParams.rxFIFO1startAddr = startAddr;
417     msgRAMConfigParams.rxFIFO1size = configParams->rxFIFO1size;
418     msgRAMConfigParams.rxFIFO1waterMark = 0;
419     msgRAMConfigParams.rxFIFO1ElemSize = CANFD_MCANElemSize_64BYTES;
420     msgRAMConfigParams.rxFIFO1OpMode = configParams->rxFIFO1OpMode;
422     /* Rx Buffer configuration */
423     startAddr += ((configParams->rxFIFO1size + 1U) * MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
424     msgRAMConfigParams.rxBufStartAddr = startAddr;
425     msgRAMConfigParams.rxBufElemSize = CANFD_MCANElemSize_64BYTES;
427     /* Configure Message RAM */
428     *errCode = MCAN_msgRAMConfig(ptrCanFdMCB->hwCfg.regBaseAddress, &msgRAMConfigParams);
431 static void CANFD_initCslMcanInitParams(const CANFD_MCANInitParams* configParams, MCAN_InitParams *cslMcanInitPrms)
433     cslMcanInitPrms->autoWkupEnable  = configParams->autoWkupEnable;
434     cslMcanInitPrms->brsEnable       = configParams->brsEnable;
435     cslMcanInitPrms->clkStopFAck     = configParams->clkStopFAck;
436     cslMcanInitPrms->darEnable       = configParams->darEnable;
437     cslMcanInitPrms->efbi            = configParams->efbi;
438     cslMcanInitPrms->emulationEnable = configParams->emulationEnable;
439     cslMcanInitPrms->emulationFAck   = configParams->emulationFAck;
440     cslMcanInitPrms->fdMode          = configParams->fdMode;
441     cslMcanInitPrms->pxhddisable     = configParams->pxhddisable;
442     cslMcanInitPrms->tdcEnable       = configParams->tdcEnable;
443     cslMcanInitPrms->txpEnable       = configParams->txpEnable;
444     cslMcanInitPrms->wdcPreload      = configParams->wdcPreload;
445     cslMcanInitPrms->wkupReqEnable   = configParams->wkupReqEnable;
446     cslMcanInitPrms->tdcConfig.tdcf  = configParams->tdcConfig.tdcf;
447     cslMcanInitPrms->tdcConfig.tdco  = configParams->tdcConfig.tdco;
450 static void CANFD_initCslMcanConfigParams(const CANFD_MCANInitParams* configParams, MCAN_ConfigParams *cslMcanConfigPrms)
452     cslMcanConfigPrms->asmEnable         = configParams->asmEnable;
453     cslMcanConfigPrms->monEnable         = configParams->monEnable;
454     cslMcanConfigPrms->timeoutCntEnable  = configParams->timeoutCntEnable;
455     cslMcanConfigPrms->timeoutPreload    = configParams->timeoutPreload;
456     cslMcanConfigPrms->timeoutSelect     = configParams->timeoutSelect;
457     cslMcanConfigPrms->tsPrescalar       = configParams->tsPrescalar;
458     cslMcanConfigPrms->tsSelect          = configParams->tsSelect;
459     cslMcanConfigPrms->filterConfig.anfe = configParams->filterConfig.anfe;
460     cslMcanConfigPrms->filterConfig.anfs = configParams->filterConfig.anfs;
461     cslMcanConfigPrms->filterConfig.rrfe = configParams->filterConfig.rrfe;
462     cslMcanConfigPrms->filterConfig.rrfs = configParams->filterConfig.rrfs;
465 static void CANFD_initCslMcanECCConfigParams(const CANFD_MCANInitParams* configParams, MCAN_ECCConfigParams *cslMcanEccConfigPrms)
467     cslMcanEccConfigPrms->enable = configParams->eccConfig.enable;
468     cslMcanEccConfigPrms->enableChk = configParams->eccConfig.enableChk;
469     cslMcanEccConfigPrms->enableRdModWr = configParams->eccConfig.enableRdModWr;
472 /**
473  *  @b Description
474  *  @n
475  *      Function initializes the CANFD driver instance with the specified hardware attributes.
476  *      It resets and configures the MCAN module, sets up the Message RAM and ECC Aggregator.
477  *      It configures the CANFD driver with the control parameters.
478  *
479  *  @param[in]  instanceId
480  *      CANFD Instance Id.
481  *      The valid values are platform specific.
482  *  @param[in]  configParams
483  *      CANFD module configuration parameters
484  *  @param[out]  errCode
485  *      Error code populated on error
486  *
487  *  @retval
488  *      Success -   Handle to the CANFD Driver
489  *  @retval
490  *      Error   -   NULL
491  */
493 CANFD_Handle CANFD_init(uint8_t instanceId, const CANFD_MCANInitParams* configParams, int32_t* errCode)
495     CANFD_DriverMCB*        ptrCanFdMCB;
496     OsalRegisterIntrParams_t interruptRegParams;
497     uint32_t                baseAddr;
498     MCAN_RxNewDataStatus    newDataStatus;
499     volatile uint32_t       status;
500     MCAN_InitParams         cslMcanInitPrms;
501     MCAN_ConfigParams       cslMcanConfigPrms;
502     MCAN_ECCConfigParams    cslMcanEccConfigPrms;
503     const CANFD_HwCfg      *hwCfg;
505     *errCode = CANFD_EOK;
507     hwCfg = CANFD_socGetHwCfg(instanceId);
508     /* Sanity check: Validate input parameters */
509     if ((instanceId >= CANFD_MAX_NUM_INSTANCE) || (configParams == NULL) || (configParams->appDataCallBack == NULL))
510     {
511         *errCode = CANFD_EINVAL;
512         ptrCanFdMCB = NULL;
513     }
514     else if ((hwCfg == NULL) || (instanceId != hwCfg->instanceId))
515     {
516         /* Check if multiple instances are supported for this SOC? */
517         *errCode = CANFD_EINVAL;
518         ptrCanFdMCB = NULL;
519     }
520     else
521     {
522         /* Allocate memory for the CANFD Driver */
523         ptrCanFdMCB = CANFD_socGetInstHandle (instanceId);
524         if (ptrCanFdMCB == NULL)
525         {
526             /* Error: Unable to allocate the memory */
527             *errCode = CANFD_ENOMEM;
528             ptrCanFdMCB = NULL;
529         }
530         else
531         {
533             /* Initialize the allocated memory */
534             memset ((void *)ptrCanFdMCB, 0, sizeof(CANFD_DriverMCB));
536             /* Initialize the CANFD driver state */
537             ptrCanFdMCB->state = CANFD_DriverState_UNINIT;
539             /* Copy over the configuration */
540             memcpy ((void *)&ptrCanFdMCB->hwCfg, hwCfg, sizeof(CANFD_HwCfg));
542             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
544             /* Check if Message RAM initialization is done or not TODO add timeout */
545             do
546             {
547                 status = MCAN_isMemInitDone(baseAddr);
548                 if (status == 1U)
549                 {
550                     break;
551                 }
552             } while (1);
554             /* Reset the MCAN module. */
555             MCAN_reset(baseAddr);
557             /* Wait while MCAN is in reset. TODO add timeout */
558             do
559             {
560             } while (MCAN_isInReset(baseAddr) == 1U);
562             /* Put MCAN in SW initialization mode */
563             MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_SW_INIT);
565             /* Wait while MCAN is not in init mode. TODO add timeout */
566             do
567             {
568             } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_SW_INIT);
570             /* Initialize the MCAN module */
571             CANFD_initCslMcanInitParams(configParams, &cslMcanInitPrms);
572             *errCode  = MCAN_init (baseAddr, &cslMcanInitPrms);
573             if (*errCode != CANFD_EOK)
574             {
575                 ptrCanFdMCB = NULL;
576             }
578             /* Configure the MCAN module */
579             if (*errCode == CANFD_EOK)
580             {
581                 CANFD_initCslMcanConfigParams(configParams,&cslMcanConfigPrms);
582                 *errCode  = MCAN_config (baseAddr, &cslMcanConfigPrms);
583                 if (*errCode != CANFD_EOK)
584                 {
585                     ptrCanFdMCB = NULL;
586                 }
587             }
589             /* Configure the Message RAM */
590             if (*errCode == CANFD_EOK)
591             {
592                 CANFD_configMessageRAM(ptrCanFdMCB, &configParams->msgRAMConfig, errCode);
593                 if (*errCode != CANFD_EOK)
594                 {
595                     ptrCanFdMCB = NULL;
596                 }
597             }
599             if (*errCode == CANFD_EOK)
600             {
601                 /* Configure the ECC Aggregator */
602                 CANFD_initCslMcanECCConfigParams(configParams, &cslMcanEccConfigPrms);
603                 MCAN_eccConfig(baseAddr, &cslMcanEccConfigPrms);
605                 /* Clear all pending error flags and status */
606                 MCAN_clearIntrStatus(baseAddr, MCAN_INTR_MASK);
607                 newDataStatus.statusLow  = MCAN_NDAT1_CLEAR;
608                 newDataStatus.statusHigh = MCAN_NDAT2_CLEAR;
609                 MCAN_clearNewDataStatus(baseAddr, &newDataStatus);
611                 /* Register the Data Interrupt Handler. */
612                 if (configParams->dataInterruptEnable == 1U)
613                 {
614                     /* Register SPI Interrupt handling ISR */
615                     /* Initialize with defaults */
616                     Osal_RegisterInterrupt_initParams(&interruptRegParams);
617                     /* Populate the interrupt parameters */
618                     interruptRegParams.corepacConfig.arg=(uintptr_t)ptrCanFdMCB;
619                     interruptRegParams.corepacConfig.name=(char *)"CANFD_0";
620                     interruptRegParams.corepacConfig.isrRoutine=CANFD_MCANInt0Isr;
621                 #if defined(_TMS320C6X)
622                     interruptRegParams.corepacConfig.corepacEventNum=(int32_t)ptrCanFdMCB->hwCfg.interruptNum0; /* Event going in to CPU */
623                     interruptRegParams.corepacConfig.intVecNum      = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
624                 #else
625                     interruptRegParams.corepacConfig.intVecNum=(int32_t)ptrCanFdMCB->hwCfg.interruptNum0; /* Host Interrupt vector */
626                     interruptRegParams.corepacConfig.corepacEventNum = (int32_t)ptrCanFdMCB->hwCfg.interruptNum0;
627                 #endif
628                     /* Register interrupts */
629                     Osal_RegisterInterrupt(&interruptRegParams, &ptrCanFdMCB->hwiHandle0);
631                     DebugP_assert (ptrCanFdMCB->hwiHandle0 != NULL);
632                 }
634                 /* Register the ECC, error Interrupt Handler. */
635                 if (configParams->errInterruptEnable == 1U)
636                 {
637                     /* Register SPI Interrupt handling ISR */
638                     /* Initialize with defaults */
639                     Osal_RegisterInterrupt_initParams(&interruptRegParams);
640                     /* Populate the interrupt parameters */
641                     interruptRegParams.corepacConfig.arg=(uintptr_t)ptrCanFdMCB;
642                     interruptRegParams.corepacConfig.name=(char *)"CANFD_1";
643                     interruptRegParams.corepacConfig.isrRoutine=CANFD_MCANInt1Isr;
644                 #if defined(_TMS320C6X)
645                     interruptRegParams.corepacConfig.corepacEventNum=(int32_t)ptrCanFdMCB->hwCfg.interruptNum1; /* Event going in to CPU */
646                     interruptRegParams.corepacConfig.intVecNum      = OSAL_REGINT_INTVEC_EVENT_COMBINER; /* Host Interrupt vector */
647                 #else
648                     interruptRegParams.corepacConfig.intVecNum=(int32_t)ptrCanFdMCB->hwCfg.interruptNum1; /* Host Interrupt vector */
649                     interruptRegParams.corepacConfig.corepacEventNum = (int32_t)ptrCanFdMCB->hwCfg.interruptNum1;
650                 #endif
651                     /* Register interrupts */
652                     Osal_RegisterInterrupt(&interruptRegParams, &ptrCanFdMCB->hwiHandle1);
654                     DebugP_assert (ptrCanFdMCB->hwiHandle1 != NULL);
655                 }
657                 if (configParams->eccConfig.enable == 1U)
658                 {
659                     /* Enable ECC Interrupt */
660                     MCAN_eccEnableIntr(baseAddr, CANFD_MCANECCErrType_SEC, 1U);
661                     MCAN_eccEnableIntr(baseAddr, CANFD_MCANECCErrType_DED, 1U);
662                 }
664                 /* Enable the MCAN interrupts */
665                 MCAN_enableIntr(baseAddr, MCAN_INTR_MASK, 1U);
666                 MCAN_selectIntrLine(baseAddr, MCAN_INTR_MASK, MCAN_INTR_LINE_NUM_0);
667                 MCAN_enableIntrLine(baseAddr, MCAN_INTR_LINE_NUM_0, 1U);
669                 /* Put MCAN in opertional mode */
670                 MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_NORMAL);
672                 /* Wait while MCAN is not in operational mode. TODO add timeout */
673                 do
674                 {
675                 } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_NORMAL);
677                 /* Initialize the datalength to DLC mapping */
678                 ptrCanFdMCB->mcanDataSize[0] = 0;
679                 ptrCanFdMCB->mcanDataSize[1] = 1U;
680                 ptrCanFdMCB->mcanDataSize[2] = 2U;
681                 ptrCanFdMCB->mcanDataSize[3] = 3U;
682                 ptrCanFdMCB->mcanDataSize[4] = 4U;
683                 ptrCanFdMCB->mcanDataSize[5] = 5U;
684                 ptrCanFdMCB->mcanDataSize[6] = 6U;
685                 ptrCanFdMCB->mcanDataSize[7] = 7U;
686                 ptrCanFdMCB->mcanDataSize[8] = 8U;
687                 ptrCanFdMCB->mcanDataSize[9] = 12U;
688                 ptrCanFdMCB->mcanDataSize[10] = 16U;
689                 ptrCanFdMCB->mcanDataSize[11] = 20U;
690                 ptrCanFdMCB->mcanDataSize[12] = 24U;
691                 ptrCanFdMCB->mcanDataSize[13] = 32U;
692                 ptrCanFdMCB->mcanDataSize[14] = 48U;
693                 ptrCanFdMCB->mcanDataSize[15] = 64U;
695                 /* Store the relevant fields from the configuration */
696                 ptrCanFdMCB->appDataCallBack =  configParams->appDataCallBack;
697                 ptrCanFdMCB->appErrCallBack =  configParams->appErrCallBack;
699                 /* Initialize the CAN driver state */
700                 ptrCanFdMCB->state = CANFD_DriverState_STARTED;
701             }
702         }
703     }
704     return (CANFD_Handle)ptrCanFdMCB;
707 /**
708  *  @b Description
709  *  @n
710  *      Function closes the CANFD driver instance and cleanups all the memory allocated by the CANFD driver.
711  *
712  *  @param[in]  handle
713  *      Handle to the CANFD Driver
714  *  @param[out]  errCode
715  *      Error code populated on error
716  *
717  *  @retval
718  *      Success     - 0
719  *  @retval
720  *      Error       - <0
721  */
722 int32_t CANFD_deinit(CANFD_Handle handle, int32_t* errCode)
724     CANFD_DriverMCB*      ptrCanFdMCB;
725     uint32_t            index;
726     int32_t             retVal = 0;
728     /* Get the pointer to the CAN Driver Block */
729     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
730     if (ptrCanFdMCB == NULL)
731     {
732         *errCode = CANFD_EINVAL;
733         retVal = MINUS_ONE;
734     }
735     else
736     {
737         /* Update the driver state */
738         ptrCanFdMCB->state = CANFD_DriverState_STOPPED;
740         /* Clean up interrupt handlers */
741         if (ptrCanFdMCB->hwiHandle0)
742         {
743             /* Delete and unregister the interrupt0 handler. */
744             Osal_DeleteInterrupt(ptrCanFdMCB->hwiHandle0, ptrCanFdMCB->hwCfg.interruptNum0);
745         }
746         if (ptrCanFdMCB->hwiHandle1)
747         {
748             /* Delete and unregister the interrupt1 handler. */
749             Osal_DeleteInterrupt(ptrCanFdMCB->hwiHandle1, ptrCanFdMCB->hwCfg.interruptNum1);
750         }
752         /* Delete the message objects */
753         for (index = 0; index < MCAN_MAX_MSG_OBJECTS; index++)
754         {
755             if (ptrCanFdMCB->msgObjectHandle[index] != NULL)
756             {
757                 MemoryP_ctrlFree (ptrCanFdMCB->msgObjectHandle[index], sizeof(CANFD_MessageObject));
758                 ptrCanFdMCB->msgObjectHandle[index] = NULL;
759             }
760         }
761     }
762     return retVal;
765 /**
766  *  @b Description
767  *  @n
768  *      Function configures the bit time parameters for the CANFD module.
769  *
770  *  @param[in]  handle
771  *      Handle to the CANFD Driver
772  *  @param[in]  bitTimeParams
773  *      Bit time configuration parameters
774  *  @param[out]  errCode
775  *      Error code populated on error
776  *
777  *  @retval
778  *      Success     - 0
779  *  @retval
780  *      Error       - <0
781  */
782 int32_t CANFD_configBitTime(CANFD_Handle handle, const CANFD_MCANBitTimingParams* bitTimeParams, int32_t* errCode)
784     CANFD_DriverMCB*        ptrCanFdMCB;
785     MCAN_BitTimingParams    mcanBitTimingParams;
786     uint32_t                baseAddr;
787     int32_t                 retVal = 0;
789     /* Get the pointer to the CANFD Driver Block */
790     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
791     if ((ptrCanFdMCB == NULL) || (bitTimeParams == NULL))
792     {
793         *errCode = CANFD_EINVAL;
794         retVal = MINUS_ONE;
795     }
796     else
797     {
798         baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
800         /* Put MCAN in SW initialization mode */
801         MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_SW_INIT);
803         /* Wait while MCAN is not in init mode. TODO add timeout */
804         do
805         {
806         } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_SW_INIT);
808         /* Calculate the MCAN bit timing parameters */
809         mcanBitTimingParams.nomRatePrescalar   = bitTimeParams->nomBrp - 1U;
810         mcanBitTimingParams.nomTimeSeg1        = bitTimeParams->nomPropSeg + bitTimeParams->nomPseg1 - 1U;
811         mcanBitTimingParams.nomTimeSeg2        = bitTimeParams->nomPseg2 - 1U;
812         mcanBitTimingParams.nomSynchJumpWidth  = bitTimeParams->nomSjw - 1U;
814         mcanBitTimingParams.dataRatePrescalar  = bitTimeParams->dataBrp - 1U;
815         mcanBitTimingParams.dataTimeSeg1       = bitTimeParams->dataPropSeg + bitTimeParams->dataPseg1 - 1U;
816         mcanBitTimingParams.dataTimeSeg2       = bitTimeParams->dataPseg2 - 1U;
817         mcanBitTimingParams.dataSynchJumpWidth = bitTimeParams->dataSjw - 1U;
819         /* Set the bit timing values */
820         *errCode = MCAN_setBitTime(baseAddr, &mcanBitTimingParams);
821         if (*errCode != CANFD_EOK)
822         {
823             retVal = MINUS_ONE;
824         }
825         /* Put MCAN in opertional mode */
826         MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_NORMAL);
828         /* Wait while MCAN is not in operational mode. TODO add timeout */
829         do
830         {
831         } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_NORMAL);
832     }
833     return retVal;
836 /**
837  *  @b Description
838  *  @n
839  *      Function configures the receive or transmit message object.
840  *      It also enables Tx completion and Tx cancelation interrupts.
841  *      The callback function will be invoked on data transmit complete for transmit message objects
842  *      OR
843  *      upon receiving data for receive message objects. The application MUST then call CANFD_getData() API to process the received data.
844  *
845  *  @param[in]  handle
846  *      Handle to the CANFD Driver
847  *  @param[in]  msgObjectParams
848  *      Message Object configuration parameters
849  *  @param[out]  errCode
850  *      Error code populated on error
851  *
852  *  @retval
853  *      Success -   Handle to the message object.
854  *  @retval
855  *      Error   -   NULL
856  */
857 CANFD_MsgObjHandle CANFD_createMsgObject(CANFD_Handle handle, const CANFD_MCANMsgObjCfgParams* msgObjectParams, int32_t* errCode)
859     CANFD_DriverMCB*            ptrCanFdMCB;
860     uint32_t                    baseAddr;
861     CANFD_MessageObject*        ptrCanMsgObj;
862     MCAN_StdMsgIDFilterElement  stdMsgIdFilter;
863     MCAN_ExtMsgIDFilterElement  extMsgIdFilter;
864     uint32_t                    i;
866     /* Get the pointer to the CAN Driver Block */
867     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
868     if ((ptrCanFdMCB == NULL) || (msgObjectParams == NULL))
869     {
870         *errCode = CANFD_EINVAL;
871         ptrCanMsgObj =  NULL;
872     }
873     else
874     {
875         *errCode = CANFD_EOK;
876         baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
878         /* Allocate memory for the CAN Message Object */
879         ptrCanMsgObj = MemoryP_ctrlAlloc (sizeof(CANFD_MessageObject), 0U);
880         if (ptrCanMsgObj == NULL)
881         {
882             /* Error: Unable to allocate the memory */
883             *errCode = CANFD_ENOMEM;
884             ptrCanMsgObj = NULL;
885         }
886         else
887         {
888             /* Initialize the allocated memory */
889             memset ((void *)ptrCanMsgObj, 0, sizeof(CANFD_MessageObject));
891             /* Save the specified parameters */
892             ptrCanMsgObj->ptrDriverMCB = ptrCanFdMCB;
893             ptrCanMsgObj->direction = msgObjectParams->direction;
894             ptrCanMsgObj->msgIdType = msgObjectParams->msgIdType;
895             ptrCanMsgObj->startMsgId = ptrCanMsgObj->endMsgId = msgObjectParams->msgIdentifier;
897             for (i = 0; i < MCAN_MAX_MSG_OBJECTS; i++)
898             {
899                 if (ptrCanFdMCB->msgObjectHandle[i] == NULL)
900                 {
901                     break;
902                 }
903             }
904             if (i == MCAN_MAX_MSG_OBJECTS)
905             {
906                 /* Error: Unable to allocate the memory */
907                 *errCode = CANFD_ENOMEM;
908                 MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
909                 ptrCanMsgObj = NULL;
910             }
911             else
912             {
913                 /* Store the message object handle for book keeping */
914                 ptrCanMsgObj->messageObjNum = i;
915                 ptrCanFdMCB->msgObjectHandle[i] = ptrCanMsgObj;
916             }
918             /* Configure the Tx Message Id */
919             if ((*errCode == CANFD_EOK) && (ptrCanMsgObj->direction == CANFD_Direction_TX))
920             {
921                 /* Get a free Tx element */
922                 for (i = 0; i < MCAN_MAX_TX_MSG_OBJECTS; i++)
923                 {
924                     if (ptrCanFdMCB->txMapping[i] == NULL)
925                     {
926                         break;
927                     }
928                 }
929                 if (i == MCAN_MAX_TX_MSG_OBJECTS)
930                 {
931                     /* Error: Unable to allocate the memory */
932                     *errCode = CANFD_ENOMEM;
933                     ptrCanFdMCB->msgObjectHandle[ptrCanMsgObj->messageObjNum] = NULL;
934                     MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
935                     ptrCanMsgObj = NULL;
936                 }
937                 else
938                 {
939                     /* Store the tx to message object handle mapping */
940                     ptrCanFdMCB->txMapping[i] = ptrCanMsgObj;
941                     ptrCanMsgObj->txElement = i;
943                     /* Store the message RAM memory access type */
944                     ptrCanMsgObj->memType = MCAN_MEM_TYPE_BUF;
946                     /* Enable Tx completion interrupt*/
947                     MCAN_txBufTransIntrEnable(baseAddr, i, 1U);
949                     /* Enable Tx cancelation interrupt*/
950                     MCAN_getTxBufCancellationIntrEnable(baseAddr, i, 1U);
951                 }
952             }
954             /* Configure the Rx Message Id */
955             if ((*errCode == CANFD_EOK) && (ptrCanMsgObj->direction == CANFD_Direction_RX))
956             {
957                 /* Get a free Rx element */
958                 for (i = 0; i < MCAN_MAX_RX_MSG_OBJECTS; i++)
959                 {
960                     if (ptrCanFdMCB->rxMapping[i] == NULL)
961                     {
962                         break;
963                     }
964                 }
965                 if (i == MCAN_MAX_RX_MSG_OBJECTS)
966                 {
967                     /* Error: Unable to allocate the memory */
968                     *errCode = CANFD_ENOMEM;
969                     ptrCanFdMCB->msgObjectHandle[ptrCanMsgObj->messageObjNum] = NULL;
970                     MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
971                     ptrCanMsgObj = NULL;
972                 }
973                 else
974                 {
975                     /* Store the rx to message object handle mapping */
976                     ptrCanFdMCB->rxMapping[i] = ptrCanMsgObj;
977                     ptrCanMsgObj->rxElement = i;
979                     /* Store the message RAM memory access type */
980                     ptrCanMsgObj->memType = MCAN_MEM_TYPE_BUF;
982                     /* Add the filter to message RAM */
983                     if (ptrCanMsgObj->msgIdType == CANFD_MCANXidType_11_BIT)
984                     {
985                         stdMsgIdFilter.sfid1 = ptrCanMsgObj->startMsgId & STD_MSGID_MASK;
986                         stdMsgIdFilter.sfid2 = i;
988                         /* Store the message in rx buffer */
989                         stdMsgIdFilter.sfec = 0x7U;
990                         stdMsgIdFilter.sft = 0;
991                         MCAN_addStdMsgIDFilter(baseAddr, i, &stdMsgIdFilter);
992                     }
993                     else
994                     {
995                         extMsgIdFilter.efid1 = ptrCanMsgObj->startMsgId & XTD_MSGID_MASK;
996                         extMsgIdFilter.efid2 = i;
998                         /* Store the message in rx buffer */
999                         extMsgIdFilter.efec = 0x7U;
1000                         extMsgIdFilter.eft = 0;
1001                         MCAN_addExtMsgIDFilter(baseAddr, i, &extMsgIdFilter);
1002                     }
1003                 }
1004             }
1005         }
1006     }
1007     return (CANFD_MsgObjHandle)ptrCanMsgObj;
1010 /**
1011  *  @b Description
1012  *  @n
1013  *      Function configures a receive message objects for a range of message Identifiersmessage object.
1014  *      It also enables Rx interrupts.
1015  *      The callback function will be invoked upon receiving data for receive message objects.
1016  *      The application MUST then call CANFD_getData() API to process the received data.
1017  *
1018  *  @param[in]  handle
1019  *      Handle to the CANFD Driver
1020  *  @param[in]  msgObjectParams
1021  *      Message Object configuration parameters
1022  *  @param[out]  errCode
1023  *      Error code populated on error
1024  *
1025  *  @retval
1026  *      Success -   Handle to the message object.
1027  *  @retval
1028  *      Error   -   NULL
1029  */
1030 CANFD_MsgObjHandle CANFD_createRxRangeMsgObject(CANFD_Handle handle, const CANFD_MCANRxMsgObjRangeCfgParams* msgObjectParams, int32_t* errCode)
1032     CANFD_DriverMCB*            ptrCanFdMCB;
1033     uint32_t                    baseAddr;
1034     CANFD_MessageObject*        ptrCanMsgObj;
1035     MCAN_StdMsgIDFilterElement  stdMsgIdFilter;
1036     MCAN_ExtMsgIDFilterElement  extMsgIdFilter;
1037     uint32_t                    i;
1039     /* Get the pointer to the CAN Driver Block */
1040     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
1041     if ((ptrCanFdMCB == NULL) || (msgObjectParams == NULL) || (msgObjectParams->startMsgIdentifier > msgObjectParams->endMsgIdentifier))
1042     {
1043         *errCode = CANFD_EINVAL;
1044         ptrCanMsgObj =  NULL;
1045     }
1046     else
1047     {
1048         *errCode = CANFD_EOK;
1049         baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1051         /* Allocate memory for the CAN Message Object */
1052         ptrCanMsgObj = MemoryP_ctrlAlloc (sizeof(CANFD_MessageObject), 0U);
1053         if (ptrCanMsgObj == NULL)
1054         {
1055             /* Error: Unable to allocate the memory */
1056             *errCode = CANFD_ENOMEM;
1057             ptrCanMsgObj = NULL;
1058         }
1059         else
1060         {
1061             /* Initialize the allocated memory */
1062             memset ((void *)ptrCanMsgObj, 0, sizeof(CANFD_MessageObject));
1064             /* Save the specified parameters */
1065             ptrCanMsgObj->ptrDriverMCB = ptrCanFdMCB;
1066             ptrCanMsgObj->direction = CANFD_Direction_RX;
1067             ptrCanMsgObj->msgIdType = msgObjectParams->msgIdType;
1068             ptrCanMsgObj->startMsgId = msgObjectParams->startMsgIdentifier;
1069             ptrCanMsgObj->endMsgId = msgObjectParams->endMsgIdentifier;
1071             for (i = 0; i < MCAN_MAX_MSG_OBJECTS; i++)
1072             {
1073                 if (ptrCanFdMCB->msgObjectHandle[i] == NULL)
1074                 {
1075                     break;
1076                 }
1077             }
1078             if (i == MCAN_MAX_MSG_OBJECTS)
1079             {
1080                 /* Error: Unable to allocate the memory */
1081                 *errCode = CANFD_ENOMEM;
1082                 MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
1083                 ptrCanMsgObj = NULL;
1084             }
1085             else
1086             {
1087                 /* Store the message object handle for book keeping */
1088                 ptrCanMsgObj->messageObjNum = i;
1089                 ptrCanFdMCB->msgObjectHandle[i] = ptrCanMsgObj;
1090             }
1092             /* Configure the Rx Message Id */
1093             if (*errCode == CANFD_EOK)
1094             {
1095                 /* Get a free Rx element */
1096                 for (i = 0; i < MCAN_MAX_RX_MSG_OBJECTS; i++)
1097                 {
1098                     if (ptrCanFdMCB->rxMapping[i] == NULL)
1099                     {
1100                         break;
1101                     }
1102                 }
1103                 if (i == MCAN_MAX_RX_MSG_OBJECTS)
1104                 {
1105                     /* Error: Unable to allocate the memory */
1106                     *errCode = CANFD_ENOMEM;
1107                     ptrCanFdMCB->msgObjectHandle[ptrCanMsgObj->messageObjNum] = NULL;
1108                     MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
1109                     ptrCanMsgObj = NULL;
1110                 }
1111                 else
1112                 {
1113                     /* Store the rx to message object handle mapping */
1114                     ptrCanFdMCB->rxMapping[i] = ptrCanMsgObj;
1115                     ptrCanMsgObj->rxElement = i;
1117                     /* Store the message RAM memory access type */
1118                     ptrCanMsgObj->memType = MCAN_MEM_TYPE_FIFO;
1120                     /* Add the filter to message RAM */
1121                     if (ptrCanMsgObj->msgIdType == CANFD_MCANXidType_11_BIT)
1122                     {
1123                         stdMsgIdFilter.sfid1 = ptrCanMsgObj->startMsgId & STD_MSGID_MASK;
1124                         stdMsgIdFilter.sfid2 = ptrCanMsgObj->endMsgId & STD_MSGID_MASK;
1126                         /* Store the message in FIFO */
1127                         stdMsgIdFilter.sfec = (ptrCanFdMCB->useFifoNum + 1U);
1128                         stdMsgIdFilter.sft = 0;
1129                         MCAN_addStdMsgIDFilter(baseAddr, i, &stdMsgIdFilter);
1130                     }
1131                     else
1132                     {
1133                         extMsgIdFilter.efid1 = ptrCanMsgObj->startMsgId & XTD_MSGID_MASK;
1134                         extMsgIdFilter.efid2 = ptrCanMsgObj->endMsgId & XTD_MSGID_MASK;
1136                         /* Store the message in FIFO */
1137                         extMsgIdFilter.efec = (ptrCanFdMCB->useFifoNum + 1U);
1138                         extMsgIdFilter.eft = 0;
1139                         MCAN_addExtMsgIDFilter(baseAddr, i, &extMsgIdFilter);
1140                     }
1142                     /* Toggle the FIFO number for the next message Id */
1143                     ptrCanFdMCB->useFifoNum = 1U - ptrCanFdMCB->useFifoNum;
1144                 }
1145             }
1146         }
1147     }
1148     return (CANFD_MsgObjHandle)ptrCanMsgObj;
1151 /**
1152  *  @b Description
1153  *  @n
1154  *      Function deletes a message object.
1155  *
1156  *  @param[in]  handle
1157  *      Handle to the message object
1158  *  @param[out]  errCode
1159  *      Error code populated on error
1160  *
1161  *  @retval
1162  *      Success     - 0
1163  *  @retval
1164  *      Error       - <0
1165  */
1166 int32_t CANFD_deleteMsgObject(CANFD_MsgObjHandle handle, int32_t* errCode)
1168     CANFD_MessageObject*  ptrCanMsgObj;
1169     CANFD_DriverMCB*      ptrCanFdMCB;
1170     int32_t             retVal = 0;
1172     ptrCanMsgObj = (CANFD_MessageObject*)handle;
1173     if (ptrCanMsgObj == NULL)
1174     {
1175         *errCode = CANFD_EINVAL;
1176         retVal = MINUS_ONE;
1177     }
1178     else
1179     {
1180         /* Get the pointer to the CAN Driver Block */
1181         ptrCanFdMCB = (CANFD_DriverMCB*)ptrCanMsgObj->ptrDriverMCB;
1183         if (ptrCanFdMCB == NULL)
1184         {
1185             /* This should never happen */
1186             DebugP_assert(0);
1187             retVal = MINUS_ONE;
1188         }
1189         else
1190         {
1191             ptrCanFdMCB->msgObjectHandle[ptrCanMsgObj->messageObjNum] = NULL;
1193             if (ptrCanMsgObj->direction == CANFD_Direction_TX)
1194             {
1195                 ptrCanFdMCB->txMapping[ptrCanMsgObj->txElement] = NULL;
1196             }
1198             if (ptrCanMsgObj->direction == CANFD_Direction_RX)
1199             {
1200                 ptrCanFdMCB->rxMapping[ptrCanMsgObj->rxElement] = NULL;
1201             }
1203             MemoryP_ctrlFree (ptrCanMsgObj, sizeof(CANFD_MessageObject));
1204         }
1205     }
1206     return retVal;
1209 /**
1210  *  @b Description
1211  *  @n
1212  *      Function used by the application to transmit data.
1213  *
1214  *  @param[in]  handle
1215  *      Handle to the message object
1216  *  @param[in]  id
1217  *      Message Identifier
1218  *  @param[in]  frameType
1219  *      Frame type - Classic or FD
1220  *  @param[in]  dataLength
1221  *      Data Length to be transmitted.
1222  *      Valid values: 1 to 64 bytes.
1223  *  @param[in]  data
1224  *      Data to be transmitted
1225  *  @param[out]  errCode
1226  *      Error code populated on error
1227  *
1228  *  @retval
1229  *      Success     - 0
1230  *  @retval
1231  *      Error       - <0
1232  */
1233 int32_t CANFD_transmitData(CANFD_MsgObjHandle handle, uint32_t id, CANFD_MCANFrameType frameType, uint32_t dataLength, const uint8_t* data, int32_t* errCode)
1235     CANFD_MessageObject*    ptrCanMsgObj;
1236     CANFD_DriverMCB*        ptrCanFdMCB;
1237     int32_t                 retVal = 0;
1238     uint32_t                baseAddr;
1239     MCAN_TxBufElement       txBuffElem;
1240     uint32_t                index;
1241     uintptr_t               key;
1242     uint8_t                 padSize = 0U;
1244     /* Get the message object pointer */
1245     ptrCanMsgObj = (CANFD_MessageObject*)handle;
1246     if ((ptrCanMsgObj == NULL) || (data == NULL) || (dataLength < 1U) || (dataLength > 64U))
1247     {
1248         *errCode = CANFD_EINVAL;
1249         retVal = MINUS_ONE;
1250     }
1251     else
1252     {
1253         /* Get the pointer to the CAN Driver Block */
1254         ptrCanFdMCB = (CANFD_DriverMCB*)ptrCanMsgObj->ptrDriverMCB;
1256         if (ptrCanFdMCB == NULL)
1257         {
1258             *errCode = CANFD_EINVAL;
1259             retVal = MINUS_ONE;
1260         }
1261         else
1262         {
1263             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1265             /* Check for pending messages */
1266             index = (uint32_t)1U << ptrCanMsgObj->txElement;
1267             if (index == (MCAN_getTxBufReqPend(baseAddr) & index))
1268             {
1269                 *errCode = CANFD_EINUSE;
1270                 retVal = MINUS_ONE;
1271             }
1272             else
1273             {
1274                 /* populate the Tx buffer message element */
1275                 txBuffElem.rtr = 0;
1276                 txBuffElem.esi = 0;
1277                 txBuffElem.efc = 0;
1278                 txBuffElem.mm = 0;
1280                 if(frameType == CANFD_MCANFrameType_CLASSIC)
1281                 {
1282                     txBuffElem.brs = 0;
1283                     txBuffElem.fdf = 0;
1284                 }
1285                 else
1286                 {
1287                     txBuffElem.brs = 1U;
1288                     txBuffElem.fdf = 1U;
1289                 }
1290                 /* Populate the Id */
1291                 if (ptrCanMsgObj->msgIdType == CANFD_MCANXidType_11_BIT)
1292                 {
1293                     txBuffElem.xtd = CANFD_MCANXidType_11_BIT;
1294                     txBuffElem.id = (id & STD_MSGID_MASK) << STD_MSGID_SHIFT;
1295                 }
1296                 else
1297                 {
1298                     txBuffElem.xtd = CANFD_MCANXidType_29_BIT;
1299                     txBuffElem.id = id & XTD_MSGID_MASK;
1300                 }
1302                 /* Copy the data */
1303                 memcpy ((void*)&txBuffElem.data, data, dataLength);
1305                 /* Compute the DLC value */
1306                 for(index = 0U ; index < 16U ; index++)
1307                 {
1308                     if(dataLength <= ptrCanFdMCB->mcanDataSize[index])
1309                     {
1310                         txBuffElem.dlc = index;
1311                         padSize = ptrCanFdMCB->mcanDataSize[index] - dataLength;
1312                         break;
1313                     }
1314                 }
1315                 txBuffElem.dlc = index;
1316                 if (index == 16)
1317                 {
1318                     *errCode = CANFD_EINVAL;
1319                     retVal = MINUS_ONE;
1320                 }
1321                 else
1322                 {
1323                     /* Pad the unused data in payload */
1324                     index = dataLength;
1325                     while (padSize != 0)
1326                     {
1327                         txBuffElem.data[index++] = (uint8_t)0xCCU;
1328                         padSize--;
1329                     }
1331                     MCAN_writeMsgRam(baseAddr, MCAN_MEM_TYPE_BUF, ptrCanMsgObj->txElement, &txBuffElem);
1333                     /* Critical Section Protection */
1334                     key = HwiP_disable();
1336                     MCAN_txBufAddReq(baseAddr, ptrCanMsgObj->txElement);
1337                     ptrCanFdMCB->txStatus[ptrCanMsgObj->txElement] = 1;
1339                     /* Release the critical section: */
1340                     HwiP_restore(key);
1342                     /* Increment the stats */
1343                     ptrCanMsgObj->messageProcessed++;
1344                 }
1345             }
1346         }
1347     }
1348     return retVal;
1351 /**
1352  *  @b Description
1353  *  @n
1354  *      Function used by the application to cancel a pending data transmit.
1355  *
1356  *  @param[in]  handle
1357  *      Handle to the message object
1358  *  @param[out]  errCode
1359  *      Error code populated on error
1360  *
1361  *  @retval
1362  *      Success     - 0
1363  *  @retval
1364  *      Error       - <0
1365  */
1366 int32_t CANFD_transmitDataCancel(CANFD_MsgObjHandle handle, int32_t* errCode)
1368     CANFD_MessageObject*    ptrCanMsgObj;
1369     CANFD_DriverMCB*        ptrCanFdMCB;
1370     int32_t                 retVal = 0;
1371     uint32_t                baseAddr;
1373     /* Get the message object pointer */
1374     ptrCanMsgObj = (CANFD_MessageObject*)handle;
1375     if (ptrCanMsgObj == NULL)
1376     {
1377         *errCode = CANFD_EINVAL;
1378         retVal = MINUS_ONE;
1379     }
1380     else
1381     {
1382         /* Get the pointer to the CAN Driver Block */
1383         ptrCanFdMCB = (CANFD_DriverMCB*)ptrCanMsgObj->ptrDriverMCB;
1385         if (ptrCanFdMCB == NULL)
1386         {
1387             *errCode = CANFD_EINVAL;
1388             retVal = MINUS_ONE;
1389         }
1390         else
1391         {
1392             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1394             /* Cancel the pending transmit */
1395             MCAN_txBufCancellationReq(baseAddr, ptrCanMsgObj->txElement);
1396         }
1397     }
1398     return retVal;
1401 /**
1402  *  @b Description
1403  *  @n
1404  *      Function is used by the application to get the CAN message from message RAM using a receive message object.
1405  *      NOTE: This API must ONLY be called from the callback context.
1406  *
1407  *  @param[in]  handle
1408  *      Handle to the message object
1409  *  @param[out]  id
1410  *      Message Identifier
1411  *  @param[out]  ptrFrameType
1412  *      Frame type - Classic or FD
1413  *  @param[out]  idType
1414  *      Meassage Id type - 11 bit standard or 29 bit extended
1415  *  @param[out]  ptrDataLength
1416  *      Data Length of the received frame.
1417  *      Valid values: 1 to 64 bytes.
1418  *  @param[out]  data
1419  *      Received data.
1420  *  @param[out]  errCode
1421  *      Error code populated on error
1422  *
1423  *  @retval
1424  *      Success     - 0
1425  *  @retval
1426  *      Error       - <0
1427  */
1428 int32_t CANFD_getData(CANFD_MsgObjHandle handle, uint32_t* id, CANFD_MCANFrameType* ptrFrameType, CANFD_MCANXidType* idType, uint32_t* ptrDataLength, uint8_t* data, int32_t* errCode)
1430     CANFD_MessageObject*    ptrCanMsgObj;
1431     CANFD_DriverMCB*        ptrCanFdMCB;
1432     int32_t                 retVal = 0;
1434     /* Get the message object pointer */
1435     ptrCanMsgObj = (CANFD_MessageObject*)handle;
1436     if ((ptrCanMsgObj == NULL) || (id == NULL) || (ptrDataLength == NULL) || (data == NULL))
1437     {
1438         *errCode = CANFD_EINVAL;
1439         retVal = MINUS_ONE;
1440     }
1441     else
1442     {
1443         /* Get the pointer to the CAN Driver Block */
1444         ptrCanFdMCB = (CANFD_DriverMCB*)ptrCanMsgObj->ptrDriverMCB;
1446         if (ptrCanFdMCB == NULL)
1447         {
1448             *errCode = CANFD_EINVAL;
1449             retVal = MINUS_ONE;
1450         }
1451         else
1452         {
1453             /* Get the data length from DLC */
1454             *ptrDataLength = ptrCanFdMCB->mcanDataSize[ptrCanFdMCB->rxBuffElem.dlc];
1456             /* Get the message Identifier */
1457             if(ptrCanFdMCB->rxBuffElem.xtd == 1U)
1458             {
1459                 /* Received frame with Extended ID */
1460                 *id = (uint32_t)(ptrCanFdMCB->rxBuffElem.id);
1461                 *idType = CANFD_MCANXidType_29_BIT;
1462             }
1463             else
1464             {
1465                 /* Received frame with Standard ID */
1466                 *id = (uint32_t)((ptrCanFdMCB->rxBuffElem.id >> 18U) & 0x7FFU);
1467                 *idType = CANFD_MCANXidType_11_BIT;
1468             }
1470             /* Get the frame type */
1471             if(ptrCanFdMCB->rxBuffElem.fdf == 1U)
1472             {
1473                 /* FD frame Received */
1474                 *ptrFrameType = CANFD_MCANFrameType_FD;
1475             }
1476             else
1477             {
1478                 /* Classic frame Received */
1479                 *ptrFrameType = CANFD_MCANFrameType_CLASSIC;
1480             }
1482             /* Copy the data */
1483             memcpy ((void *)data, ptrCanFdMCB->rxBuffElem.data, *ptrDataLength);
1485             /* Increment the stats */
1486             ptrCanMsgObj->messageProcessed++;
1487         }
1488     }
1489     return retVal;
1492 /**
1493  *  @b Description
1494  *  @n
1495  *      Function is used by the application to get the error and status information from the driver.
1496  *
1497  *  @param[in]  handle
1498  *      Handle to the CAN Driver
1499  *  @param[out] ptrOptInfo
1500  *      Option info in TLV format which is populated with the requested information
1501  *  @param[out]  errCode
1502  *      Error code populated on error
1503  *
1504  *  @retval
1505  *      Success     - 0
1506  *  @retval
1507  *      Error       - <0
1508  */
1509 int32_t CANFD_getOptions(CANFD_Handle handle, const CANFD_OptionTLV* ptrOptInfo, int32_t* errCode)
1512     CANFD_DriverMCB*            ptrCanFdMCB;
1513     CANFD_MessageObject*        ptrCanMsgObj;
1514     CANFD_MCANErrCntStatus*     ptrErrCounter;
1515     CANFD_MCANProtocolStatus*   ptrProtoStatus;
1516     CANFD_MCANMsgObjectStats*   ptrMsgObjectStats;
1517     int32_t                     retVal = 0;
1518     MCAN_ErrCntStatus           cslErrStatus;
1519     MCAN_ProtocolStatus         cslProtocolStatus;
1521     /* Get the pointer to the CAN Driver Block */
1522     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
1523     if ((ptrCanFdMCB == NULL) || (ptrOptInfo == NULL))
1524     {
1525         *errCode = CANFD_EINVAL;
1526         retVal = MINUS_ONE;
1527     }
1528     else
1529     {
1530         /* Process the supported options */
1531         switch (ptrOptInfo->type)
1532         {
1533             case CANFD_Option_MCAN_ERROR_COUNTER:
1534             {
1535                 /* Sanity Check: Validate the arguments. */
1536                 if (ptrOptInfo->length != sizeof(CANFD_MCANErrCntStatus))
1537                 {
1538                     *errCode = CANFD_EINVAL;
1539                     retVal = MINUS_ONE;
1540                     goto endGetOptions;
1541                 }
1543                 ptrErrCounter = (CANFD_MCANErrCntStatus*) ptrOptInfo->value;
1544                 if (ptrErrCounter == NULL)
1545                 {
1546                     *errCode = CANFD_EINVAL;
1547                     retVal = MINUS_ONE;
1548                     goto endGetOptions;
1549                 }
1551                 /* Populate the stats */
1552                 MCAN_getErrCounters (ptrCanFdMCB->hwCfg.regBaseAddress, &cslErrStatus);
1553                 ptrErrCounter->canErrLogCnt = cslErrStatus.canErrLogCnt;
1554                 ptrErrCounter->recErrCnt    = cslErrStatus.recErrCnt;
1555                 ptrErrCounter->rpStatus     = cslErrStatus.rpStatus;
1556                 ptrErrCounter->transErrLogCnt = cslErrStatus.transErrLogCnt;
1557                 break;
1558             }
1559             case CANFD_Option_MCAN_PROTOCOL_STATUS:
1560             {
1561                 /* Sanity Check: Validate the arguments. */
1562                 if (ptrOptInfo->length != sizeof(CANFD_MCANProtocolStatus))
1563                 {
1564                     *errCode = CANFD_EINVAL;
1565                     retVal = MINUS_ONE;
1566                     goto endGetOptions;
1567                 }
1569                 ptrProtoStatus = (CANFD_MCANProtocolStatus*) ptrOptInfo->value;
1570                 if (ptrProtoStatus == NULL)
1571                 {
1572                     *errCode = CANFD_EINVAL;
1573                     retVal = MINUS_ONE;
1574                     goto endGetOptions;
1575                 }
1577                 /* Populate the stats */
1578                 MCAN_getProtocolStatus (ptrCanFdMCB->hwCfg.regBaseAddress, &cslProtocolStatus);
1579                 ptrProtoStatus->act           = cslProtocolStatus.act;
1580                 ptrProtoStatus->busOffStatus  = cslProtocolStatus.busOffStatus;
1581                 ptrProtoStatus->dlec          = cslProtocolStatus.dlec;
1582                 ptrProtoStatus->errPassive    = cslProtocolStatus.errPassive;
1583                 ptrProtoStatus->lastErrCode   = cslProtocolStatus.lastErrCode;
1584                 ptrProtoStatus->pxe           = cslProtocolStatus.pxe;
1585                 ptrProtoStatus->rbrs          = cslProtocolStatus.rbrs;
1586                 ptrProtoStatus->resi          = cslProtocolStatus.resi;
1587                 ptrProtoStatus->rfdf          = cslProtocolStatus.rfdf;
1588                 ptrProtoStatus->tdcv          = cslProtocolStatus.tdcv;
1589                 ptrProtoStatus->warningStatus = cslProtocolStatus.warningStatus;
1590                 break;
1591             }
1592             case CANFD_Option_MCAN_MSG_OBJECT_STATS:
1593             {
1594                 /* Sanity Check: Validate the arguments. */
1595                 if (ptrOptInfo->length != sizeof(CANFD_MCANMsgObjectStats))
1596                 {
1597                     *errCode = CANFD_EINVAL;
1598                     retVal = MINUS_ONE;
1599                     goto endGetOptions;
1600                 }
1602                 ptrMsgObjectStats = (CANFD_MCANMsgObjectStats*) ptrOptInfo->value;
1603                 if (ptrMsgObjectStats == NULL)
1604                 {
1605                     *errCode = CANFD_EINVAL;
1606                     retVal = MINUS_ONE;
1607                     goto endGetOptions;
1608                 }
1610                 ptrCanMsgObj = (CANFD_MessageObject*) ptrMsgObjectStats->handle;
1611                 if (ptrCanMsgObj == NULL)
1612                 {
1613                     *errCode = CANFD_EINVAL;
1614                     retVal = MINUS_ONE;
1615                     goto endGetOptions;
1616                 }
1618                 /* Populate the stats */
1619                 ptrMsgObjectStats->startMsgIdentifier = ptrCanMsgObj->startMsgId;
1620                 ptrMsgObjectStats->endMsgIdentifier = ptrCanMsgObj->endMsgId;
1621                 ptrMsgObjectStats->direction = ptrCanMsgObj->direction;
1622                 ptrMsgObjectStats->interruptsRxed = ptrCanMsgObj->interruptsRxed;
1623                 ptrMsgObjectStats->messageProcessed = ptrCanMsgObj->messageProcessed;
1624                 break;
1625             }
1626             default:
1627             {
1628                 /* Option is NOT supported */
1629                 *errCode = CANFD_EINVAL;
1630                 retVal = MINUS_ONE;
1631                 break;
1632             }
1633         }
1634     }
1636 endGetOptions:
1637     return retVal;
1640 /**
1641  *  @b Description
1642  *  @n
1643  *      Function is used by the application to configure the driver options.
1644  *
1645  *  @param[in]  handle
1646  *      Handle to the CANFD Driver
1647  *  @param[in] ptrOptInfo
1648  *      Option info in TLV format which is used to configure the driver
1649  *  @param[out]  errCode
1650  *      Error code populated on error
1651  *
1652  *  @retval
1653  *      Success     - 0
1654  *  @retval
1655  *      Error       - <0
1656  */
1657 int32_t CANFD_setOptions(CANFD_Handle handle, const CANFD_OptionTLV* ptrOptInfo, int32_t* errCode)
1659     CANFD_DriverMCB*                ptrCanFdMCB;
1660     uint32_t                        baseAddr;
1661     CANFD_MCANLoopbackCfgParams*    ptrMcanLoopBackCfg;
1662     int32_t                         retVal = 0;
1663     /* Get the pointer to the CAN Driver Block */
1664     ptrCanFdMCB = (CANFD_DriverMCB*)handle;
1665     if ((ptrCanFdMCB == NULL) || (ptrOptInfo == NULL))
1666     {
1667         *errCode = CANFD_EINVAL;
1668         retVal = MINUS_ONE;
1669         goto endSetOptions;
1670     }
1672     /* Process the supported options */
1673     switch (ptrOptInfo->type)
1674     {
1675         case CANFD_Option_MCAN_MODE:
1676         {
1677             /* Sanity Check: Validate the arguments. */
1678             if (ptrOptInfo->length != sizeof(uint8_t))
1679             {
1680                 *errCode = CANFD_EINVAL;
1681                 retVal = MINUS_ONE;
1682                 goto endSetOptions;
1683             }
1685             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1687             if ((*(uint8_t*)ptrOptInfo->value == 1U) || (*(uint8_t*)ptrOptInfo->value == 0U))
1688             {
1689                 /* Put MCAN in soecified mode */
1690                 MCAN_setOpMode(baseAddr, (uint32_t)(*(uint8_t*)ptrOptInfo->value));
1692                 /* Wait while MCAN is not in init mode. TODO add timeout */
1693                 do
1694                 {
1695                 } while (MCAN_getOpMode(baseAddr) != *(uint8_t*)ptrOptInfo->value);
1696             }
1697             else
1698             {
1699                 *errCode = CANFD_EINVAL;
1700                 retVal = MINUS_ONE;
1701             }
1702             break;
1703         }
1704         case CANFD_Option_MCAN_LOOPBACK:
1705         {
1706             /* Sanity Check: Validate the arguments. */
1707             if (ptrOptInfo->length != sizeof(CANFD_MCANLoopbackCfgParams))
1708             {
1709                 *errCode = CANFD_EINVAL;
1710                 retVal = MINUS_ONE;
1711                 goto endSetOptions;
1712             }
1714             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1716             ptrMcanLoopBackCfg = (CANFD_MCANLoopbackCfgParams*) ptrOptInfo->value;
1718             /* Put MCAN in SW initialization mode */
1719             MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_SW_INIT);
1721             /* Wait while MCAN is not in init mode. TODO add timeout */
1722             do
1723             {
1724             } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_SW_INIT);
1726             /* Disable loopback mode */
1727             if (ptrMcanLoopBackCfg->enable == 0)
1728             {
1729                 MCAN_lpbkModeEnable(baseAddr, ptrMcanLoopBackCfg->mode, 0U);
1730             }
1731             else
1732             {
1733                 /* Enable loopback mode */
1734                 MCAN_lpbkModeEnable(baseAddr, ptrMcanLoopBackCfg->mode, 1U);
1735             }
1736             /* Put MCAN in opertional mode */
1737             MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_NORMAL);
1739             /* Wait while MCAN is not in operational mode. TODO add timeout */
1740             do
1741             {
1742             } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_NORMAL);
1744             break;
1745         }
1746         case CANFD_Option_MCAN_POWER_DOWN:
1747         {
1748             /* Sanity Check: Validate the arguments. */
1749             if (ptrOptInfo->length != sizeof(uint8_t))
1750             {
1751                 *errCode = CANFD_EINVAL;
1752                 retVal = MINUS_ONE;
1753                 goto endSetOptions;
1754             }
1756             baseAddr = ptrCanFdMCB->hwCfg.regBaseAddress;
1758             if (*(uint8_t*)ptrOptInfo->value == 1U)
1759             {
1760                 /* Request a clock stop to enter local power down */
1761                 MCAN_addClockStopRequest(baseAddr, 1U);
1763                 /* Wait for power down to be successful */
1764                 do
1765                 {
1766                 } while (MCAN_getClkStopAck(baseAddr) != MCAN_CCCR_CSA_ACK);
1768                 /* Update the state information */
1769                 ptrCanFdMCB->state = CANFD_DriverState_SLEEP;
1770             }
1771             else if (*(uint8_t*)ptrOptInfo->value == 0U)
1772             {
1773                 /* Turn on the local clocks to wakeup from local power down */
1774                 MCAN_addClockStopRequest(baseAddr, 0);
1776                 /* Wait for wake up to be successful */
1777                 do
1778                 {
1779                 } while (MCAN_getClkStopAck(baseAddr) != MCAN_CCCR_CSA_NO_ACK);
1781                 /* Put MCAN in opertional mode */
1782                 MCAN_setOpMode(baseAddr, MCAN_OPERATION_MODE_NORMAL);
1784                 /* Wait while MCAN is not in operational mode. TODO add timeout */
1785                 do
1786                 {
1787                 } while (MCAN_getOpMode(baseAddr) != MCAN_OPERATION_MODE_NORMAL);
1789                 /* Update the state information */
1790                 ptrCanFdMCB->state = CANFD_DriverState_STARTED;
1791             }
1792             else
1793             {
1794                 *errCode = CANFD_EINVAL;
1795                 retVal = MINUS_ONE;
1796             }
1797             break;
1798         }
1799         default:
1800         {
1801             /* Option is NOT supported */
1802             *errCode = CANFD_EINVAL;
1803             retVal = MINUS_ONE;
1804             break;
1805         }
1806     }
1807 endSetOptions:
1808     return retVal;