
#include "CANFD.h"
#include "PowerManagement.h"


/******************************************************************************

                                Baud rate setting

The bit time can be divided into four segments according to the CAN
specifications, the synchronization segment (Sync_Seg), the propagation time
segment (Prop_Seg), the phase buffer segment 1 (Phase_Seg1), and the phase
buffer segment 2 (Phase_Seg2). The sample point, the point of time at which the
bus level is read and interpreted as the value of that respective bit, is
located at the end of Phase_Seg1.

  |<-----------------------------  A bit time  ---------------------------->|
  ---------------------------------------------------------------------------
  | Sync_Seg |    Prop_Seg    |      Phase_Seg1      |      Phase_Seg2      |
  ---------------------------------------------------------------------------
  |<- 1 Tq ->|<--------------  T_SEG1  ------------->|<-----  T_SEG2  ----->|
                                                     ^
                                                     |
                                               Sampling point

Each segment consists of a programmable number of time quanta(Tq), which is a
multiple of the time quantum that is defined by source clock and a prescaler.

The time quantum is configured as
                   Tq = 1 / (Source Clock Freq / PRESCALER)

-------------------------------------------------------------------------------
  Parameter  | Description
-------------+-----------------------------------------------------------------
 Sync_Seg    |Sync_Seg is fixed to 1 time quantum as defined by the CAN
             |specifications and is therefore not configurable
-------------+-----------------------------------------------------------------
             |Prop_Seg is the part of the bit time that is used to compensate
             |for the physical delay times within the network.
 Prop_Seg    |
     &       |Phase_Seg1 is used to compensate for edge phase errors before the
 Phase_Seg1  |sampling point. Can be lengthened by the resynchronization jump
             |width.
             |
             |T_SEG1 = Prop_Seg + Phase_Seg1
-------------+-----------------------------------------------------------------
             |Phase_Seg2 is used to compensate for edge phase errors after the
             |sampling point. Can be shortened by the resynchronization jump
 Phase_Seg2  |width.
             |
             |T_SEG2 = Phase_Seg2
-------------+-----------------------------------------------------------------
             |Resynchronization Jump Width. Used to adjust the length of
 SJW         |Phase_Seg1 and Phase_Seg2. SJW will not be longer than either
             |Phase_Seg1 or Phase_Seg2.
-------------------------------------------------------------------------------

Baud rate = 1 / [(Sync_Seg + Prop_Seg + Phase_Seg1 + Phase_Seg2)   Tq)]
          = Source Clock Freq / [PRESCALER * (1 + T_SEG1 + T_SEG2)]

******************************************************************************/



#if   (CANFD_CH0_BAUD_RATE == 500U)
#define CANFD_CH0_PRESCALER                1U
#define CANFD_CH0_T_SEG1                  12U
#define CANFD_CH0_T_SEG2                   3U
#define CANFD_CH0_SJW                      3U

#elif (CANFD_CH0_BAUD_RATE == 250U)
#define CANFD_CH0_PRESCALER                2U
#define CANFD_CH0_T_SEG1                  12U
#define CANFD_CH0_T_SEG2                   3U
#define CANFD_CH0_SJW                      3U
#elif (CANFD_CH0_BAUD_RATE == 125U)
#define CANFD_CH0_PRESCALER                4U
#define CANFD_CH0_T_SEG1                  11U
#define CANFD_CH0_T_SEG2                   4U
#define CANFD_CH0_SJW                      4U
#else
#if CANFD_CH0_ENABLE
#error CANFD5: Unsupported baud rate
#endif
#endif


#define   CANFD_MSG_RAM_WORD_SIZE           4352U

#define   CANFD_CH0_MSG_RAM_ADDR            ((uint32_t)(&CPG_CANFD0) + 0x00008000UL)


extern void Can_BusOffRecover(void);



typedef struct
{
    volatile uint32_t   ID        : 29;   /*!< Identifier */
        volatile uint32_t   RTR       :  1;   /*!< Remote Transmission Request */
        volatile uint32_t   XTD       :  1;   /*!< Extended Identifier */
        volatile uint32_t   ESI       :  1;   /*!< Error State Indicator */
    } CANFD_Rx_Buffer_R0_st_t;

    typedef struct
{
    volatile uint32_t   RXTS      : 16;   /*!< Rx Timestamp */
        volatile uint32_t   DLC       :  4;   /*!< Data Length Code */
        volatile uint32_t   BRS       :  1;   /*!< Bit Rate Switch */
        volatile uint32_t   FDF       :  1;   /*!< Extended Data Length */
        uint32_t   RSVD1              :  2;   /*!< Reserved bits */
        volatile uint32_t   FIDX      :  7;   /*!< Filter Index */
        volatile uint32_t   ANMF      :  1;   /*!< Accepted Non-matching Frame */
    } CANFD_Rx_Buffer_R1_st_t;

    typedef struct stc_canfd_rx_buffer
{
    CANFD_Rx_Buffer_R0_st_t   R0_f;       /*!< Rx buffer element for R0. See #stc_canfd_r0_t. */
    CANFD_Rx_Buffer_R1_st_t   R1_f;       /*!< Rx buffer element for R1. See #stc_canfd_r1_t. */
    uint32_t                  Data[16];   /*!< Rx buffer element for Rn */
} CANFD_Rx_Buffer_st_t;









typedef struct
{
    volatile uint32_t  ID         : 29;   /*!< Identifier */
        volatile uint32_t  RTR        :  1;   /*!< Remote Transmission Request */
        volatile uint32_t  XTD        :  1;   /*!< Extended Identifier  */
        volatile uint32_t  ESI        :  1;   /*!< Error State Indicator */
    } CANFD_Tx_Buffer_T0_st_t;


    typedef struct
{
    uint32_t  RSVD1      : 16;   /*!< Reserved bits */
    volatile uint32_t  DLC        :  4;   /*!< Data Length Code */
        volatile uint32_t  BRS        :  1;   /*!< Bit Rate Switching */
        volatile uint32_t  FDF        :  1;   /*!< FD Format */
        volatile uint32_t  EFC        :  1;   /*!< Event FIFO Control */
        volatile uint32_t  MM         :  8;   /*!< Message Marker */
    } CANFD_Tx_Buffer_T1_st_t;



    typedef struct stc_canfd_tx_buffer
{
    CANFD_Tx_Buffer_T0_st_t   T0_f;       /*!< Tx buffer element for T0. See #stc_canfd_t0_t. */
    CANFD_Tx_Buffer_T1_st_t   T1_f;       /*!< Tx buffer element for T1. See #stc_canfd_t1_t. */
    uint32_t                  Data[16];   /*!< Tx buffer element for Tn */
} CANFD_Tx_Buffer_st_t;







typedef struct
{
    volatile uint32_t SFID2       : 11;   /*!< Standard Filter ID 2 */
        uint32_t RESERVED4   :  5;   /*!< Reserved bits */
        volatile uint32_t SFID1       : 11;   /*!< Standard Filter ID 1 */
        volatile uint32_t SFEC        :  3;   /*!< Standard Filter Element Configuration */
        volatile uint32_t SFT         :  2;   /*!< Standard Filter Type */
    } CANFD_Std_ID_Filter_st_t;


    typedef struct
{
    volatile uint32_t EFID1       : 29;   /*!< Extended Filter ID 1 */
        volatile uint32_t EFEC        :  3;   /*!< Extended Filter Element Configuration */
    } CANFD_Ext_ID_F0_st_t;

    typedef struct stc_canfd_f1
{
    volatile uint32_t EFID2       : 29;   /*!< Extended Filter ID 2 */
        uint32_t RESERVED1   :  1;   /*!< Reserved bits */
        volatile uint32_t EFT         :  2;   /*!< Extended Filter Type */
    } CANFD_Ext_ID_F1_st_t;


    typedef struct stc_extid_filter
{
    CANFD_Ext_ID_F0_st_t  F0_f;   /*!< Extended Message ID Filter Element for F0. See #stc_canfd_f0_t. */
    CANFD_Ext_ID_F1_st_t  F1_f;   /*!< Extended Message ID Filter Element for F1. See #stc_canfd_f1_t. */
} CANFD_Ext_ID_Filter_st_t;



static const uint32_t CANFDRxBufferLookupData0[1] =
{
    0x0000FFFFUL,
};

static const uint32_t CANFDRxBufferLookupData1[2] =
{
    0x000000FFUL, 0x00FF0000UL,
};

static const uint32_t CANFDRxBufferLookupData2[4] =
{
    0x0000000FUL, 0x00000F00UL, 0x000F0000UL, 0x0F000000UL,
};

static const uint32_t CANFDRxBufferLookupData3[8] =
{
    0x00000003UL, 0x00000030UL, 0x00000300UL, 0x00003000UL,
    0x00030000UL, 0x00300000UL, 0x03000000UL, 0x30000000UL,
};

static const uint32_t CANFDRxBufferLookupData4[16] =
{
    0x00000001UL, 0x00000004UL, 0x00000010UL, 0x00000040UL,
    0x00000100UL, 0x00000400UL, 0x00001000UL, 0x00004000UL,
    0x00010000UL, 0x00040000UL, 0x00100000UL, 0x00400000UL,
    0x01000000UL, 0x04000000UL, 0x10000000UL, 0x40000000UL,
};

static const uint32_t CANFDRxBufferLookupData5[32] =
{
    0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL,
    0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL,
    0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL,
    0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL,
    0x00010000UL, 0x00020000UL, 0x00040000UL, 0x00080000UL,
    0x00100000UL, 0x00200000UL, 0x00400000UL, 0x00800000UL,
    0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
    0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
};

const uint32_t *const pCANFDRxBufferLookupData[6] =
{
    CANFDRxBufferLookupData0,
    CANFDRxBufferLookupData1,
    CANFDRxBufferLookupData2,
    CANFDRxBufferLookupData3,
    CANFDRxBufferLookupData4,
    CANFDRxBufferLookupData5,
};

static __irq __arm void CANFD_Ch0_Data_Reception_ISR(void);



CAN_Data_Ind_Func pfCANDataIndCb;
CAN_Data_Cfm_Func pfCANDataCfmCb;
CAN_Data_Abort_Func pfCANDataAbortCb;


uint8_t MSCAN_Exist;
uint32_t g_SuccessBuff;
uint8_t txMbState[32];



#if CANFD_CH0_ENABLE
uint8_t   CANFDCh0UsedRxBufferNum;
#endif


uint8_t Can_Read_Bus(void)
{
    return MSCAN_Exist;
}

void Can_Set_Bus(uint8_t exist)
{
    MSCAN_Exist = exist;
    if(exist==1u)
    {
      SleepTime_Timing=0u;
    }
}



void CANFD_Clk_Init ( void )
{
    CANP_CTR_CANPRE = 0U;
    while ( CANP_STR_BUSY ) {}
    CANP_CTR_CPCKS = 1U;
}


void CANFD_CH0_Init (CANFD_Filter_Init_st_t *pFilterInit)
{
#if CANFD_CH0_ENABLE

    uint16_t  i;
    uint16_t  j;
    uint16_t  FilterNum;
    uint16_t  RxBufferStart;
    uint32_t *p;

    un_ric_keycdr_t            RICKey;
    CANFD_Filter_Cfg_st_t     *pFilterCfg;
    CANFD_Std_ID_Filter_st_t  *pStdIDFilter;
    CANFD_Ext_ID_Filter_st_t  *pExtIDFilter;

    pfCANDataIndCb = pFilterInit->pfCANDataIndCb;
    pfCANDataCfmCb = pFilterInit->pfCANDataCfmCb;
    pfCANDataAbortCb = pFilterInit->pfCANDataAbortCb;

    /*** CANFD0 = CPG_CANFD0 ***/

    /*** CANFD0 Rx pin config ***/
    RICKey.u32Register = 0U;
    RICKey.stcField.u15RADR = ( uint_io32_t ) ( &RIC_RESIN210 ) & 0x00007FFFUL;
    RICKey.stcField.u2SIZE  = 0x1U;

    IRQ_DISABLE_LOCAL()
    RICKey.stcField.u2KEY   = 0x0U;
    RIC_KEYCDR = RICKey.u32Register;
    RICKey.stcField.u2KEY   = 0x1U;
    RIC_KEYCDR = RICKey.u32Register;
    RICKey.stcField.u2KEY   = 0x2U;
    RIC_KEYCDR = RICKey.u32Register;
    RICKey.stcField.u2KEY   = 0x3U;
    RIC_KEYCDR = RICKey.u32Register;
    RIC_RESIN210            = 0x0000U;     /* RESSEL = 0, PORTSEL = 0*/
    IRQ_RESTORE()

    /*** Set CCCR.INIT to 1 and wait until it will be updated. ***/
    CPG_CANFD0_CCCR_INIT = 1U;
    while ( CPG_CANFD0_CCCR_INIT == 0U ) {}
    CPG_CANFD0_CCCR_CCE = 1U;        /* Enable configuration change */

    CANFD_Clk_Init();

    /*** Configuration of CAN bus ***/

    /* CCCR register */
    CPG_CANFD0_CCCR_TXP  = 0U;       /* Transmit pause disabled. */
    CPG_CANFD0_CCCR_BRSE = 0U;       /* Bit rate switching for transmissions disabled. */
    CPG_CANFD0_CCCR_FDOE = 0U;       /* FD operation disabled. */
    CPG_CANFD0_CCCR_TEST = 0U;       /* Normal operation */
    CPG_CANFD0_CCCR_DAR  = 0U;       /* Automatic retransmission enabled. */
    CPG_CANFD0_CCCR_MON  = 0U;       /* Bus Monitoring Mode is disabled. */
    CPG_CANFD0_CCCR_CSR  = 0U;       /* No clock stop is requested. */
    CPG_CANFD0_CCCR_ASM  = 0U;       /* Normal CAN operation. */    /*50302*/

    /* Bit Timing & Prescaler Register */
    CPG_CANFD0_DBTP_TDC     = 0U;    /* Transceiver Delay Compensation disabled */

#if CANFD_CH0_PRESCALER
    CPG_CANFD0_NBTP_NBRP    = CANFD_CH0_PRESCALER - 1U;
    CPG_CANFD0_DBTP_DBRP    = CANFD_CH0_PRESCALER - 1U;
#endif

#if CANFD_CH0_T_SEG1
    CPG_CANFD0_NBTP_NTSEG1  = CANFD_CH0_T_SEG1 - 1U;
    CPG_CANFD0_DBTP_DTSEG1  = CANFD_CH0_T_SEG1 - 1U;
#endif

#if CANFD_CH0_T_SEG2
    CPG_CANFD0_NBTP_NTSEG2  = CANFD_CH0_T_SEG2 - 1U;
    CPG_CANFD0_DBTP_DTSEG2  = CANFD_CH0_T_SEG2 - 1U;
#endif

#if CANFD_CH0_SJW
    CPG_CANFD0_NBTP_NSJW    = CANFD_CH0_SJW - 1U;
    CPG_CANFD0_DBTP_DSJW    = CANFD_CH0_SJW - 1U;
#endif

    /*** Configuration of message RAM ***/

    /* Initialize message RAM area(Entire region zeroing) */
    p = ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR;
    for ( i = 0U; i < CANFD_MSG_RAM_WORD_SIZE; i++ )
    {
        *p = 0x00000000UL;
        p++;
    }

    /* Configuration of ID filter */
    FilterNum     = 0U;
    RxBufferStart = 0U;

    CPG_CANFD0_SIDFC_FLSSA = 0x0000U;
    CPG_CANFD0_XIDFC_FLESA = 0x0080U;

    /* Step 1 : Configure single standard ID filters */
    pFilterCfg = & ( pFilterInit -> NMStdFilter );
    for ( i = 0U; i < 3U; i++ )
    {
        if ( ( pFilterCfg -> CfgType == CANFD_FILTER_ID_LIST ) && \
                ( pFilterCfg -> pIDs    != NULL ) )
        {
            for ( j = 0U; j < pFilterCfg -> IDNum; j++ )
            {
                pStdIDFilter  = ( CANFD_Std_ID_Filter_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_SIDFC_FLSSA ) + FilterNum;
                pStdIDFilter -> SFT   = 2U;                          /* Classic filter */
                pStdIDFilter -> SFEC  = 7U;                          /* Store into dedicated Rx Buffer */
                pStdIDFilter -> SFID1 = pFilterCfg -> pIDs[j];       /* Filter ID */
                pStdIDFilter -> SFID2 = (uint32_t)RxBufferStart + (uint32_t)FilterNum;   /* Set buffer index */

                FilterNum++;
            }
        }
        pFilterCfg++;
    }

    RxBufferStart  = FilterNum;

    /* Step 2 : Configure range standard ID filters */
    pFilterCfg = & ( pFilterInit -> NMStdFilter );
    for ( i = 0U; i < 3U; i++ )
    {
        if ( ( pFilterCfg -> CfgType == CANFD_FILTER_ID_RANGE ) && \
                ( pFilterCfg -> pIDs    != NULL ) )
        {
            pStdIDFilter  = ( CANFD_Std_ID_Filter_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_SIDFC_FLSSA ) + FilterNum;
            pStdIDFilter -> SFT   = 0U;                            /* Range filter */
            pStdIDFilter -> SFEC  = 1U;                            /* Store into Rx FIFO 0 */
            pStdIDFilter -> SFID1 = pFilterCfg -> pIDs[0];         /* Filter ID strat */
            pStdIDFilter -> SFID2 = pFilterCfg -> pIDs[1];         /* Filter ID end */

            FilterNum++;
        }
        pFilterCfg++;
    }

    CPG_CANFD0_SIDFC_LSS = (uint8_t)FilterNum;
    FilterNum            = 0U;

    /* Step 3 : Configure single extended ID filters */
    pFilterCfg = & ( pFilterInit -> NMExtFilter );
    for ( i = 0U; i < 3U; i++ )
    {
        if ( ( pFilterCfg -> CfgType == CANFD_FILTER_ID_LIST ) && \
                ( pFilterCfg -> pIDs    != NULL ) )
        {
            for ( j = 0U; j < pFilterCfg -> IDNum; j++ )
            {
                pExtIDFilter  = ( CANFD_Ext_ID_Filter_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_XIDFC_FLESA ) + FilterNum;
                pExtIDFilter -> F1_f.EFT   = 2U;                          /* Classic filter */
                pExtIDFilter -> F0_f.EFEC  = 7U;                          /* Store into dedicated Rx Buffer */
                pExtIDFilter -> F0_f.EFID1 = pFilterCfg -> pIDs[j];       /* Filter ID */
                pExtIDFilter -> F1_f.EFID2 = (uint32_t)RxBufferStart + (uint32_t)FilterNum;   /* Set buffer index */

                FilterNum++;
            }
        }
        pFilterCfg++;
    }

    CANFDCh0UsedRxBufferNum = (uint8_t)(RxBufferStart + FilterNum);

    /* Step 4 : Configure range extended ID filters */
    pFilterCfg = & ( pFilterInit -> NMExtFilter );
    for ( i = 0U; i < 3U; i++ )
    {
        if ( ( pFilterCfg -> CfgType == CANFD_FILTER_ID_RANGE ) && \
                ( pFilterCfg -> pIDs    != NULL ) )
        {
            pExtIDFilter  = ( CANFD_Ext_ID_Filter_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_XIDFC_FLESA ) + FilterNum;
            pExtIDFilter -> F1_f.EFT   = 0U;                            /* Range filter */
            pExtIDFilter -> F0_f.EFEC  = 1U;                            /* Store into Rx FIFO 0 */
            pExtIDFilter -> F0_f.EFID1 = pFilterCfg -> pIDs[0];         /* Filter ID strat */
            pExtIDFilter -> F1_f.EFID2 = pFilterCfg -> pIDs[1];         /* Filter ID end */

            FilterNum++;
        }
        pFilterCfg++;
    }

    CPG_CANFD0_XIDFC_LSE = FilterNum;

    /* Configuration of ID filter list */
    CPG_CANFD0_GFC_ANFS   = 1U;                        /* Reject when unmatch id */
    CPG_CANFD0_GFC_ANFE   = 1U;                        /* Reject when unmatch id */
    CPG_CANFD0_GFC_RRFS   = 1U;                        /* Reject all remote frame */
    CPG_CANFD0_GFC_RRFE   = 1U;                        /* Reject all remote frame */

    CPG_CANFD0_XIDAM_EIDM = 0x1FFFFFFFUL;              /* Extended ID mask is not active */

    /* Configuration of Rx buffer and Rx FIFO */
    CPG_CANFD0_RXF0C_F0OM = 0U;                        /* Rx FIFO 0 blocking mode */
    CPG_CANFD0_RXF0C_F0WM = 0U;                        /* Watermark interrupt disabled */
    CPG_CANFD0_RXF0C_F0S  = CANFD_CH0_RX_FIFO_DEPTH;   /* Rx FIFO 0 Size */
    CPG_CANFD0_RXF0C_F0SA = 0x0100U;                   /* Rx FIFO 0 RAM offset (word) */

    CPG_CANFD0_RXF1C_F1OM = 0U;                        /* Rx FIFO 1 blocking mode */
    CPG_CANFD0_RXF1C_F1WM = 0U;                        /* Watermark interrupt disabled */
    CPG_CANFD0_RXF1C_F1S  = CANFD_CH0_RX_FIFO_DEPTH;   /* Rx FIFO 1 Size (this FIFO is not used)*/
    CPG_CANFD0_RXF1C_F1SA = 0x0580U;                   /* Rx FIFO 1 RAM offset (word) */

    CPG_CANFD0_RXBC_RBSA  = 0x0A00U;                   /* Rx buffer RAM offset (word) */

    CPG_CANFD0_RXESC_F0DS = 0U;                        /* Rx FIFO 0 data field size = 8 byte */
    CPG_CANFD0_RXESC_F1DS = 0U;                        /* Rx FIFO 1 data field size = 8 byte */
    CPG_CANFD0_RXESC_RBDS = 0U;                        /* Rx buffer data field size = 8 byte */

    /* Configuration of Tx buffer and Tx FIFO / Queue */
    CPG_CANFD0_TXEFC_EFWM = 0U;                        /* Watermark interrupt disabled */
    CPG_CANFD0_TXEFC_EFS  = 0U;                        /* Tx Event FIFO disabled. */
    CPG_CANFD0_TXEFC_EFSA = 0x0E80U;                   /* Tx Event FIFO RAM offset (word) */

    CPG_CANFD0_TXBC_TFQM  = 0U;                        /* Tx FIFO operation */
    CPG_CANFD0_TXBC_TFQS  = 0U;                        /* Tx FIFO Size */
    CPG_CANFD0_TXBC_NDTB  = 32U;                       /* No Dedicated Tx Buffers */
    CPG_CANFD0_TXBC_TBSA  = 0x0EC0U;                   /* Tx FIFO RAM offset (word) */

    CPG_CANFD0_TXESC_TBDS = 0U;                        /* Tx buffer data field size = 8 byte */

    /*** Configuration of Interrupt ***/
    CPG_CANFD0_TXBTIE     = 0x00000000UL;  /* Disable Tx buffer transmission Interrupt */
    CPG_CANFD0_TXBCIE     = 0x00000000UL;  /* Disable Tx buffer cancellation Interrupt */

    CPG_CANFD0_IE         = 0x00000000UL;  /* Disable all interrupts */


    CPG_CANFD0_IR         = 0x3FFFFFFFUL;  /* Clear all interrupt flags */
    CPG_CANFD0_ILS        = 0x00000000UL;  /* Interrupt assigned to line 0 */

    CPG_CANFD0_IE_DRXE    = 1U;            /* Rx buffer new message interrupt enable */
    CPG_CANFD0_IE_RF0NE   = 1U;            /* Rx FIFO 0 new message interrupt enable */
    CPG_CANFD0_IE_RF1NE   = 1U;            /* Rx FIFO 1 new message interrupt enable */
    CPG_CANFD0_IE_PEAE = 1U;
    CPG_CANFD0_IE_PEDE = 1U;
    CPG_CANFD0_IE_TCE   = 1U;
    CPG_CANFD0_IE_TCFE  = 0U;
    CPG_CANFD0_IE_BOE  = 0U;

    Interrupt_IRQ_ISR_Register(INTERRUPTS_IRQ_NUMBER_40, (uint32_t)CANFD_Ch0_Data_Reception_ISR, 31U);

    CPG_CANFD0_ILE_EINT0  = 1U;            /* Enable interrupt line 0 */
    CPG_CANFD0_ILE_EINT1  = 0U;            /* Disable interrupt line 1 */

    /*** Start CAN  ***/
    CPG_CANFD0_CCCR_INIT  = 0U;
    while (CPG_CANFD0_CCCR_INIT != 0U) {}
    g_SuccessBuff = 0u;
    for (i = 0u; i < sizeof(txMbState); i++)
    {
        txMbState[i] = 0u;
    }
#endif
}

void CANFD_CH0_L_Data_Request ( uint32_t Identifier, uint16_t Idx, uint8_t DLC, uint8_t *Data )
{
#if CANFD_CH0_ENABLE
    uint8_t   i;
    /*uint8_t   FlagTFQF;*/
    uint8_t   FlagBO;
    uint16_t  Index;
    uint32_t  Word;
    CANFD_Tx_Buffer_st_t *pTxBuffer;

    if ( ( DLC == 0U ) || ( DLC > 8U ) || ( Data == NULL ) )
    {
        /* Make upper layer clear ther error message */
        if (pfCANDataCfmCb != NULL)
        {
            pfCANDataCfmCb ( (uint32_t)Idx, CANFD_NOT_COMPLETE );
        }
        /* Do not transmit */
    }
    else
    {
        /* Check Tx FIFO status, Read TXFQS */
        /*FlagTFQF = CPG_CANFD0_TXFQS_TFQF;*/
        FlagBO   = CPG_CANFD0_PSR_BO;
        /*if ((FlagTFQF != 0U) || (FlagBO != 0U))*/
        if ((FlagBO != 0U))
        {
            if (pfCANDataCfmCb != NULL)
            {
                pfCANDataCfmCb ( (uint32_t)Idx, CANFD_NOT_COMPLETE );
            }
        }
        else
        {
            /*** Calculate access pointer ***/
            Index     = Idx;
            pTxBuffer = ( CANFD_Tx_Buffer_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_TXBC_TBSA + 4U * Index );

            /*** Write transmission frame information to message RAM ***/
#if (CANFD_CH0_TX_ID_TYPE == CANFD_TX_STD_ID)
            pTxBuffer -> T0_f.XTD = 0U;                 /* 11-bit standard identifier */
            pTxBuffer -> T0_f.ID  = Identifier << 18U;  /* Standard identifier has to be written to ID[28:18] */
#else
            pTxBuffer -> T0_f.XTD = 1U;                 /* 29-bit extended identifier */
            pTxBuffer -> T0_f.ID  = Identifier;
#endif

            pTxBuffer -> T0_f.ESI = 0U;                   /* ESI bit in CAN FD format depends only on error passive flag */
            pTxBuffer -> T0_f.RTR = 0U;                   /* Transmit data frame */
            pTxBuffer -> T1_f.EFC = 0U;                   /* Dont store Tx events */
            pTxBuffer -> T1_f.MM  = 0U;                   /* Not used */
            pTxBuffer -> T1_f.DLC = DLC;                 /* Data Length Code */
            pTxBuffer -> T1_f.FDF = 0U;                   /* Classic CAN format */
            pTxBuffer -> T1_f.BRS = 0U;                   /* Transmitted without bit rate switching */

            if (DLC < 5U)
            {
                pTxBuffer -> Data[1] = 0x00000000UL;
            }
            else
            {
                Word = 0U;
                i    = 8U;
                while ( i > 4U )
                {
                    i--;
                    Word <<= 8U;
                    if ( i < DLC )
                    {
                        Word |= ( uint32_t ) Data[i];
                    }
                }
                pTxBuffer -> Data[1] = Word;
            }

            Word = 0U;
            i    = 4U;
            while (i > 0U)
            {
                i--;
                Word <<= 8U;
                if ( i < DLC )
                {
                    Word |= ( uint32_t ) Data[i];
                }
            }
            pTxBuffer -> Data[0] = Word;

            /*** Write to Tx Buffer Add Request ***/
            Word = 0x00000001UL << Index;
            CPG_CANFD0_TXBTIE |= Word;
            txMbState[Index] = 0x55u;
            CPG_CANFD0_TXBAR = Word;
        }
    }
#endif
}

uint16_t m_u16LastErrorCode = 0U;
void ErrorHandling ( void );
void ErrorHandling ( void )
{

    /* Access to Reserved Address */
    if ( CPG_CANFD0_IR_ARA == 1U )
    {
        m_u16LastErrorCode = 0x0001U;
    }

    /* Protocol Error in Data Phase */
    if ( CPG_CANFD0_IR_PED == 1U )
    {
        CPG_CANFD0_IR_PED = 1U;
        m_u16LastErrorCode = 0x0002U;
    }

    /* Protocol Error in Arbitration Phase */
    if ( CPG_CANFD0_IR_PEA == 1U )
    {
        CPG_CANFD0_IR_PEA = 1U;
        m_u16LastErrorCode = 0x0003U;
    }

    /* Watchdog Interrupt */
    if ( CPG_CANFD0_IR_WDI == 1U )
    {
        CPG_CANFD0_IR_WDI = 1U;
        m_u16LastErrorCode = 0x0004U;
    }

    /* Bus_Off Status Interrupt */
    if ( CPG_CANFD0_IR_BO == 1U )
    {
        CPG_CANFD0_IR_BO = 1U;
        m_u16LastErrorCode = 0x0005U;
    }

    /* Bit Error Uncorrected Interrupt */
    if ( CPG_CANFD0_IR_BEU == 1U )
    {
        CPG_CANFD0_IR_BEU = 1U;
        m_u16LastErrorCode = 0x0006U;
    }
} /* ErrorHandling */


static __irq __arm void CANFD_Ch0_Data_Reception_ISR(void)
{
    uint8_t   i;
    uint8_t   j;
    uint8_t   DLC;
    uint16_t  Index;
    uint32_t  Identifier;
    uint32_t  Flag;
    uint32_t  IndexBit;
    uint32_t  Word;
    uint8_t   Data[8];
    uint32_t  ResIdx;
    CANFD_Rx_Buffer_st_t *pRxBuffer;

    if ( CPG_CANFD0_IR & 0x3ff7E0EEUL )
    {
        ErrorHandling();
    }

    if ( CPG_CANFD0_IR_DRX )        /* New message in Rx buffer */
    {
        CPG_CANFD0_IR_DRX = 1U;
        Can_Set_Bus(1u);
        while ( CPG_CANFD0_NDAT1 )
        {
            Flag  = CPG_CANFD0_NDAT1;

#if CANFD_CH0_ENABLE
            Index    = 0U;
            IndexBit = 0xFFFFFFFFUL;

            for ( j = 0U; j < 6U; j++ )
            {
                Index  <<= 1U;
                if ( ( Flag & IndexBit ) == 0U )
                {
                    Index += 1U;
                }

                IndexBit = pCANFDRxBufferLookupData[j][Index];
            }

            pRxBuffer  = ( CANFD_Rx_Buffer_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_RXBC_RBSA + 4U * Index );

            if ( pRxBuffer -> R0_f.XTD )
            {
                Identifier = pRxBuffer -> R0_f.ID;
            }
            else
            {
                Identifier = pRxBuffer -> R0_f.ID >> 18U;
            }

            DLC = (uint8_t)(pRxBuffer -> R1_f.DLC);
            if ( DLC > 8U )
            {
                DLC = 8U;
            }

            for ( i = 0U; i < DLC; i++ )
            {
                if ( ( i & 0x03U ) == 0U )
                {
                    Word = pRxBuffer -> Data[i >> 2U];
                }

                Data[i]   = ( uint8_t ) Word;
                Word    >>= 8U;
            }

            if (pfCANDataIndCb != NULL)
            {
                pfCANDataIndCb ( Identifier, DLC, Data );
            }


            CPG_CANFD0_NDAT1 = IndexBit;
#else
            CPG_CANFD0_NDAT1 = Flag;
#endif
        }

        while ( CPG_CANFD0_NDAT2 )
        {
            Flag  = CPG_CANFD0_NDAT2;

#if CANFD_CH0_ENABLE
        Can_Set_Bus(1u);
            Index    = 0U;
            IndexBit = 0xFFFFFFFFUL;

            for ( j = 0U; j < 6U; j++ )
            {
                Index  <<= 1U;
                if ( ( Flag & IndexBit ) == 0U )
                {
                    Index += 1U;
                }

                IndexBit = pCANFDRxBufferLookupData[j][Index];
            }

            Index     += 32U;
            pRxBuffer  = ( CANFD_Rx_Buffer_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_RXBC_RBSA + 4U * Index );

            if ( pRxBuffer -> R0_f.XTD )
            {
                Identifier = pRxBuffer -> R0_f.ID;
            }
            else
            {
                Identifier = pRxBuffer -> R0_f.ID >> 18U;
            }

            DLC = (uint8_t)(pRxBuffer -> R1_f.DLC);
            if ( DLC > 8U )
            {
                DLC = 8U;
            }

            for ( i = 0U; i < DLC; i++ )
            {
                if ( ( i & 0x03U ) == 0U )
                {
                    Word = pRxBuffer -> Data[i >> 2U];
                }

                Data[i]   = ( uint8_t ) Word;
                Word    >>= 8U;
            }

            if (pfCANDataIndCb != NULL)
            {
                Can_BusOffRecover();
                pfCANDataIndCb ( Identifier, DLC, Data );
            }


            CPG_CANFD0_NDAT2 = IndexBit;
#else
            CPG_CANFD0_NDAT2 = Flag;
#endif
        }
    }

    if ( CPG_CANFD0_IR_RF0N )        /* New message in Rx FIFO 0 */
    {
        CPG_CANFD0_IR_RF0N = 1U;
        Can_Set_Bus(1u);
        while ( CPG_CANFD0_RXF0S_F0FL )
        {
#if CANFD_CH0_ENABLE
            Index      = (uint16_t)(CPG_CANFD0_RXF0S_F0GI);
            pRxBuffer  = ( CANFD_Rx_Buffer_st_t * ) ( ( uint32_t * ) CANFD_CH0_MSG_RAM_ADDR + CPG_CANFD0_RXF0C_F0SA + 4U * Index );

            if ( pRxBuffer -> R0_f.XTD )
            {
                Identifier = pRxBuffer -> R0_f.ID;
            }
            else
            {
                Identifier = pRxBuffer -> R0_f.ID >> 18U;
            }

            DLC = (uint8_t)(pRxBuffer -> R1_f.DLC);
            if ( DLC > 8U )
            {
                DLC = 8U;
            }

            for ( i = 0U; i < DLC; i++ )
            {
                if ( ( i & 0x03U ) == 0U )
                {
                    Word = pRxBuffer -> Data[i >> 2U];
                }

                Data[i]   = ( uint8_t ) Word;
                Word    >>= 8U;
            }
            if (pfCANDataIndCb != NULL)
            {
                pfCANDataIndCb( Identifier, DLC, Data );
            }


#endif
            CPG_CANFD0_RXF0A_F0AI = CPG_CANFD0_RXF0S_F0GI;
        }
    }
    if ( CPG_CANFD0_IR_RF1N )        /* New message in Rx FIFO 1 */
    {
        CPG_CANFD0_IR_RF1N = 1U;
        Can_Set_Bus(1u);
        while ( CPG_CANFD0_RXF1S_F1FL )
        {
            CPG_CANFD0_RXF1A_F1AI = CPG_CANFD0_RXF1S_F1GI;
        }

    }



    if ( CPG_CANFD0_IR_TCF )
    {
        /*CPG_CANFDx_TXBCF查询*/
        CPG_CANFD0_IR_TCF = 1U;
    }
    if ( CPG_CANFD0_IR_TC )        /* 发送完成中断 */
    {
      
        Can_BusOffRecover();
        /*CPG_CANFDx_TXBTO 查询*/
        IndexBit = CPG_CANFD0_TXBTO;
        IndexBit &= CPG_CANFD0_TXBTIE;

        for (Index = 0U; Index < 32u; Index++)
        {
            IndexBit = (CPG_CANFD0_TXBTO >> Index) & 1u;
            if (IndexBit && (txMbState[Index] != 0u))
            {
                Word = 0x00000001UL << Index;
                CPG_CANFD0_TXBTIE &= ~Word;
                txMbState[Index] = 0u;
                ResIdx = Index;
                if (pfCANDataCfmCb != NULL)
                {
                  pfCANDataCfmCb ( ResIdx, CANFD_COMPLETE );
                }
            }

        }
        CPG_CANFD0_IR_TC = 1U;
    }

    if ( CPG_CANFD0_IR_PEA ) /* Protocol Error in Arbitration Phase */
    {
        CPG_CANFD0_IR_PEA = 1U;

        /*
        if (pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDErrorInterruptFunction != NULL)
        {
            pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDErrorInterruptFunction(CanFDWarning);
        }
        */
    }
    if ( CPG_CANFD0_IR_PED ) /* Protocol Error in Data Phase */
    {
        CPG_CANFD0_IR_PED = 1U;

        /*
        if (pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDErrorInterruptFunction != NULL)
        {
            pstcCanFDInternData->stcCanFDNotificationCb.pfnCanFDErrorInterruptFunction(CanFDWarning);
        }
        */
    }




    IRC0_IRQHC = INTERRUPTS_IRQ_NUMBER_40;
}


void CANFD_CH0_Bus_Off_Recover( void )
{

    if ( CPG_CANFD0_PSR_BO ) /* CHECK BUSOFF EVENT */
    {
        CPG_CANFD0_CCCR_INIT = 0U;
    }
}


uint32_t CANFD_ReadBus_Sts(void)
{
    uint32_t Res;

    Res = 0u;
   /*
    if (CPG_CANFD0_PSR_LEC == 3u)
    {
        Res = 1u;
    }
    */
    if (CPG_CANFD0_PSR_BO == 1u)
    {
        Res = 1u;
    }
    return Res;
}

uint32_t CANFD_ReadNOACK_Sts(void)
{
    uint32_t Res;

    Res = 0u;
    if (CPG_CANFD0_PSR_LEC == 3u)
    {
        Res = 1u;
    }
    if (CPG_CANFD0_PSR_BO == 1u)
    {
        Res = 1u;
    }
    return Res;
}


uint32_t CANFD_ReadTX_Buf(void)
{
    uint32_t Res;
    Res = CPG_CANFD0_TXBAR;
    return Res;
}

uint32_t CANFD_ReadTX_Status(void)
{
    uint32_t Res;
    Res = CPG_CANFD0_TXBTO;
    return Res;
}

void CANFD_SetTX_Abort(uint32_t BufIdx)
{
    CPG_CANFD0_TXBCR = BufIdx;
}





/*
void CANFD_CH0_Sleep ( void )
{
    uint32_t Cancel;

    CPG_CANFD0_CCCR_INIT = 1U;
    Cancel = CPG_CANFD0_TXBAR;
    CPG_CANFD0_TXBCR = Cancel;

    if ( CPG_CANFD0_CCCR_CSR == 0U )
    {
        CPG_CANFD0_CCCR_CSR = 1U;
        CAN0_STB = 1U;
    }
}
*/
void CANFD_CH0_Sleep ( void )
{
    uint32_t Cancel;

    /*** Set CCCR.INIT to 1 and wait until it will be updated. ***/
    CPG_CANFD0_CCCR_INIT = 1U;
    while ( CPG_CANFD0_CCCR_INIT == 0U ) {}
    CPG_CANFD0_CCCR_CCE = 1U;        /* Enable configuration change */

    Cancel = CPG_CANFD0_TXBAR;
    CPG_CANFD0_TXBCR = Cancel;

    CPG_CANFD0_IE         = 0x00000000UL;  /* Disable all interrupts */
    CPG_CANFD0_IR         = 0x3FFFFFFFUL;  /* Clear all interrupt flags */
    CPG_CANFD0_ILE_EINT0  = 0U;            /* Enable interrupt line 0 */
    CPG_CANFD0_ILE_EINT1  = 0U;            /* Disable interrupt line 1 */

    if ( CPG_CANFD0_CCCR_CSR == 0U )
    {
        CPG_CANFD0_CCCR_CSR = 1U;
        CAN0_STB = 1U;
    }

}