/******************************************************************************
* $Revision: 423 $
* $Date:: 2017-04-07 16:03:30 +0900#$
*****************************************************************************/
/* __DISCLAIMER_START__                                                      */
/******************************************************************************
* (c)2017, Cypress Semiconductor Corporation
* or a subsidiary of Cypress Semiconductor Corporation. All rights
* reserved.
*
* This software, including source code, documentation and related
* materials ( "Software" ), is owned by Cypress Semiconductor
* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by
* and subject to worldwide patent protection (United States and foreign),
* United States copyright laws and international treaty provisions.
* Therefore, you may use this Software only as provided in the license
* agreement accompanying the software package from which you
* obtained this Software ( "EULA" ).
*
* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,
* non-transferable license to copy, modify, and compile the
* Software source code solely for use in connection with Cypress' s
* integrated circuit products. Any reproduction, modification, translation,
* compilation, or representation of this Software except as specified
* above is prohibited without the express written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. Cypress reserves the right to make
* changes to the Software without notice. Cypress does not assume any
* liability arising out of the application or use of the Software or any
* product or circuit described in the Software. Cypress does not
* authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ( "High Risk Product" ). By
* including Cypress' s product in a High Risk Product, the manufacturer
* of such system or application assumes all risk of such use and in doing
* so agrees to indemnify Cypress against all liability.
******************************************************************************/
/* __DISCLAIMER_END__                                                        */
/*****************************************************************************
** \file canfd.c
**
** CAN-FD functions
**
** History:
**   - 2014-06-02  0.01  ST  Initial version for Traveo
**   - 2015-02-25  0.02  ST  Change location of Dedicated Rx Buffer flag clear
**                           Change setting for NDAT and TXBAR
**   - 2015-10-01  0.03  ST  Supports MCAN 3.2
*****************************************************************************/


/*****************************************************************************/
/* Include files                                                             */
/*****************************************************************************/
#include "pdl.h"
#include "abstract.h"
#include "interrupts.h"


#if defined(PDL_PERIPHERAL_CANFD_ACTIVE)

/**
*****************************************************************************
** \addtogroup CanFDGroup CAN with Flexible Data rate (CAN-FD)
**
*****************************************************************************/
//@{
    
    /*****************************************************************************/
    /* Local pre-processor symbols/macros ('#define')                            */
    /*****************************************************************************/
    
    
    /*****************************************************************************/
    /* Global variable definitions (declared in header file with 'extern')       */
    /*****************************************************************************/
    
    
    /*****************************************************************************/
    /* Local type definitions ('typedef')                                        */
    /*****************************************************************************/
    
    
    /*****************************************************************************/
    /* Local variable definitions ('static')                                     */
    /*****************************************************************************/
    /* Error Log area */
    static volatile uint16_t  m_u16LastErrorCode;
    
    
    /*****************************************************************************/
    /* Local function prototypes ('static')                                      */
    /*****************************************************************************/
    static void CanFDIrqHandler( pstc_canfd_type_t pstcCanFD,
                                stc_canfd_intern_data_t* pstcCanFDInternData
                                ) ;
    static void ErrorHandling( pstc_canfd_type_t   pstcCanFD );
    
    
    /*****************************************************************************/
    /* Function implementation - global ('extern') and local ('static')          */
    /*****************************************************************************/
    
#include "canfd_generated.c"
    
    /**
    *****************************************************************************
    ** \brief Message buffer address calculation for reception.
    **
    ** \param [in] pstcCanFD           Pointer to register area of a CAN-FD unit.
    ** \param [in] u8MsgBuf            Message buffer index for reception.(0-63)
    
    ** \retval pulAdrs                 Message buffer address corresponding to the index.
    **                                 Can be 0 if the index is invalid.
    *****************************************************************************/
    static uint32_t* calcRxBufAdrs(pstc_canfd_type_t pstcCanFD,
                                   uint8_t u8MsgBuf)
    {
        uint32_t* pulAdrs;
        
        if (u8MsgBuf > 63)
        {
            /* Set 0 to the return value if the index is invalid */
            pulAdrs = 0;
        }
        else
        {
            /* Set the message buffer address to the return value if the index is available */
            pulAdrs = (uint32_t *)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unRXBC.stcField.u14RBSA + (2 + iDlcInWord[pstcCanFD->unRXESC.stcField.u3RBDS]) * u8MsgBuf;
        }
        return pulAdrs;
    }
    
    
    /**
    *****************************************************************************
    ** \brief Message buffer address calculation for transmission.
    **
    ** \param [in] pstcCanFD           Pointer to register area of a CAN-FD unit.
    ** \param [in] u8MsgBuf            Message buffer index for transmission.(0-31)
    
    ** \retval pulAdrs                 Message buffer address corresponding to the index.
    **                                 Can be 0 if the index is invalid.
    *****************************************************************************/
    static uint32_t* calcTxBufAdrs(pstc_canfd_type_t pstcCanFD,
                                   uint8_t u8MsgBuf)
    {
        uint32_t* pulAdrs;
        
        if ( u8MsgBuf > 31)
        {
            /* Set 0 to the return value if the index is invalid */
            pulAdrs = 0;
        }
        else
        {
            /* Set the message buffer address to the return value if the index is available */
            pulAdrs = (uint32_t *)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unTXBC.stcField.u14TBSA + (2 + iDlcInWord[pstcCanFD->unTXESC.stcField.u3TBDS]) * u8MsgBuf;
        }
        return pulAdrs;
    }
    
    
    /**
    ******************************************************************************
    ** \brief Set error code to log area.
    **
    ** \param [in] pstcCanFD           Pointer to register area of a CAN-FD unit.
    **
    ******************************************************************************/
    void ErrorHandling( pstc_canfd_type_t   pstcCanFD )
    {
        
        /* Access to Reserved Address */
        if ( pstcCanFD->unIR.stcField.u1ARA == 1 )
        {
            m_u16LastErrorCode = 0x0001;
        }
        
        /* Protocol Error in Data Phase */
        if ( pstcCanFD->unIR.stcField.u1PED == 1 )
        {
            m_u16LastErrorCode = 0x0002;
        }
        
        /* Protocol Error in Arbitration Phase */
        if ( pstcCanFD->unIR.stcField.u1PEA == 1 )
        {
            m_u16LastErrorCode = 0x0003;
        }
        
        /* Watchdog Interrupt */
        if ( pstcCanFD->unIR.stcField.u1WDI == 1 )
        {
            m_u16LastErrorCode = 0x0004;
        }
        
        /* Bus_Off Status Interrupt */
        if ( pstcCanFD->unIR.stcField.u1BO == 1 )
        {
            m_u16LastErrorCode = 0x0005;
        }
        
        /* Bit Error Uncorrected Interrupt */
        if ( pstcCanFD->unIR.stcField.u1BEU == 1 )
        {
            m_u16LastErrorCode = 0x0006;
        }
        
        return;
        
    } /* ErrorHandling */
    
    
    /**
    *****************************************************************************
    ** \brief CAN-FD (Status/Error/Rx/Tx) interrupt ISR
    **
    **
    ** \param [in] pstcCanFD             Pointer to register area of a CAN-FD unit.
    ** \param [in] pstcCanFDInternData   Pointer to internal data.
    **
    *****************************************************************************/
    static void CanFDIrqHandler( pstc_canfd_type_t   pstcCanFD,
                                stc_canfd_intern_data_t* pstcCanFDInternData
                                )
    {
        uint32_t*    pulAdrs = 0;
        uint16_t     u16count = 0;
        uint16_t     u16dlcTmp = 0;
        uint16_t     u16MessageBufferNumber ;
        stc_canfd_msg_t stcCanFDmsg;
        
        /* Other than Tx/Rx interrupt occured */
        if ( pstcCanFD->unIR.u32Register & 0x3ff7E0EE )
        {
            ErrorHandling( pstcCanFD );
        }
        
        /* Received a data frame */
        if ( pstcCanFD->unIR.stcField.u1DRX == 1 ) // At least one received message stored into an Rx Buffer.
        {
            /* Clear the Message stored to Dedicated Rx Buffer flag */
            pstcCanFD->unIR.stcField.u1DRX = 1;
            
            // New data is exist
            if (pstcCanFD->unNDAT1.u32Register & 0x00000001ul)      /* Check the message buffer 0 */
            {
                // Message Buffer 0
                u16MessageBufferNumber = 0;
                // Rx Buffer address
                pulAdrs = calcRxBufAdrs( pstcCanFD, 0 );
                // Clear NDAT1 register
                pstcCanFD->unNDAT1.u32Register = 0x00000001ul;
            }
            else if (pstcCanFD->unNDAT1.u32Register & 0x00000002)   /* Check the message buffer 1 */
            {
                // Message Buffer 1
                u16MessageBufferNumber = 1;
                // Rx Buffer address
                pulAdrs = calcRxBufAdrs( pstcCanFD, 1 );
                // Clear NDAT1 register
                pstcCanFD->unNDAT1.u32Register = 0x00000002ul;
            }
            
            if (pulAdrs)
            {
                /* Save received data */
                /* XTD : Extended Identifier */
                stcCanFDmsg.stcIdentifier.bExtended = ((stc_canfd_rx_buffer_t *) pulAdrs)->R0_f.XTD;
                    
                /* ID : RxID */
                if ( stcCanFDmsg.stcIdentifier.bExtended == FALSE )
                {
                    
                    stcCanFDmsg.stcIdentifier.u32Identifier = ((stc_canfd_rx_buffer_t *) pulAdrs)->R0_f.ID >> 18;
                }
                else
                {
                    stcCanFDmsg.stcIdentifier.u32Identifier = ((stc_canfd_rx_buffer_t *) pulAdrs)->R0_f.ID;
                }
                
                /* FDF : Extended Data Length */
                stcCanFDmsg.bCanFDFormat = ((stc_canfd_rx_buffer_t *) pulAdrs)->R1_f.FDF;
                
                /* DLC : Data Length Code */
                stcCanFDmsg.stcData.u8DataLengthCode = ((stc_canfd_rx_buffer_t *) pulAdrs)->R1_f.DLC;
                
                /* Copy 0-64 byte of data area */
                if ( stcCanFDmsg.stcData.u8DataLengthCode < 8 )
                {
                    u16dlcTmp = 0;
                }
                else
                {
                    u16dlcTmp = stcCanFDmsg.stcData.u8DataLengthCode - 8;
                }
                
                for ( u16count = 0; u16count < iDlcInWord[u16dlcTmp]; u16count++ )
                {
                    stcCanFDmsg.stcData.au32Data[u16count] = ((stc_canfd_rx_buffer_t *) pulAdrs)->DATA_AREA_f[u16count];
                }
                
                /* CAN-FD message received, check if there is a callback function */
                /* Call callback function if it was set previously. */
                if (pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDRxInterruptFunction != NULL)
                {
                    pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDRxInterruptFunction((uint8_t)u16MessageBufferNumber, &stcCanFDmsg);
                }
            }
        }
        else if ( pstcCanFD->unIR.stcField.u1TC == 1 ) // Transmission completed.
        {
            /* CAN-FD message succesfully transmitted. */
            /* Call callback function if it was set previously. */
            if (pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDTxInterruptFunction != NULL)
            {
                pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDTxInterruptFunction();
            }
        }
        
        
    } /* CanFDIrqHandler */
    
    
    /**
    *****************************************************************************
    ** \brief Initializes the CAN Prescaler.
    **
    ** This function initialises CAN Prescaler with the parameters
    ** porvided in the given confdig sturcture.
    **
    ** Initialize the CAN Prescaler before calling CanFD_Init().
    ** Call the Can_PrescalerInit() in a state in which the CAN-FD is stopped.(CCCR.Init=1)
    **
    ** \param [in] pstcCanp          Pointer to register area of a CAN Prescaler.
    ** \param [in] u8CanPrescaler    CAN Prescaler parameters.
    ** \param [in] bSelectMainClock  Source clock selection. (TRUE:Main clock, FALSE:PLL clock)
    **
    ** \retval Ok                    CAN Prescaler has been successfully initialized.
    ** \retval ErrorInvalidParameter If one of the following conditions are met:
    **   - pstcCanp == NULL
    *****************************************************************************/
    en_result_t Can_PrescalerInit( volatile stc_canp_t* pstcCanp,
                                  uint8_t u8CanPrescaler,
                                  boolean_t bSelectMainClock
                                  )
    {
        /* Check for NULL pointers */
        if ( pstcCanp    == NULL )
        {
            return ErrorInvalidParameter;
        }
        
        /* Set CAN prescaler */
        pstcCanp->unCTR.stcField.u6CANPRE = u8CanPrescaler;
        while( pstcCanp->unSTR.stcField.u1BUSY == 1 )
        {
        }
        
        /* Select the source clock of CAN Prescaler */
        pstcCanp->unCTR.stcField.u1CPCKS  = (bSelectMainClock == TRUE) ? 1 : 0 ;
        
        return Ok;
        
    } /* Can_PrescalerInit */
    
    
    
    /**
    *****************************************************************************
    ** \brief Initializes the CAN-FD module.
    **
    ** This function initialises one specific CAN-FD module with the parameters
    ** porvided in the given confdig sturcture.
    **
    ** CanFD_Init() has to be called with the parameter pstcConfig of type
    ** stc_canfd_config_t the CAN-FD settings, the CAN baudrate, the CAN-FD baudrate,
    ** and the transmission and reception and the error and status change callback
    ** function can be set.
    **
    ** All values in pstcConfig have to be in valid range. The callback functions
    ** can be NULL. In this case no information will be reported to the API.
    **
    ** \param [in] pstcCanFD         Pointer to register area of a CAN-FD unit.
    ** \param [in] pstcConfig        CAN-FD configuration parameters.
    **
    ** \retval Ok                    CAN-FD module has been successfully initialized.
    ** \retval ErrorInvalidParameter If one of the following conditions are met:
    **   - pstcCanFD == NULL
    **   - pstcConfig == NULL
    **   - pstcCanFDInternData == NULL (invalid or disabled CAN-FD unit)
    *****************************************************************************/
    en_result_t CanFD_Init( pstc_canfd_type_t pstcCanFD, stc_canfd_config_t* pstcConfig )
    {
        stc_canfd_intern_data_t* pstcCanFDInternData;
        stc_id_filter_t*         pstcIdFilter;
        stc_extid_filter_t*      pstcExtIdFilter;
        uint32_t*                pulAdrs;
        uint16_t                 u16count;
        
        /* Shadow data to avoid RMW and speed up HW access */
        un_cpg_canfdn_sidfc_t unSIDFC = { 0 };
        un_cpg_canfdn_xidfc_t unXIDFC = { 0 };
        un_cpg_canfdn_xidam_t unXIDAM = { 0 };
        un_cpg_canfdn_rxf0c_t unRXF0C = { 0 };
        un_cpg_canfdn_rxf1c_t unRXF1C = { 0 };
        un_cpg_canfdn_rxbc_t  unRXBC  = { 0 };
        un_cpg_canfdn_txefc_t unTXEFC = { 0 };
        un_cpg_canfdn_txbc_t  unTXBC  = { 0 };
        un_cpg_canfdn_cccr_t  unCCCR  = { 0 };
        un_cpg_canfdn_nbtp_t  unNBTP  = { 0 };
        un_cpg_canfdn_dbtp_t  unDBTP  = { 0 };
        un_cpg_canfdn_tdcr_t  unTDCR  = { 0 };
        un_cpg_canfdn_gfc_t   unGFC   = { 0 };
        un_cpg_canfdn_rxesc_t unRXESC = { 0 };
        un_cpg_canfdn_txesc_t unTXESC = { 0 };
        un_cpg_canfdn_ie_t    unIE    = { 0 };
        un_cpg_canfdn_ils_t   unILS   = { 0 };
        un_cpg_canfdn_ile_t   unILE   = { 0 };
        
        
        /* Check for NULL pointers */
        if ( pstcCanFD    == NULL ||
            pstcConfig == NULL
            )
        {
            return ErrorInvalidParameter;
        }
        
        /* Get pointer to internal data structure */
        pstcCanFDInternData = CanFDGetInternDataPtr( pstcCanFD ) ;
        
        /* Check for NULL */
        if (pstcCanFDInternData == NULL)
        {
            return ErrorInvalidParameter;
        }
        
        /* Set notification callback functions */
        pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDTxInterruptFunction = pstcConfig->pfnTxCallback;
        pstcCanFDInternData->stcCanFDInterruptHandling.pfnCanFDRxInterruptFunction  = pstcConfig->pfnRxCallback;
        pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDStatusInterruptFunction = pstcConfig->pfnStatusCallback;
        pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDErrorInterruptFunction  = pstcConfig->pfnErrorCallback;
        
        /* Set CCCR.INIT to 1 and wait until it will be updated. */
        unCCCR.stcField.u1INIT = 1;
        pstcCanFD->unCCCR.u32Register = unCCCR.u32Register;
        while ( pstcCanFD->unCCCR.stcField.u1INIT != 1 )
        {
        }
        
        /* Cancel protection */
        unCCCR.stcField.u1CCE = 1;
        pstcCanFD->unCCCR.u32Register = unCCCR.u32Register;
        
        /* Select Normal CAN mode or CAN-FD mode */
        if( pstcConfig->bCanFDMode == FALSE )
        {
            /* Classic CAN mode */
            
            /* Set message RAM area */
            /* Standard ID filter */
            unSIDFC.stcField.u8LSS = 1; /* Number of standard Message ID filter elements = 1 */
            unSIDFC.stcField.u14FLSSA = 0x00000000; /* offset(word) */
            pstcCanFD->unSIDFC.u32Register = unSIDFC.u32Register;
            
            /* Extended ID filter */
            unXIDFC.stcField.u7LSE = 1; /* Number of extended Message ID filter elements = 1 */
            unXIDFC.stcField.u14FLESA = 0x00000004; /* offset(word) */
            pstcCanFD->unXIDFC.u32Register = unXIDFC.u32Register;
            
            unXIDAM.stcField.u29EIDM = 0x1fffffff;	/* not filtering(inituial value) */
            pstcCanFD->unXIDAM.u32Register = unXIDAM.u32Register;
            
            /* Rx FIFO 0 (not use) */
            unRXF0C.stcField.u1F0OM = 0;    /* Rx FIFO 0 blocking mode */
            unRXF0C.stcField.u7F0WM = 0;    /* Watermark interrupt disabled */
            unRXF0C.stcField.u7F0S = 0;     /* FIFO Element Number = 0 */
            unRXF0C.stcField.u14F0SA = 0x00000010; /* offset(word) */
            pstcCanFD->unRXF0C.u32Register = unRXF0C.u32Register;
            
            /* Rx FIFO 1 (not use) */
            unRXF1C.stcField.u1F1OM = 0;    /* Rx FIFO 1 blocking mode */
            unRXF1C.stcField.u7F1WM = 0;    /* Watermark interrupt disabled */
            unRXF1C.stcField.u7F1S = 0;     /* FIFO Element Number = 0 */
            unRXF1C.stcField.u14F1SA = 0x00000020; /* offset(word) */
            pstcCanFD->unRXF1C.u32Register = unRXF1C.u32Register;
            
            /* Rx buffer */
            unRXBC.stcField.u14RBSA = 0x00000030; /* offset(word) */
            pstcCanFD->unRXBC.u32Register = unRXBC.u32Register;
            
            /* Tx FIFO/QUEUE (not use) */
            unTXEFC.stcField.u6EFWM = 0; /* Watermark interrupt disabled. */
            unTXEFC.stcField.u6EFS = 0;  /* Tx Event FIFO disabled. */
            unTXEFC.stcField.u14EFSA = 0x00000080; /* offset(word) */
            pstcCanFD->unTXEFC.u32Register = unTXEFC.u32Register;
            
            /* Tx buffer */
            unTXBC.stcField.u1TFQM = 0;  /* Tx FIFO operation */
            unTXBC.stcField.u6TFQS = 0;  /* No Tx FIFO/Queue */
            unTXBC.stcField.u6NDTB = 1;  /* Number of Dedicated Tx Buffers = 1 */
            unTXBC.stcField.u14TBSA = 0x00000090; /* offset(word) */
            pstcCanFD->unTXBC.u32Register = unTXBC.u32Register;
            
            /* Initialize message RAM area(Entire region zeroing) */
            pulAdrs = (uint32_t *)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET);
            for (u16count = 0; u16count < CANFD0MRWORDS; u16count++)
            {
                *pulAdrs++ = 0ul;
            }
            
            /* Configuration of CAN bus */
            /* CCCR register */
            unCCCR.stcField.u1TXP  = 0; /* Transmit pause disabled. */
            unCCCR.stcField.u1BRSE = 0; /* Bit rate switching for transmissions disabled. */
            unCCCR.stcField.u1FDOE = 0; /* FD operation disabled. */
            unCCCR.stcField.u1TEST = 0; /* Normal operation */
            unCCCR.stcField.u1DAR  = 0; /* Automatic retransmission enabled. */
            unCCCR.stcField.u1MON  = 0; /* Bus Monitoring Mode is disabled. */
            unCCCR.stcField.u1CSR  = 0; /* No clock stop is requested. */
            unCCCR.stcField.u1ASM  = 0; /* Normal CAN operation. */
            pstcCanFD->unCCCR.u32Register  = unCCCR.u32Register;
            
            /* Bit Timing & Prescaler Register */
            unNBTP.stcField.u9NBRP   = pstcConfig->stcBitrate.u16Prescaler;
            unNBTP.stcField.u8NTSEG1 = pstcConfig->stcBitrate.u8TimeSegment1;
            unNBTP.stcField.u7NTSEG2 = pstcConfig->stcBitrate.u8TimeSegment2;
            unNBTP.stcField.u7NSJW   = pstcConfig->stcBitrate.u8SyncJumpWidth;
            pstcCanFD->unNBTP.u32Register  = unNBTP.u32Register;
            
            /* Configuration of Global Filter */
            unGFC.stcField.u2ANFS = 2; /* Reject when unmatch id */
            unGFC.stcField.u2ANFE = 2; /* Reject when unmatch id */
            unGFC.stcField.u1RRFS = 1; /* Reject all remote frame */
            unGFC.stcField.u1RRFE = 1; /* Reject all remote frame */
            pstcCanFD->unGFC.u32Register = unGFC.u32Register;
            
            /* Standard Message ID Filter */
            pstcIdFilter = (stc_id_filter_t*)((uint32_t*)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unSIDFC.stcField.u14FLSSA);
            pstcIdFilter->SFT   = 2;        /* Standard Filter Type : Classic filter */
            pstcIdFilter->SFEC  = 7;        /* Store into dedicated Rx Buffer, configuration of SFT[1:0] ignored. */
            pstcIdFilter->SFID1 = 0x010;    /* Filter ID : 0x10(16) */
            pstcIdFilter->SFID2 = (0 << 9)  /* Store message into a dedicated Rx Buffer */
            | 0;        /* Buffer index : 0 */
            
            /* Extended Message ID Filter */
            pstcExtIdFilter = (stc_extid_filter_t*)((uint32_t*)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unXIDFC.stcField.u14FLESA);
            pstcExtIdFilter->F1_f.EFT   = 2;        /* Extended Filter Type : Classic filter */
            pstcExtIdFilter->F0_f.EFEC  = 7;        /* Store into dedicated Rx Buffer, configuration of EFT[1:0] ignored. */
            pstcExtIdFilter->F0_f.EFID1 = 0x10001;  /* Filter ID : 0x10001(65537) */
            pstcExtIdFilter->F1_f.EFID2 = (0 << 9)  /* Store message into a dedicated Rx Buffer */
            | 1;           /* Buffer index : 1 */
            
            /* Configuration of Rx Buffer and Rx FIFO */
            unRXESC.stcField.u3RBDS = 0; /* 8 byte data field. */
            unRXESC.stcField.u3F1DS = 0; /* FIFO1 8 byte data field. */
            unRXESC.stcField.u3F0DS = 0; /* FIFO0 8 byte data field. */
            pstcCanFD->unRXESC.u32Register = unRXESC.u32Register;
            
            /* Configuration of Tx Buffer and Tx FIFO/Queue */
            unTXESC.stcField.u3TBDS = 0; /* 8 byte data field. */
            pstcCanFD->unTXESC.u32Register = unTXESC.u32Register;
            
        }
        else
        {
            /* FAN-FD mode */
            
            /* Set message RAM area */
            /* Standard ID filter */
            unSIDFC.stcField.u8LSS = 1; /* Number of standard Message ID filter elements = 1 */
            unSIDFC.stcField.u14FLSSA = 0x00000000; /* offset(word) */
            pstcCanFD->unSIDFC.u32Register = unSIDFC.u32Register;
            
            /* Extended ID filter */
            unXIDFC.stcField.u7LSE = 1; /* Number of extended Message ID filter elements = 1 */
            unXIDFC.stcField.u14FLESA = 0x00000004; /* offset(word) */
            pstcCanFD->unXIDFC.u32Register = unXIDFC.u32Register;
            
            unXIDAM.stcField.u29EIDM = 0x1fffffff;	/* not filtering(inituial value) */
            pstcCanFD->unXIDAM.u32Register = unXIDAM.u32Register;
            
            /* Rx FIFO 0 (not use) */
            unRXF0C.stcField.u1F0OM = 0;    /* Rx FIFO 0 blocking mode */
            unRXF0C.stcField.u7F0WM = 0;    /* Watermark interrupt disabled */
            unRXF0C.stcField.u7F0S = 0;     /* FIFO Element Number = 0 */
            unRXF0C.stcField.u14F0SA = 0x00000010; /* offset(word) */
            pstcCanFD->unRXF0C.u32Register = unRXF0C.u32Register;
            
            /* Rx FIFO 1 (not use) */
            unRXF1C.stcField.u1F1OM = 0;    /* Rx FIFO 1 blocking mode */
            unRXF1C.stcField.u7F1WM = 0;    /* Watermark interrupt disabled */
            unRXF1C.stcField.u7F1S = 0;     /* FIFO Element Number = 0 */
            unRXF1C.stcField.u14F1SA = 0x00000020; /* offset(word) */
            pstcCanFD->unRXF1C.u32Register = unRXF1C.u32Register;
            
            /* Rx buffer */
            unRXBC.stcField.u14RBSA = 0x00000030; /* offset(word) */
            pstcCanFD->unRXBC.u32Register = unRXBC.u32Register;
            
            /* Tx FIFO/QUEUE (not use) */
            unTXEFC.stcField.u6EFWM = 0; /* Watermark interrupt disabled. */
            unTXEFC.stcField.u6EFS = 0;  /* Tx Event FIFO disabled. */
            unTXEFC.stcField.u14EFSA = 0x00000100; /* offset(word) */
            pstcCanFD->unTXEFC.u32Register = unTXEFC.u32Register;
            
            /* Tx buffer */
            unTXBC.stcField.u1TFQM = 0;  /* Tx FIFO operation */
            unTXBC.stcField.u6TFQS = 0;  /* No Tx FIFO/Queue */
            unTXBC.stcField.u6NDTB = 1;  /* Number of Dedicated Tx Buffers = 1 */
            unTXBC.stcField.u14TBSA = 0x00000200; /* offset(word) */
            pstcCanFD->unTXBC.u32Register = unTXBC.u32Register;
            
            /* Initialize message RAM area(Entire region zeroing) */
            pulAdrs = (uint32_t *)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET);
            for (u16count = 0; u16count < CANFD0MRWORDS; u16count++)
            {
                *pulAdrs++ = 0ul;
            }
            
            /* Configuration of CAN bus */
            /* CCCR register */
            unCCCR.stcField.u1TXP  = 0; /* Transmit pause disabled. */
            unCCCR.stcField.u1BRSE = 1; /* Bit rate switching for transmissions enabled. */
            unCCCR.stcField.u1FDOE = 1; /* FD operation enabled. */
            unCCCR.stcField.u1TEST = 0; /* Normal operation */
            unCCCR.stcField.u1DAR  = 0; /* Automatic retransmission enabled. */
            unCCCR.stcField.u1MON  = 0; /* Bus Monitoring Mode is disabled. */
            unCCCR.stcField.u1CSR  = 0; /* No clock stop is requested. */
            unCCCR.stcField.u1ASM  = 0; /* Normal CAN operation. */
            pstcCanFD->unCCCR.u32Register  = unCCCR.u32Register;
            
            /* Bit Timing & Prescaler Register */
            unNBTP.stcField.u9NBRP   = pstcConfig->stcBitrate.u16Prescaler;
            unNBTP.stcField.u8NTSEG1 = pstcConfig->stcBitrate.u8TimeSegment1;
            unNBTP.stcField.u7NTSEG2 = pstcConfig->stcBitrate.u8TimeSegment2;
            unNBTP.stcField.u7NSJW   = pstcConfig->stcBitrate.u8SyncJumpWidth;
            pstcCanFD->unNBTP.u32Register  = unNBTP.u32Register;
            
            /* Fast Bit Timing & Prescaler */
            unDBTP.stcField.u1TDC    = 1; /* Transceiver Delay Compensation enabled. */
            unDBTP.stcField.u5DBRP   = pstcConfig->stcFastBitrate.u16Prescaler;
            unDBTP.stcField.u5DTSEG1 = pstcConfig->stcFastBitrate.u8TimeSegment1;
            unDBTP.stcField.u4DTSEG2 = pstcConfig->stcFastBitrate.u8TimeSegment2;
            unDBTP.stcField.u4DSJW   = pstcConfig->stcFastBitrate.u8SyncJumpWidth;
            pstcCanFD->unDBTP.u32Register   = unDBTP.u32Register;
            
            /* Transmitter Delay Compensation */
            unTDCR.stcField.u7TDCO   = 4; /* Transmitter Delay Compensation Offset */
            unTDCR.stcField.u7TDCF   = 0; /* Transmitter Delay Compensation Filter Window Length */
            pstcCanFD->unTDCR.u32Register   = unTDCR.u32Register;
            
            /* Configuration of Global Filter */
            unGFC.stcField.u2ANFS = 2; /* Reject when unmatch id */
            unGFC.stcField.u2ANFE = 2; /* Reject when unmatch id */
            unGFC.stcField.u1RRFS = 1; /* Reject all remote frame */
            unGFC.stcField.u1RRFE = 1; /* Reject all remote frame */
            pstcCanFD->unGFC.u32Register = unGFC.u32Register;
            
            /* Standard Message ID Filter */
            pstcIdFilter = (stc_id_filter_t*)((uint32_t*)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unSIDFC.stcField.u14FLSSA);
            pstcIdFilter->SFT   = 2;        /* Standard Filter Type : Classic filter */
            pstcIdFilter->SFEC  = 7;        /* Store into dedicated Rx Buffer, configuration of SFT[1:0] ignored. */
            pstcIdFilter->SFID1 = 0x010;    /* Filter ID : 0x10(16) */
            pstcIdFilter->SFID2 = (0 << 9)  /* Store message into a dedicated Rx Buffer */
            | 0;        /* Buffer index : 0 */
            
            /* Extended Message ID Filter */
            pstcExtIdFilter = (stc_extid_filter_t*)((uint32_t*)((uint32_t)pstcCanFD + (uint32_t)MSGRAMOFFSET) + pstcCanFD->unXIDFC.stcField.u14FLESA);
            pstcExtIdFilter->F1_f.EFT   = 2;        /* Extended Filter Type : Classic filter */
            pstcExtIdFilter->F0_f.EFEC  = 7;        /* Store into dedicated Rx Buffer, configuration of EFT[1:0] ignored. */
            pstcExtIdFilter->F0_f.EFID1 = 0x10001;  /* Filter ID : 0x10001(65537) */
            pstcExtIdFilter->F1_f.EFID2 = (0 << 9)  /* Store message into a dedicated Rx Buffer */
            | 1;           /* Buffer index : 1 */
            
            /* Configuration of Rx Buffer and Rx FIFO */
            unRXESC.stcField.u3RBDS = 7; /* 64 byte data field. */
            unRXESC.stcField.u3F1DS = 7; /* FIFO1 64 byte data field. */
            unRXESC.stcField.u3F0DS = 7; /* FIFO0 64 byte data field. */
            pstcCanFD->unRXESC.u32Register = unRXESC.u32Register;
            
            /* Configuration of Tx Buffer and Tx FIFO/Queue */
            unTXESC.stcField.u3TBDS = 7; /* 64 byte data field. */
            pstcCanFD->unTXESC.u32Register = unTXESC.u32Register;
            
        } // if( pstcConfig->bCanFDMode == 0 )
        
        
        /* Configuration of Interrupt */
        // Interrupt Enable
        unIE.stcField.u1ARAE  = 0; /* Access to Reserved Address */
        unIE.stcField.u1PEDE  = 0; /* Protocol Error in Data Phase */
        unIE.stcField.u1PEAE  = 0; /* Protocol Error in Arbitration Phase */
        unIE.stcField.u1WDIE  = 0; /* Watchdog */
        unIE.stcField.u1BOE   = 0; /* Bus_Off Status */
        unIE.stcField.u1EWE   = 0; /* Warning Status */
        unIE.stcField.u1EPE   = 0; /* Error Passive */
        unIE.stcField.u1ELOE  = 0; /* Error Logging Overflow */
        unIE.stcField.u1BEUE  = 0; /* Bit Error Uncorrected */
        unIE.stcField.u1BECE  = 0; /* Bit Error Corrected */
        unIE.stcField.u1DRXE  = 1; /* Message stored to Dedicated Rx Buffer */
        unIE.stcField.u1TOOE  = 0; /* Timeout Occurred */
        unIE.stcField.u1MRAFE = 0; /* Message RAM Access Failure */
        unIE.stcField.u1TSWE  = 0; /* Timestamp Wraparound */
        unIE.stcField.u1TEFLE = 0; /* Tx Event FIFO Event Lost */
        unIE.stcField.u1TEFFE = 0; /* Tx Event FIFO Full */
        unIE.stcField.u1TEFWE = 0; /* Tx Event FIFO Watermark Reached */
        unIE.stcField.u1TEFNE = 0; /* Tx Event FIFO New Entry */
        unIE.stcField.u1TFEE  = 0; /* Tx FIFO Empty */
        unIE.stcField.u1TCFE  = 0; /* Transmission Cancellation Finished */
        unIE.stcField.u1TCE   = 0; /* Transmission Completed */
        unIE.stcField.u1HPME  = 0; /* High Priority Message */
        unIE.stcField.u1RF1LE = 0; /* Rx FIFO 1 Message Lost */
        unIE.stcField.u1RF1FE = 0; /* Rx FIFO 1 Full */
        unIE.stcField.u1RF1WE = 0; /* Rx FIFO 1 Wotermark Reached */
        unIE.stcField.u1RF1NE = 0; /* Rx FIFO 1 New Message */
        unIE.stcField.u1RF0LE = 0; /* Rx FIFO 0 Message Lost */
        unIE.stcField.u1RF0FE = 0; /* Rx FIFO 0 Full */
        unIE.stcField.u1RF0WE = 0; /* Rx FIFO 0 Wotermark Reached */
        unIE.stcField.u1RF0NE = 0; /* Rx FIFO 0 New Message */
        pstcCanFD->unIE.u32Register = unIE.u32Register;
        
        /* Interrupt Line Select */
        unILS.stcField.u1ARAL  = 0; /* Access to Reserved Address */
        unILS.stcField.u1PEDL  = 0; /* Protocol Error in Data Phase */
        unILS.stcField.u1PEAL  = 0; /* Protocol Error in Arbitration Phase */
        unILS.stcField.u1WDIL  = 0; /* Watchdog */
        unILS.stcField.u1BOL   = 0; /* Bus_Off Status */
        unILS.stcField.u1EWL   = 0; /* Warning Status */
        unILS.stcField.u1EPL   = 0; /* Error Passive */
        unILS.stcField.u1ELOL  = 0; /* Error Logging Overflow */
        unILS.stcField.u1BEUL  = 0; /* Bit Error Uncorrected */
        unILS.stcField.u1BECL  = 0; /* Bit Error Corrected */
        unILS.stcField.u1DRXL  = 0; /* Message stored to Dedicated Rx Buffer */
        unILS.stcField.u1TOOL  = 0; /* Timeout Occurred */
        unILS.stcField.u1MRAFL = 0; /* Message RAM Access Failure */
        unILS.stcField.u1TSWL  = 0; /* Timestamp Wraparound */
        unILS.stcField.u1TEFLL = 0; /* Tx Event FIFO Event Lost */
        unILS.stcField.u1TEFFL = 0; /* Tx Event FIFO Full */
        unILS.stcField.u1TEFWL = 0; /* Tx Event FIFO Watermark Reached */
        unILS.stcField.u1TEFNL = 0; /* Tx Event FIFO New Entry */
        unILS.stcField.u1TFEL  = 0; /* Tx FIFO Empty */
        unILS.stcField.u1TCFL  = 0; /* Transmission Cancellation Finished */
        unILS.stcField.u1TCL   = 0; /* Transmission Completed */
        unILS.stcField.u1HPML  = 0; /* High Priority Message */
        unILS.stcField.u1RF1LL = 0; /* Rx FIFO 1 Message Lost */
        unILS.stcField.u1RF1FL = 0; /* Rx FIFO 1 Full */
        unILS.stcField.u1RF1WL = 0; /* Rx FIFO 1 Wotermark Reached */
        unILS.stcField.u1RF1NL = 0; /* Rx FIFO 1 New Message */
        unILS.stcField.u1RF0LL = 0; /* Rx FIFO 0 Message Lost */
        unILS.stcField.u1RF0FL = 0; /* Rx FIFO 0 Full */
        unILS.stcField.u1RF0WL = 0; /* Rx FIFO 0 Wotermark Reached */
        unILS.stcField.u1RF0NL = 0; /* Rx FIFO 0 New Message */
        pstcCanFD->unILS.u32Register = unILS.u32Register;
        
        /* Interrupt Line Enable */
        unILE.stcField.u1EINT0 = 1; /* Enable Interrupt Line 0 */
        unILE.stcField.u1EINT1 = 0; /* Disable Interrupt Line 1 */
        pstcCanFD->unILE.u32Register = unILE.u32Register;
        
        /* Initialize the Last error code data */
        m_u16LastErrorCode = 0;
        
        /* CAN-FD operation start */
        /* Set CCCR.INIT to 0 and wait until it will be updated. */
        unCCCR.stcField.u1INIT = 0;
        pstcCanFD->unCCCR.u32Register = unCCCR.u32Register;
        while ( pstcCanFD->unCCCR.stcField.u1INIT != 0 )
        {
        }
        
        return Ok;
    } /* CanFD_Init */
    
    
    /**
    *****************************************************************************
    ** \brief Updates the message data of a message buffer and start transmission.
    ** Transmits the message immediately.
    ** Function CanFD_Init() must be called before setup the identifier and enable
        ** this message buffer.
    **
    ** \param [in] pstcCanFD             Pointer to register area of a CAN-FD unit.
    ** \param [in] u8MsgBuf              Message buffer index (0-31)
    ** \param [in] pstcMsg               CAN-FD message data
    **
    ** \retval Ok                        Message buffer has been succesfully updated.
    ** \retval ErrorInvalidParameter     If one of the following conditions are met:
    **   - pstcCanFD == NULL
    **   - pstcMsg == NULL
    **   - pstcCanFDTxBuffer == NULL
    *****************************************************************************/
    en_result_t CanFD_UpdateAndTransmitMsgBuffer( pstc_canfd_type_t pstcCanFD,
                                                 uint8_t u8MsgBuf,
                                                 stc_canfd_msg_t* pstcMsg
                                                 )
    {
        stc_canfd_intern_data_t* pstcCanFDInternData; // Pointer to internal data
        uint8_t u8DataLengthWord;
        stc_canfd_tx_buffer_t* pstcCanFDTxBuffer;
        uint16_t u16count;
        uint16_t u16dlcTmp;
        
        /* Check for NULL pointers */
        if ( pstcCanFD     == NULL ||
            pstcMsg == NULL
            )
        {
            return ErrorInvalidParameter;
        }
        
        /* Get pointer to internal data structure */
        pstcCanFDInternData = CanFDGetInternDataPtr( pstcCanFD ) ;
        
        /* Check for NULL */
        if ( pstcCanFDInternData == NULL )
        {
            return ErrorInvalidParameter;
        }
        
        /* Get Tx Buffer address */
        pstcCanFDTxBuffer = (stc_canfd_tx_buffer_t *)(calcTxBufAdrs( pstcCanFD, u8MsgBuf ));
        if ( pstcCanFDTxBuffer == NULL )
        {
            return ErrorInvalidParameter;
        }
        
        /* Set data to Tx buffer */
        pstcCanFDTxBuffer->T0_f.RTR = 0; /* Transmit data frame. */
        pstcCanFDTxBuffer->T0_f.XTD = (pstcMsg->stcIdentifier.bExtended == TRUE) ? 1 : 0;
            pstcCanFDTxBuffer->T0_f.ID  =
        (pstcCanFDTxBuffer->T0_f.XTD == 0) ? (pstcMsg->stcIdentifier.u32Identifier << 18) : pstcMsg->stcIdentifier.u32Identifier;
            pstcCanFDTxBuffer->T1_f.EFC = 0; /* Not store Tx event FIFO */
        pstcCanFDTxBuffer->T1_f.MM  = 0; /* Not used */
        pstcCanFDTxBuffer->T1_f.DLC = pstcMsg->stcData.u8DataLengthCode;
        pstcCanFDTxBuffer->T1_f.FDF = (pstcMsg->bCanFDFormat == TRUE) ? 1 : 0;
        pstcCanFDTxBuffer->T1_f.BRS = (pstcMsg->bCanFDFormat == TRUE) ? 1 : 0;
        
        /* Convert the DLC to data byte word */
        if ( pstcMsg->stcData.u8DataLengthCode < 8 )
        {
            u16dlcTmp = 0;
        }
        else
        {
            u16dlcTmp = pstcMsg->stcData.u8DataLengthCode - 8;
        }
        u8DataLengthWord = iDlcInWord[u16dlcTmp];
        
        /* Data set */
        for ( u16count = 0; u16count < u8DataLengthWord; u16count++ )
        {
            pstcCanFDTxBuffer->DATA_AREA_f[u16count] = pstcMsg->stcData.au32Data[u16count];
        }
        
        /* Check whether Tx buffer is empty or not */
        while ( 0 != (pstcCanFD->unTXBRP.u32Register & 0x00000001 )) /* Check the TRP0 */
        {
            if(pstcCanFD->unCCCR.stcField.u1INIT == 1)
            {
                return ErrorOperationInProgress ;
            }
        }
        
        /* Request to transmit */
        pstcCanFD->unTXBAR.u32Register = 0x00000001ul; // request for buffer 0
        
        return Ok;
    } /* CanFD_UpdateAndTransmitMsgBuffer */
    
    
//@}
#endif /* (PDL_PERIPHERAL_CANFD_ACTIVE) */
/*****************************************************************************/
/* EOF (not truncated)                                                       */
/*****************************************************************************/
