/**
 *******************************************************************************
 * @file    dpm32m0xx_can.c
 *
 * @brief   Source file for CAN firmware driver.
 *          This file provides firmware functions to manage the following
 *          functionalities of the Controller area network (CAN) peripheral:
 *           + Initialization and Configuration
 *           + CAN Frames Transmission
 *           + CAN Frames Reception
 *           + Basic and peli modes switch
 *           + Error management
 *           + Interrupts and flags
 *
 * @author  DPM
 *
 * @version V1.0.0
 *
 * @date    2023-11-01
 *
 * @verbatim
 ===============================================================================
                       ##### How to use this driver #####
 ===============================================================================
    [..]
      (#) Enable the CAN controller interface clock using
          RCC_APBPeriphClockCmd(RCC_APB_PERIPH_CAN, ENABLE).

      (#) CAN pins configuration:
        (+) Enable the clock for the CAN GPIOs using the following function:
            RCC_AHBPeriphClockCmd(RCC_AHB_PERIPH_GPIO, ENABLE).
        (+) Configure these CAN pins in alternate function mode by calling
            the function GPIO_Init().
        (+) Connect the involved CAN pins to alternate function using the
            following function GPIO_AltFuncConfig().

    *** CAN basic mode configuration ***
    =============================================
      (#) Initialize and configure the CAN using CAN_Init() and
          CAN_FilterInit() functions.

      (#) Activate the CAN peripheral using CAN_Cmd() function.

      (#) Transmit the desired CAN frame using CAN_Transmit() function.

      (#) Check the transmission of a CAN frame using CAN_GetFlagStatus()
          function.

      (#) Cancel the transmission of a CAN frame using CAN_CancelTransmit()
          function.

      (#) Receive a CAN frame using CAN_Receive() function.

      (#) Release the receive FIFOs using CAN_ReceiveFIFORelease() function.

      (#) CAN basic mode interrupt configuration:
        (+) To activate the CAN interrupt, use CAN_IntCmd() functions.
        (+) Check on CAN interrupt enable flags using the function
            CAN_GetIntCmdStatus().
        (+) Check on CAN interrupt occur flags using the function
            CAN_GetIntFlagStatus().

    *** CAN peli mode configuration ***
    =============================================
      (#) Initialize and configure the CAN using CAN_PELI_Init() and
          CAN_PELI_FilterInit() functions.

      (#) Activate the CAN peripheral using CAN_PELI_Cmd() function.

      (#) Transmit the desired CAN frame using CAN_PELI_Transmit() function.

      (#) Check the transmission of a CAN frame using CAN_PELI_GetFlagStatus()
          function.

      (#) Cancel the transmission of a CAN frame using CAN_PELI_CancelTransmit()
          function.

      (#) Receive a CAN frame using CAN_PELI_Receive() function.

      (#) Release the receive FIFOs using CAN_PELI_ReceiveFIFORelease() function.

      (#) To analyze can error codes, use the CAN_PELI_GetErrorCodeCaptureReg()
          get the error code, then use CAN_PELI_ParseErrorType(),
          CAN_PELI_ParseErrorDirection() and CAN_PELI_ParseErrorSegment() to
          analyze it.

      (#) Get error count during communication. use the
           CAN_PELI_GetReceiveMessageCounter() ,CAN_PELI_GetReceiveErrorCounter()
          and CAN_PELI_GetTransmitErrorCounter() functions.

      (#) CAN peli mode interrupt configuration:
        (+) To activate the CAN peli mode interrupt, use CAN_PELI_IntCmd()
            functions.
        (+) Check on CAN peli mode interrupt enable flags using the function
            CAN_PELI_GetIntCmdStatus().
        (+) Check on CAN peli mode interrupt occur flags using the function
            CAN_PELI_GetIntFlagStatus().

 * @endverbatim
 *******************************************************************************/

#include "dpm32m0xx_can.h"

#if defined (DPM32M08x) && defined (DPM32M0xx_CAN_ENABLED)


#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wself-assign"
#endif


/**
 *******************************************************************************
 * @brief   Deinitializes the CAN peripheral registers to their default reset values.
 * @retval  None.
 ******************************************************************************/
void CAN_DeInit(void)
{
  /* Reset CAN control register. */
  CAN->CAN_BASEMODE.CTRL = (uint32_t)0x00000001;
  CAN->CAN_BASEMODE.EX_CAN = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.COMMAND = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.ACR = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.AMR = (uint32_t)0x000000FF;
  CAN->CAN_BASEMODE.BTR0 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.BTR1 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.CTRL = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_ID_BYTE1 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_ID_BYTE2 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA1 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA2 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA3 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA4 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA5 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA6 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA7 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.TX_DATA8 = (uint32_t)0x00000000;
  CAN->CAN_BASEMODE.CTRL = (uint32_t)0x00000021;
}

/**
 *******************************************************************************
 * @brief   Initializes the CAN peripheral basic functions according to the
 *          specified parameters in the CAN_InitType.
 * @param   [in]  CAN_InitType: Structure pointer of CAN configuration.
 * @retval  None.
 ******************************************************************************/
void CAN_Init(CAN_InitTypeStruct* CAN_InitType)
{
  /* Parameters check. */
  PARAM_ASSERT(IS_CAN_SJW(CAN_InitType->CAN_SyncJumpWidth));
  PARAM_ASSERT(IS_CAN_SAMPLING(CAN_InitType->CAN_Sampling));
  PARAM_ASSERT(IS_CAN_TSEG1(CAN_InitType->CAN_TimeSegment1));
  PARAM_ASSERT(IS_CAN_TSEG2(CAN_InitType->CAN_TimeSegment2));

  /* Request reset mode */
  CAN->CAN_BASEMODE.CTRL |= CAN_BASE_CTRL_RM_Msk;

  /* Set the CAN basic mode */
  CAN->CAN_BASEMODE.EX_CAN &= ~CAN_BASE_EX_CAN_EX_CAN_Msk;

  /* Set the bit BTR0 register */
  CAN->CAN_BASEMODE.BTR0 = (((uint32_t)CAN_InitType->CAN_SyncJumpWidth << CAN_BASE_BTR0_SJW_Pos) |
                            ((uint32_t)CAN_InitType->CAN_Prescaler << CAN_BASE_BTR0_BRP_Pos));

  /* Set the bit BTR1 register */
  CAN->CAN_BASEMODE.BTR1 = (((uint32_t)CAN_InitType->CAN_Sampling << CAN_BASE_BTR1_SAM_Pos) |
                            ((uint32_t)CAN_InitType->CAN_TimeSegment1 << CAN_BASE_BTR1_TSEG1_Pos) |
                            ((uint32_t)CAN_InitType->CAN_TimeSegment2 << CAN_BASE_BTR1_TSEG2_Pos));

  /* Exit reset mode */
  CAN->CAN_BASEMODE.CTRL &= ~CAN_BASE_CTRL_RM_Msk;
}

/**
 *******************************************************************************
 * @brief   Configures the CAN_Basic reception  according to the specified
 *          parameters in the CAN_FilterInitStruct.
 * @param   [in]  CAN_FilterInitStruct: Structure pointer of CAN_Basic reception
 *                filter configuration.
 * @retval  None.
 ******************************************************************************/
void CAN_FilterInit(CAN_FilterInitTypeStruct* CAN_FilterInitStruct)
{
  /* Request reset mode */
  CAN_ResetModeCmd(ENABLE);

  /* Filter Mode */
  CAN->CAN_BASEMODE.ACR = ((uint32_t)CAN_FilterInitStruct->CAN_FilterId << CAN_BASE_ACR_AC_Pos);

  /* Set the bit AMR register */
  CAN->CAN_BASEMODE.AMR = ((uint32_t)CAN_FilterInitStruct->CAN_FilterMaskId << CAN_BASE_AMR_AM_Pos);

  /* Exit reset mode */
  CAN_ResetModeCmd(DISABLE);
}

/**
 *******************************************************************************
 * @brief   Initialize the CAN_FilterInitStruct with default parameters.
 * @param   [in]  CAN_FilterInitStruct: Pointer to a CAN_FilterInitTypeStruct structure
 *                which will be initialized.
 * @retval  None.
 ******************************************************************************/
void CAN_FilterStructInit(CAN_FilterInitTypeStruct* CAN_FilterInitStruct)
{
  CAN_FilterInitStruct->CAN_FilterId = 0x00;
  CAN_FilterInitStruct->CAN_FilterMaskId = 0xFF;
}

/**
 *******************************************************************************
 * @brief   Initialize the CAN_InitType with default parameters.
 * @param   [in]  CAN_InitType: Pointer to a CAN_InitTypeStruct structure
 *                which will be initialized.
 * @retval  None.
 ******************************************************************************/
void CAN_StructInit(CAN_InitTypeStruct* CAN_InitType)
{
  CAN_InitType->CAN_Prescaler = 0x00;
  CAN_InitType->CAN_SyncJumpWidth = CAN_SJW_1TQ;
  CAN_InitType->CAN_Sampling = CAN_SAM_SINGLE;
  CAN_InitType->CAN_TimeSegment1 = CAN_TSEG1_1TQ;
  CAN_InitType->CAN_TimeSegment2 = CAN_TSEG2_1TQ;
}

/**
 *******************************************************************************
 * @brief   Enables or disables the specified CAN peripheral basic functions.
 * @param   [in]  Newstate: This parameter can be: ENABLE or DISABLE.
 * @retval  None.
 ******************************************************************************/
void CAN_Cmd(FunctionalState Newstate)
{
  if(DISABLE != Newstate)
  {
    /* Enable CAN peripheral basic functions. */
    CAN->CAN_BASEMODE.CTRL |= CAN_BASE_CTRL_EN_Msk;
  }
  else
  {
    /* Disable CAN peripheral basic functions. */
    CAN->CAN_BASEMODE.CTRL &= ~CAN_BASE_CTRL_EN_Msk;
  }
}

/**
 *******************************************************************************
 * @brief   Releases the receive FIFO.
 * @retval  None.
 ******************************************************************************/
void CAN_ReceiveFIFORelease(void)
{
  /* Release receive FIFO */
  CAN->CAN_BASEMODE.COMMAND = CAN_BASE_COMMAND_RRB_Msk;
}

/**
 *******************************************************************************
 * @brief   Cancels a transmit request.
 * @retval  None.
 ******************************************************************************/
void CAN_CancelTransmit(void)
{
  /* Abort transmission */
  CAN->CAN_BASEMODE.COMMAND = CAN_BASE_COMMAND_AT_Msk;
}

/**
 *******************************************************************************
 * @brief   Initiates and transmits a CAN frame message.
 * @param   [in]  TxMessage: Pointer to a structure which contains CAN Id, CAN DLC and CAN data.
 * @retval  None.
 ******************************************************************************/
void CAN_Transmit(CanBasicMsg* TxMessage)
{
  CAN->CAN_BASEMODE.TX_ID_BYTE1 = (TxMessage->ID >> 3) & 0xff;
  CAN->CAN_BASEMODE.TX_ID_BYTE2 = (uint32_t)(((TxMessage->ID & 0x7) << 5) \
                                  | (TxMessage->RTR << 4) | (TxMessage->DLC));

  CAN->CAN_BASEMODE.TX_DATA1 = TxMessage->Data[0];
  CAN->CAN_BASEMODE.TX_DATA2 = TxMessage->Data[1];
  CAN->CAN_BASEMODE.TX_DATA3 = TxMessage->Data[2];
  CAN->CAN_BASEMODE.TX_DATA4 = TxMessage->Data[3];
  CAN->CAN_BASEMODE.TX_DATA5 = TxMessage->Data[4];
  CAN->CAN_BASEMODE.TX_DATA6 = TxMessage->Data[5];
  CAN->CAN_BASEMODE.TX_DATA7 = TxMessage->Data[6];
  CAN->CAN_BASEMODE.TX_DATA8 = TxMessage->Data[7];

  CAN->CAN_BASEMODE.COMMAND = (CAN_BASE_COMMAND_TR_Msk | CAN_BASE_COMMAND_AT_Msk);
}

/**
 *******************************************************************************
 * @brief   Initiates and transmits a CAN frame message，enable automatic resend function.
 * @param   [in]  TxMessage: Pointer to a structure which contains CAN Id, CAN DLC and CAN data.
 * @retval  None.
 ******************************************************************************/
void CAN_TransmitRepeat(CanBasicMsg* TxMessage)
{
  CAN->CAN_BASEMODE.TX_ID_BYTE1 = (TxMessage->ID >> 3) & 0xff;
  CAN->CAN_BASEMODE.TX_ID_BYTE2 = (uint32_t)(((TxMessage->ID & 0x7) << 5) \
                                  | (TxMessage->RTR << 4) | (TxMessage->DLC));

  CAN->CAN_BASEMODE.TX_DATA1 = TxMessage->Data[0];
  CAN->CAN_BASEMODE.TX_DATA2 = TxMessage->Data[1];
  CAN->CAN_BASEMODE.TX_DATA3 = TxMessage->Data[2];
  CAN->CAN_BASEMODE.TX_DATA4 = TxMessage->Data[3];
  CAN->CAN_BASEMODE.TX_DATA5 = TxMessage->Data[4];
  CAN->CAN_BASEMODE.TX_DATA6 = TxMessage->Data[5];
  CAN->CAN_BASEMODE.TX_DATA7 = TxMessage->Data[6];
  CAN->CAN_BASEMODE.TX_DATA8 = TxMessage->Data[7];

  CAN->CAN_BASEMODE.COMMAND = CAN_BASE_COMMAND_TR_Msk;
}

/**
 *******************************************************************************
 * @brief   Receives a correct CAN frame.
 * @param   [in]  RxMessage: pointer to a structure receive frame which contains
 *                CAN Id,CAN DLC, CAN data and FMI number.
 * @retval  None.
 ******************************************************************************/
void CAN_Receive(CanBasicMsg* RxMessage)
{
  uint16_t tempid = 0;

  RxMessage->RTR = (uint8_t)((CAN->CAN_BASEMODE.RX_ID_BYTE2) >> 4) & 0x1;
  RxMessage->DLC = (uint8_t)((CAN->CAN_BASEMODE.RX_ID_BYTE2) & 0xf);

  tempid = (uint16_t)(((CAN->CAN_BASEMODE.RX_ID_BYTE2) & 0xe0) >> 5);
  tempid |= (uint16_t)(CAN->CAN_BASEMODE.RX_ID_BYTE1 << 3);

  RxMessage->ID = tempid;

  RxMessage->Data[0] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA1;
  RxMessage->Data[1] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA2;
  RxMessage->Data[2] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA3;
  RxMessage->Data[3] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA4;
  RxMessage->Data[4] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA5;
  RxMessage->Data[5] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA6;
  RxMessage->Data[6] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA7;
  RxMessage->Data[7] = (uint8_t)CAN->CAN_BASEMODE.RX_DATA8;

  CAN_ReceiveFIFORelease();
}

/**
 *******************************************************************************
 * @brief   Enables or disables the specified CAN basic interrupts.
 * @param   [in]  CAN_IntType: Specifies the UART interrupt.
 *                This parameter can be any combination of @ref CAN_IntTypeEnum.
 *                  @arg CAN_INT_TYPE_RX: Reception interrupt.
 *                  @arg CAN_INT_TYPE_TX: Transmission interrupt.
 *                  @arg CAN_INT_TYPE_ERR: Error interrupt.
 *                  @arg CAN_INT_TYPE_OVERRUN: Over run interrupt.
 *                  @arg CAN_INT_TYPE_OVERRHAP: Over run happen interrupt.
 * @param   [in]  Newstate: New state of the CAN basic interrupts.
 *                This parameter can be: ENABLE or DISABLE.
 * @retval  None.
 ******************************************************************************/
void CAN_IntCmd(uint32_t CAN_IntType, FunctionalState Newstate)
{
  if(DISABLE != Newstate)
  {
    /* Enable the interrupt for selected. */
    CAN->CAN_BASEMODE.CTRL |= (uint32_t)CAN_IntType;
  }
  else
  {
    /* Disable the interrupt for selected. */
    CAN->CAN_BASEMODE.CTRL &= ~(uint32_t)CAN_IntType;
  }
}

/**
 *******************************************************************************
 * @brief   Get the specified UART interrupt has enable or not.
 * @param   [in]  CAN_IntType: Specifies the UART interrupt.
 *                This parameter can be any combination of @ref CAN_IntTypeEnum.
 *                  @arg CAN_INT_TYPE_RX: Reception interrupt.
 *                  @arg CAN_INT_TYPE_TX: Transmission interrupt.
 *                  @arg CAN_INT_TYPE_ERR: Error interrupt.
 *                  @arg CAN_INT_TYPE_OVERRUN: Over run interrupt.
 *                  @arg CAN_INT_TYPE_OVERRHAP: Over run happen interrupt.
 * @param   [in]  state: New state of the CAN basic interrupts.
 * @retval  FunctionalState: The CAN interrupt state(ENABLE or DISABLE).
 ******************************************************************************/
FunctionalState CAN_GetIntCmdStatus(CAN_IntTypeEnum CAN_IntType)
{
  FunctionalState state = DISABLE;

  if(RESET != (CAN->CAN_BASEMODE.CTRL & (CAN_IntType)))
  {
    /* Interrupt is enable. */
    state = ENABLE;
  }
  else
  {
    /* Interrupt is disbale. */
    state = DISABLE;
  }

  /* Return the status of the interrupt enable bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief   Get the specified CAN flag is set or not.
 * @param   [in]  CAN_IntFlag: Specifies the CAN interrupt flag.
 *                This parameter can be a value of @ref CAN_IntFlagEnum.
 *                  @arg CAN_INT_FLAG_RX: Reception interrupt flag.
 *                  @arg CAN_INT_FLAG_TX: Transmission interrupt flag.
 *                  @arg CAN_INT_FLAG_ERR: Error interrupt flag.
 *                  @arg CAN_INT_FLAG_OVERRUN: Over run interrupt flag.
 *                  @arg CAN_INT_FLAG_OVERRHAP: Over run happen interrupt flag.
 * @retval  FlagState: The state of UART_IntFlag (SET or RESET).
 ******************************************************************************/
FlagState CAN_GetIntFlagStatus(CAN_IntFlagEnum CAN_IntFlag)
{
  FlagState state = RESET;

  /* Get the status of the Interrupt */
  if(RESET != (CAN->CAN_BASEMODE.INTERRUPT & ((uint32_t)CAN_IntFlag)))
  {
    state = SET;
  }
  else
  {
    state = RESET;
  }

  /* Return the status of the interrupt flag bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief   Get the specified CAN status bit is set or not.
 * @param   [in]  CAN_Status: Specifies the CAN status bit.
 *                This parameter can be a value of @ref CAN_FlagEnum.
 *                  @arg CAN_FLAG_RBS: Reception interrupt flag.
 *                  @arg CAN_FLAG_DOS: Transmission interrupt flag.
 *                  @arg CAN_FLAG_TBS: Error interrupt flag.
 *                  @arg CAN_FLAG_TCS: Over run interrupt flag.
 *                  @arg CAN_FLAG_RS: Over run happen interrupt flag.
 *                  @arg CAN_FLAG_TS: Transmission interrupt flag.
 *                  @arg CAN_FLAG_ES: Error interrupt flag.
 *                  @arg CAN_FLAG_BS: Bus flag.
 *                  @arg CAN_FLAG_OHS: Over run happen interrupt flag.
 * @retval  FlagState: The state of CAN_Status (SET or RESET).
 ******************************************************************************/
FlagState CAN_GetFlagStatus(CAN_FlagEnum CAN_Flag)
{
  FlagState state = RESET;

  /* Get the status of the Interrupt */
  if(RESET != (CAN->CAN_BASEMODE.STATUS & ((uint32_t)CAN_Flag)))
  {
    state = SET;
  }
  else
  {
    state = RESET;
  }

  /* Return the status of the status bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief   Enables or disables the specified CAN basic reset mode.
 * @param   [in]  NewState: New state of the CAN basic reset mode.
 *                This parameter can be: ENABLE or DISABLE.
 * @retval  None.
 ******************************************************************************/
void CAN_ResetModeCmd(FunctionalState NewState)
{
  if(DISABLE != NewState)
  {
    /* CAN go to reset mode. */
    CAN->CAN_BASEMODE.CTRL |= (uint32_t)CAN_BASE_CTRL_RM_Msk;
  }
  else
  {
    /* CAN go to normal mode. */
    CAN->CAN_BASEMODE.CTRL &= ~(uint32_t)CAN_BASE_CTRL_RM_Msk;
  }
}

/**
 *******************************************************************************
 * @brief   Clear the data overflow.
 * @retval  None.
 ******************************************************************************/
void CAN_ClearDataOverflow(void)
{
  CAN->CAN_BASEMODE.COMMAND = CAN_BASE_COMMAND_CDO_Msk;
}

/**
 *******************************************************************************
 * @brief   Clears the CAN interrupt pending bit.
 * @retval  None.
 ******************************************************************************/
void CAN_ClearIntPendingBit(void)
{
  uint32_t tmpReg = 0;

  tmpReg = tmpReg;

  /* Read this register clear all interrupt. */
  tmpReg = CAN->CAN_BASEMODE.INTERRUPT;
}




/********************************************* Peli Work function *********************************************/

/**
 *******************************************************************************
 * @brief  De-initialize the CAN peripheral registers to their default reset values.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_DeInit(void)
{
  /* Reset CAN control register. */
  CAN_PELI_ResetModeCmd(ENABLE);
  CAN->CAN_PELIMODE.EX_CAN = (uint32_t)0x00000080;
  CAN->CAN_PELIMODE.MODE = (uint32_t)0x00000001;
  CAN->CAN_PELIMODE.COMMAND = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.IE = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.BTR0 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.BTR1 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.EWL = (uint32_t)0x00000060;
  CAN->CAN_PELIMODE.RX_ERR = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.TX_ERR = (uint32_t)0x00000000;
  CAN_PELI_ResetModeCmd(DISABLE);
  CAN->CAN_PELIMODE.FRAME_INFO = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.ID1 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.ID2 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA1_ID3 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA2_ID4 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA3_DA1 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA4_DA2 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA5_DA3 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA6_DA4 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA7_DA5 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.DATA8_DA6 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.RES_DA7 = (uint32_t)0x00000000;
  CAN->CAN_PELIMODE.RES_DA8 = (uint32_t)0x00000000;
}

/**
 *******************************************************************************
 * @brief  Initializes the CAN peripheral according to the specified
 *         parameters in the CAN_Peli_InitType.
 * @param  [in]  CAN_Peli_InitType: pointer to a CAN_PELI_InitTypeStruct structure
 *               that contains the configuration information for the specified CAN peripheral.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_Init(CAN_PELI_InitTypeStruct* CAN_Peli_InitType)
{
  uint32_t tmpReg = 0UL;

  /* Parameters check. */
  PARAM_ASSERT(IS_CAN_PELI_EWL_VAL(CAN_Peli_InitType->CAN_PELI_ErrorWarningLimit));
  PARAM_ASSERT(IS_CAN_PELI_LOM(CAN_Peli_InitType->CAN_PELI_ListenOnlyMode));
  PARAM_ASSERT(IS_CAN_PELI_BRP_VAL(CAN_Peli_InitType->CAN_PELI_Prescaler));
  PARAM_ASSERT(IS_CAN_PELI_SAM(CAN_Peli_InitType->CAN_PELI_Sampling));
  PARAM_ASSERT(IS_CAN_PELI_STM(CAN_Peli_InitType->CAN_PELI_SelfTestMode));
  PARAM_ASSERT(IS_CAN_PELI_SJW(CAN_Peli_InitType->CAN_PELI_SyncJumpWidth));
  PARAM_ASSERT(IS_CAN_PELI_TSEG1(CAN_Peli_InitType->CAN_PELI_TimeSegment1));
  PARAM_ASSERT(IS_CAN_PELI_TSEG2(CAN_Peli_InitType->CAN_PELI_TimeSegment2));

  /* Request reset mode */
  CAN_PELI_ResetModeCmd(ENABLE);

  /* Set CAN to peli mode. */
  CAN->CAN_PELIMODE.EX_CAN |= CAN_PELI_EX_CAN_EX_CAN_Msk;

  /*-------------------------------------- CAN_PELI MOD Configuration --------------------------------------*/
  /* Get the CAN_PELI MODE value. */
  tmpReg = CAN->CAN_PELIMODE.MODE;

  /* Clear LOM bits. */
  tmpReg &= ~CAN_PELI_MODE_LOM_Msk;
  /* Set LOM bits according to CAN_PELI_ListenOnlyMode. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_ListenOnlyMode) << CAN_PELI_MODE_LOM_Pos);

  /* Clear STM bits. */
  tmpReg &= ~CAN_PELI_MODE_STM_Msk;
  /* Set STM bits according to CAN_PELI_SelfTestMode. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_SelfTestMode) << CAN_PELI_MODE_STM_Pos);

  /* Write to CAN_PELI MODE */
  CAN->CAN_PELIMODE.MODE = tmpReg;

  /*-------------------------------------- CAN_PELI EWLR Configuration --------------------------------------*/
  /* Clear EWL[7:0] bits. */
  CAN->CAN_PELIMODE.EWL &= ~CAN_PELI_EWL_EWL_Msk;
  /* Set EWL[7:0] bits according to CAN_PELI_ErrorWarningLimit. */
  CAN->CAN_PELIMODE.EWL |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_ErrorWarningLimit) << CAN_PELI_EWL_EWL_Pos);

  /*-------------------------------------- CAN_PELI BTR0 Configuration --------------------------------------*/
  /* Get the CAN_PELI BTR0 value */
  tmpReg = CAN->CAN_PELIMODE.BTR0;

  /* Clear SJW[1:0] bits. */
  tmpReg &= ~CAN_PELI_BTR0_SJW_Msk;
  /* Set SJW[1:0] bits according to CAN_PELI_SyncJumpWidth. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_SyncJumpWidth) << CAN_PELI_BTR0_SJW_Pos);

  /* Clear BRP[5:0] bits. */
  tmpReg &= ~CAN_PELI_BTR0_BRP_Msk;
  /* Set BRP[5:0] bits according to CAN_PELI_Prescaler. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_Prescaler) << CAN_PELI_BTR0_BRP_Pos);

  /* Write to CAN_PELI BTR0 */
  CAN->CAN_PELIMODE.BTR0 = tmpReg;

  /*-------------------------------------- CAN_PELI BTR1 Configuration --------------------------------------*/
  /* Get the CAN_PELI BTR1 value */
  tmpReg = CAN->CAN_PELIMODE.BTR1;

  /* Clear SAM bits. */
  tmpReg &= ~CAN_PELI_BTR1_SAM_Msk;
  /* Set SAM bits according to CAN_PELI_Sampling. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_Sampling) << CAN_PELI_BTR1_SAM_Pos);

  /* Clear TSEG1[3:0] bits. */
  tmpReg &= ~CAN_PELI_BTR1_TSEG1_Msk;
  /* Set TSEG1[3:0] bits according to CAN_PELI_TimeSegment1. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_TimeSegment1) << CAN_PELI_BTR1_TSEG1_Pos);

  /* Clear TSEG2[2:0] bits. */
  tmpReg &= ~CAN_PELI_BTR1_TSEG2_Msk;
  /* Set TSEG2[2:0] bits according to CAN_PELI_TimeSegment2. */
  tmpReg |= (((uint32_t)CAN_Peli_InitType->CAN_PELI_TimeSegment2) << CAN_PELI_BTR1_TSEG2_Pos);

  /* Write to CAN_PELI BTR1 */
  CAN->CAN_PELIMODE.BTR1 = tmpReg;

  /* Exit reset mode */
  CAN_PELI_ResetModeCmd(DISABLE);
}

/**
 *******************************************************************************
 * @brief  Fills each CAN_Peli_InitType member with its default value.
 * @param  [out] CAN_Peli_InitType: pointer to a SPI_InitTypeStruct structure
 *               which will be initialized.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_StructInit(CAN_PELI_InitTypeStruct* CAN_Peli_InitType)
{
  /*---------------- Reset CAN_PELI init structure parameters values --------------*/
  /* Initialize the CAN_PELI_ErrorWarningLimit member */
  CAN_Peli_InitType->CAN_PELI_ErrorWarningLimit = 0x96;
  /* Initialize the CAN_PELI_ListenOnlyMode member */
  CAN_Peli_InitType->CAN_PELI_ListenOnlyMode = CAN_PELI_LOM_DISABLE;
  /* Initialize the CAN_PELI_Prescaler member */
  CAN_Peli_InitType->CAN_PELI_Prescaler = 0x0;
  /* Initialize the CAN_PELI_Sampling member */
  CAN_Peli_InitType->CAN_PELI_Sampling = CAN_SAM_SINGLE;
  /* Initialize the CAN_PELI_SelfTestMode member */
  CAN_Peli_InitType->CAN_PELI_SelfTestMode = CAN_PELI_STM_DISABLE;
  /* Initialize the CAN_PELI_SyncJumpWidth member */
  CAN_Peli_InitType->CAN_PELI_SyncJumpWidth = CAN_SJW_1TQ;
  /* Initialize the CAN_PELI_TimeSegment1 member */
  CAN_Peli_InitType->CAN_PELI_TimeSegment1 = 0x0;
  /* Initialize the CAN_PELI_TimeSegment2 member */
  CAN_Peli_InitType->CAN_PELI_TimeSegment2 = 0x0;
}

/**
 *******************************************************************************
 * @brief  Enables or disables the specified CAN peripheral.
 * @param  [in]  Newstate: new state of the CAN peripheral.
 *               Any value of @ref FunctionalState.
 *               @arg DISABLE: disbale CAN peripheral.
 *               @arg ENABLE: enable CAN peripheral.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_Cmd(FunctionalState Newstate)
{
  if(Newstate != DISABLE)
  {
    /* Enable the selected CAN_PELI peripheral */
    CAN->CAN_PELIMODE.MODE |= CAN_PELI_MODE_EN_Msk;
  }
  else
  {
    /* Disable the selected CAN_PELI peripheral */
    CAN->CAN_PELIMODE.MODE &= (uint32_t)~((uint32_t)CAN_PELI_MODE_EN_Msk);
  }
}

/**
 *******************************************************************************
 * @brief  Initialize the CAN peripheral filter according to the parameters
 *         specified in CAN_Peli_FilterInitType.
 * @param  [in]  CAN_Peli_FilterInitType: pointer to a CAN_PELI_FilterInitTypeStruct structure
 *               that contains the configuration information for the specified CAN peripheral filter.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_FilterInit(CAN_PELI_FilterInitTypeStruct* CAN_Peli_FilterInitType)
{
  /* Parameters check. */
  PARAM_ASSERT(IS_CAN_PELI_AFM(CAN_Peli_FilterInitType->CAN_PELI_AcceptanceFilterMode));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_ID_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterId0));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_ID_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterId1));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_ID_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterId2));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_ID_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterId3));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_MASK_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId0));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_MASK_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId1));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_MASK_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId2));
  PARAM_ASSERT(IS_CAN_PELI_FILTER_MASK_VAL(CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId3));

  /* Request reset mode */
  CAN_PELI_ResetModeCmd(ENABLE);

  /*-------------------------------------- CAN_PELI MOD Configuration --------------------------------------*/
  /* Clear AFM bits. */
  CAN->CAN_PELIMODE.MODE &= ~CAN_PELI_MODE_AFM_Msk;
  /* Set AFM bits according to CAN_PELI_AcceptanceFilterMode. */
  CAN->CAN_PELIMODE.MODE |= (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_AcceptanceFilterMode) << CAN_PELI_MODE_AFM_Pos);

  /*-------------------------------------- CAN_PELI MR0~MR7 Configuration --------------------------------------*/
  /* Set FRAME_INFO bits according to CAN_PELI_FilterId0. */
  CAN->CAN_PELIMODE.FRAME_INFO = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterId0));
  /* Set ID1 bits according to CAN_PELI_FilterId1. */
  CAN->CAN_PELIMODE.ID1 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterId1));
  /* Set ID2 bits according to CAN_PELI_FilterId2. */
  CAN->CAN_PELIMODE.ID2 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterId2));
  /* Set DATA1_ID3 bits according to CAN_PELI_FilterId3. */
  CAN->CAN_PELIMODE.DATA1_ID3 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterId3));

  /* Set DATA2_ID4 bits according to CAN_PELI_FilterMaskId0. */
  CAN->CAN_PELIMODE.DATA2_ID4 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId0));
  /* Set DATA3_DA1 bits according to CAN_PELI_FilterMaskId1. */
  CAN->CAN_PELIMODE.DATA3_DA1 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId1));
  /* Set DATA4_DA2 bits according to CAN_PELI_FilterMaskId2. */
  CAN->CAN_PELIMODE.DATA4_DA2 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId2));
  /* Set DATA5_DA3 bits according to CAN_PELI_FilterMaskId3. */
  CAN->CAN_PELIMODE.DATA5_DA3 = (((uint32_t)CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId3));

  /* Exit reset mode */
  CAN_PELI_ResetModeCmd(DISABLE);
}

/**
 *******************************************************************************
 * @brief  Fills each CAN_Peli_FilterInitType member with its default value.
 * @param  [out] CAN_Peli_FilterInitType: pointer to a CAN_PELI_FilterInitTypeStruct
 *                  structure which will be initialized.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_FilterStructInit(CAN_PELI_FilterInitTypeStruct *CAN_Peli_FilterInitType)
{
  /*---------------- Reset CAN_PELI init structure parameters values --------------*/

  /* Initialize the CAN_PELI_AcceptanceFilterMode member */
  CAN_Peli_FilterInitType->CAN_PELI_AcceptanceFilterMode = CAN_PELI_AFM_DUAL;
  /* Initialize the CAN_PELI_FilterId0 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterId0 = 0x00;
  /* Initialize the CAN_PELI_FilterId1 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterId1 = 0x00;
  /* Initialize the CAN_PELI_FilterId2 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterId2 = 0x00;
  /* Initialize the CAN_PELI_FilterId3 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterId3 = 0x00;
  /* Initialize the CAN_PELI_FilterMaskId0 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId0 = 0x00;
  /* Initialize the CAN_PELI_FilterMaskId1 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId1 = 0x00;
  /* Initialize the CAN_PELI_FilterMaskId2 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId2 = 0x00;
  /* Initialize the CAN_PELI_FilterMaskId3 member */
  CAN_Peli_FilterInitType->CAN_PELI_FilterMaskId3 = 0x00;
}

/**
 *******************************************************************************
 * @brief  Enable or disable CAN reset mode.
 * @param  [in]  Newstate: new state for entering or exiting reset mode.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: Exit reset mode.
 *                 @arg ENABLE: Enter reset mode.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_ResetModeCmd(FunctionalState Newstate)
{
  if(Newstate != DISABLE)
  {
    /* Enable the CAN reset mode. */
    CAN->CAN_PELIMODE.MODE |= CAN_PELI_MODE_RM_Msk;
  }
  else
  {
    /* Disable the CAN_PELI reset mode. */
    CAN->CAN_PELIMODE.MODE &= (uint32_t)~((uint32_t)CAN_PELI_MODE_RM_Msk);
  }
}

/**
 *******************************************************************************
 * @brief  Clear the data overflow.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_ClearDataOverflow(void)
{
  CAN->CAN_PELIMODE.COMMAND = CAN_PELI_COMMAND_CDO_Msk;
}

/**
 *******************************************************************************
 * @brief  Clears the CAN IT pending.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_ClearITPendingBit(void)
{
  uint32_t temp = 0;

  temp = temp;

  /* read this register clear all interrupt */
  temp = CAN->CAN_PELIMODE.INTERRUPT;
}

/**
 *******************************************************************************
 * @brief  Initiates and transmits a CAN frame message.
 * @param  [in]  TxMessage: pointer to a structure which contains
 *               CAN Id, CAN DLC and CAN data.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_Transmit(CanPeliMsg* TxMessage)
{
  /* Configuring CAN_SFF: IDE, RTR and DLC. */
  CAN->CAN_PELIMODE.FRAME_INFO = (((uint32_t)TxMessage->IDE << CAN_PELI_SFF_FF_Pos) |
                                  ((uint32_t)TxMessage->RTR << CAN_PELI_SFF_RTR_Pos) |
                                  ((uint32_t)TxMessage->DLC << CAN_PELI_SFF_DLC_Pos));

  if(TxMessage->IDE == CAN_PELI_IDE_STD)
  {
    /* Configure standard Frame identifiers. */
    CAN->CAN_PELIMODE.ID1 = (((uint32_t)TxMessage->ID >> 3) & CAN_PELI_ID1_ID1_Msk);
    CAN->CAN_PELIMODE.ID2 = (((uint32_t)TxMessage->ID << 5) & CAN_PELI_ID2_ID2_Msk);
    /* Copy data to transmit data register. */
    CAN->CAN_PELIMODE.DATA1_ID3 = (uint32_t)TxMessage->Data[0];
    CAN->CAN_PELIMODE.DATA2_ID4 = (uint32_t)TxMessage->Data[1];
    CAN->CAN_PELIMODE.DATA3_DA1 = (uint32_t)TxMessage->Data[2];
    CAN->CAN_PELIMODE.DATA4_DA2 = (uint32_t)TxMessage->Data[3];
    CAN->CAN_PELIMODE.DATA5_DA3 = (uint32_t)TxMessage->Data[4];
    CAN->CAN_PELIMODE.DATA6_DA4 = (uint32_t)TxMessage->Data[5];
    CAN->CAN_PELIMODE.DATA7_DA5 = (uint32_t)TxMessage->Data[6];
    CAN->CAN_PELIMODE.DATA8_DA6 = (uint32_t)TxMessage->Data[7];
  }
  else
  {
    /* Configure extended frame identifiers. */
    CAN->CAN_PELIMODE.ID1 = (((uint32_t)TxMessage->ID >> 21) & CAN_PELI_ID1_ID1_Msk);
    CAN->CAN_PELIMODE.ID2 = (((uint32_t)TxMessage->ID >> 13) & CAN_PELI_ID2_ID2_Msk);
    CAN->CAN_PELIMODE.DATA1_ID3 = (((uint32_t)TxMessage->ID >> 5) & CAN_PELI_DATA1_ID3_DATA1_ID3_Msk);
    CAN->CAN_PELIMODE.DATA2_ID4 = (((uint32_t)TxMessage->ID << 3) & CAN_PELI_DATA2_ID4_DATA2_ID4_Msk);
    /* Copy data to transmit data register. */
    CAN->CAN_PELIMODE.DATA3_DA1 = (uint32_t)TxMessage->Data[0];
    CAN->CAN_PELIMODE.DATA4_DA2 = (uint32_t)TxMessage->Data[1];
    CAN->CAN_PELIMODE.DATA5_DA3 = (uint32_t)TxMessage->Data[2];
    CAN->CAN_PELIMODE.DATA6_DA4 = (uint32_t)TxMessage->Data[3];
    CAN->CAN_PELIMODE.DATA7_DA5 = (uint32_t)TxMessage->Data[4];
    CAN->CAN_PELIMODE.DATA8_DA6 = (uint32_t)TxMessage->Data[5];
    CAN->CAN_PELIMODE.RES_DA7 = (uint32_t)TxMessage->Data[6];
    CAN->CAN_PELIMODE.RES_DA8 = (uint32_t)TxMessage->Data[7];
  }

  /* Transmission request  */
  if(CAN->CAN_PELIMODE.MODE & CAN_PELI_MODE_STM_Msk)
  {
    CAN->CAN_PELIMODE.COMMAND = (CAN_PELI_COMMAND_SRR_Msk | CAN_PELI_COMMAND_AT_Msk);
  }
  else
  {
    CAN->CAN_PELIMODE.COMMAND = (CAN_PELI_COMMAND_TR_Msk | CAN_PELI_COMMAND_AT_Msk);
  }
}

/**
 *******************************************************************************
 * @brief  Initiates and transmits a CAN frame message，enable automatic resend function.
 * @param  [in]  TxMessage: pointer to a structure which contains
 *               CAN Id, CAN DLC and CAN data.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_TransmitRepeat(CanPeliMsg* TxMessage)
{
  /* Configuring CAN_SFF: IDE, RTR and DLC. */
  CAN->CAN_PELIMODE.FRAME_INFO = (((uint32_t)TxMessage->IDE << CAN_PELI_SFF_FF_Pos) |
                                  ((uint32_t)TxMessage->RTR << CAN_PELI_SFF_RTR_Pos) |
                                  ((uint32_t)TxMessage->DLC << CAN_PELI_SFF_DLC_Pos));

  if(TxMessage->IDE == CAN_PELI_IDE_STD)
  {
    /* Configure standard Frame identifiers. */
    CAN->CAN_PELIMODE.ID1 = (((uint32_t)TxMessage->ID >> 3) & CAN_PELI_ID1_ID1_Msk);
    CAN->CAN_PELIMODE.ID2 = (((uint32_t)TxMessage->ID << 5) & CAN_PELI_ID2_ID2_Msk);
    /* Copy data to transmit data register. */
    CAN->CAN_PELIMODE.DATA1_ID3 = (uint32_t)TxMessage->Data[0];
    CAN->CAN_PELIMODE.DATA2_ID4 = (uint32_t)TxMessage->Data[1];
    CAN->CAN_PELIMODE.DATA3_DA1 = (uint32_t)TxMessage->Data[2];
    CAN->CAN_PELIMODE.DATA4_DA2 = (uint32_t)TxMessage->Data[3];
    CAN->CAN_PELIMODE.DATA5_DA3 = (uint32_t)TxMessage->Data[4];
    CAN->CAN_PELIMODE.DATA6_DA4 = (uint32_t)TxMessage->Data[5];
    CAN->CAN_PELIMODE.DATA7_DA5 = (uint32_t)TxMessage->Data[6];
    CAN->CAN_PELIMODE.DATA8_DA6 = (uint32_t)TxMessage->Data[7];
  }
  else
  {
    /* Configure extended frame identifiers. */
    CAN->CAN_PELIMODE.ID1 = (((uint32_t)TxMessage->ID >> 21) & CAN_PELI_ID1_ID1_Msk);
    CAN->CAN_PELIMODE.ID2 = (((uint32_t)TxMessage->ID >> 13) & CAN_PELI_ID2_ID2_Msk);
    CAN->CAN_PELIMODE.DATA1_ID3 = (((uint32_t)TxMessage->ID >> 5) & CAN_PELI_DATA1_ID3_DATA1_ID3_Msk);
    CAN->CAN_PELIMODE.DATA2_ID4 = (((uint32_t)TxMessage->ID << 3) & CAN_PELI_DATA2_ID4_DATA2_ID4_Msk);
    /* Copy data to transmit data register. */
    CAN->CAN_PELIMODE.DATA3_DA1 = (uint32_t)TxMessage->Data[0];
    CAN->CAN_PELIMODE.DATA4_DA2 = (uint32_t)TxMessage->Data[1];
    CAN->CAN_PELIMODE.DATA5_DA3 = (uint32_t)TxMessage->Data[2];
    CAN->CAN_PELIMODE.DATA6_DA4 = (uint32_t)TxMessage->Data[3];
    CAN->CAN_PELIMODE.DATA7_DA5 = (uint32_t)TxMessage->Data[4];
    CAN->CAN_PELIMODE.DATA8_DA6 = (uint32_t)TxMessage->Data[5];
    CAN->CAN_PELIMODE.RES_DA7 = (uint32_t)TxMessage->Data[6];
    CAN->CAN_PELIMODE.RES_DA8 = (uint32_t)TxMessage->Data[7];
  }

  /* Transmission request  */
  if(CAN->CAN_PELIMODE.MODE & CAN_PELI_MODE_STM_Msk)
  {
    CAN->CAN_PELIMODE.COMMAND = CAN_PELI_COMMAND_SRR_Msk;
  }
  else
  {
    CAN->CAN_PELIMODE.COMMAND = CAN_PELI_COMMAND_TR_Msk;
  }
}

/**
 *******************************************************************************
 * @brief  Receives a correct CAN frame.
 * @param  [in]  RxMessage: pointer to a structure receive frame which contains CAN Id,
 *               CAN DLC, CAN data and FMI number.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_Receive(CanPeliMsg* RxMessage)
{
  /* Get frame information: IDE, RTR and DLC. */
  RxMessage->IDE = (uint8_t)((CAN->CAN_PELIMODE.FRAME_INFO & CAN_PELI_SFF_FF_Msk) >> CAN_PELI_SFF_FF_Pos);
  RxMessage->RTR = (uint8_t)((CAN->CAN_PELIMODE.FRAME_INFO & CAN_PELI_SFF_RTR_Msk) >> CAN_PELI_SFF_RTR_Pos);
  RxMessage->DLC = (uint8_t)((CAN->CAN_PELIMODE.FRAME_INFO & CAN_PELI_SFF_DLC_Msk) >> CAN_PELI_SFF_DLC_Pos);

  if(CAN_PELI_IDE_STD == (CAN_PELI_IDEEnum)RxMessage->IDE)
  {
    /* Get standard frame identifiers. */
    RxMessage->ID = (((uint32_t)(CAN->CAN_PELIMODE.ID1 & CAN_PELI_ID1_ID1_Msk) << 3) |
                     ((uint32_t)(CAN->CAN_PELIMODE.ID2 & CAN_PELI_ID2_ID2_Msk) >> 5));
    /* Get data from receive FIFO. */
    RxMessage->Data[0] = (uint8_t)CAN->CAN_PELIMODE.DATA1_ID3;
    RxMessage->Data[1] = (uint8_t)CAN->CAN_PELIMODE.DATA2_ID4;
    RxMessage->Data[2] = (uint8_t)CAN->CAN_PELIMODE.DATA3_DA1;
    RxMessage->Data[3] = (uint8_t)CAN->CAN_PELIMODE.DATA4_DA2;
    RxMessage->Data[4] = (uint8_t)CAN->CAN_PELIMODE.DATA5_DA3;
    RxMessage->Data[5] = (uint8_t)CAN->CAN_PELIMODE.DATA6_DA4;
    RxMessage->Data[6] = (uint8_t)CAN->CAN_PELIMODE.DATA7_DA5;
    RxMessage->Data[7] = (uint8_t)CAN->CAN_PELIMODE.DATA8_DA6;
  }
  else
  {
    /* Get standard frame identifiers. */
    RxMessage->ID = (((uint32_t)(CAN->CAN_PELIMODE.ID1 & CAN_PELI_ID1_ID1_Msk) << 21) |
                     ((uint32_t)(CAN->CAN_PELIMODE.ID2 & CAN_PELI_ID2_ID2_Msk) << 13) |
                     ((uint32_t)(CAN->CAN_PELIMODE.DATA1_ID3 & CAN_PELI_DATA1_ID3_DATA1_ID3_Msk) << 5) |
                     ((uint32_t)(CAN->CAN_PELIMODE.DATA2_ID4 & CAN_PELI_DATA2_ID4_DATA2_ID4_Msk) >> 3));
    /* Get data from receive FIFO. */
    RxMessage->Data[0] = (uint8_t)CAN->CAN_PELIMODE.DATA3_DA1;
    RxMessage->Data[1] = (uint8_t)CAN->CAN_PELIMODE.DATA4_DA2;
    RxMessage->Data[2] = (uint8_t)CAN->CAN_PELIMODE.DATA5_DA3;
    RxMessage->Data[3] = (uint8_t)CAN->CAN_PELIMODE.DATA6_DA4;
    RxMessage->Data[4] = (uint8_t)CAN->CAN_PELIMODE.DATA7_DA5;
    RxMessage->Data[5] = (uint8_t)CAN->CAN_PELIMODE.DATA8_DA6;
    RxMessage->Data[6] = (uint8_t)CAN->CAN_PELIMODE.RES_DA7;
    RxMessage->Data[7] = (uint8_t)CAN->CAN_PELIMODE.RES_DA8;
  }

  /* Release receive buffer. */
  CAN_PELI_ReceiveFIFORelease();
}

/**
 *******************************************************************************
 * @brief  Cancels a transmit request.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_CancelTransmit(void)
{
  /* Abort transmission. */
  CAN->CAN_PELIMODE.COMMAND = CAN_PELI_COMMAND_AT_Msk;
}

/**
 *******************************************************************************
 * @brief  Releases the specified receive FIFO.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_ReceiveFIFORelease(void)
{
  /* Release FIFO. */
  CAN->CAN_PELIMODE.COMMAND = CAN_PELI_COMMAND_RRB_Msk;
}

/**
 *******************************************************************************
 * @brief  Get CAN arbitration lost bit.
 * @retval CAN_PELI_ARBLostBitEnum: arbitration lost bit.
 *         Any value of @ref CAN_PELI_ARBLostBitEnum.
 *           @arg CAN_PELI_ARBLOST_BIT_1: arbitration lost in bit 1 of identifier
 *           @arg CAN_PELI_ARBLOST_BIT_2: arbitration lost in bit 2 of identifier
 *           ...
 *           @arg CAN_PELI_ARBLOST_BIT_29: arbitration lost in bit 19 of identifier
 *           @arg CAN_PELI_ARBLOST_BIT_RTR: arbitration lost in bit RTR
 ******************************************************************************/
CAN_PELI_ARBLostBitEnum CAN_PELI_GetArbitrationLostBit(void)
{
  return (CAN_PELI_ARBLostBitEnum)(CAN->CAN_PELIMODE.ALC & CAN_PELI_ALC_ALC_Msk);
}

/**
 *******************************************************************************
 * @brief  Get CAN Peli mode error code capture register value.
 * @retval uint32_t: error code capture register value.
 ******************************************************************************/
uint32_t CAN_PELI_GetErrorCodeCaptureReg(void)
{
  return CAN->CAN_PELIMODE.ECC;
}

/**
 *******************************************************************************
 * @brief  Get CAN error type.
 * @retval CAN_PELI_ErrTypeEnum: error type.
 *         Any value of @ref CAN_PELI_ErrTypeEnum.
 *           @arg CAN_PELI_ERRTYPE_BIT: bit error
 *           @arg CAN_PELI_ERRTYPE_FORMAT: format error
 *           @arg CAN_PELI_ERRTYPE_STUFF: stuff error
 *           @arg CAN_PELI_ERRTYPE_OTHER: other type of error
 ******************************************************************************/
CAN_PELI_ErrTypeEnum CAN_PELI_ParseErrorType(uint32_t ErrorCode)
{
  return (CAN_PELI_ErrTypeEnum)((ErrorCode & CAN_PELI_ECC_ERRC_Msk) >> CAN_PELI_ECC_ERRC_Pos);
}

/**
 *******************************************************************************
 * @brief  Get CAN error direction.
 * @retval CAN_PELI_ErrDirectionEnum: error direction.
 *         Any value of @ref CAN_PELI_ErrDirectionEnum.
 *           @arg CAN_PELI_ERRDIR_TRANSMITTER: error while sending
 *           @arg CAN_PELI_ERRDIR_RECEIVER: error while receiving
 ******************************************************************************/
CAN_PELI_ErrDirectionEnum CAN_PELI_ParseErrorDirection(uint32_t ErrorCode)
{
  return (CAN_PELI_ErrDirectionEnum)!((ErrorCode & CAN_PELI_ECC_DIR_Msk) >> CAN_PELI_ECC_DIR_Pos);
}

/**
 *******************************************************************************
 * @brief  Get CAN error segment.
 * @retval CAN_PELI_ErrSegmentEnum: error segment.
 *         Any value of @ref CAN_PELI_ErrSegmentEnum.
 *           @arg CAN_PELI_ERRSEG_ID28_21: ID.28 to ID.21
 *           @arg CAN_PELI_ERRSEG_START_FRAME: start of frame
 *           ...
 *           @arg CAN_PELI_ERRSEG_ACK_OVERLOAD: overload flag
 *           @arg CAN_PELI_ERRSEG_ACK_UNKNOWN: unknown
 ******************************************************************************/
CAN_PELI_ErrSegmentEnum CAN_PELI_ParseErrorSegment(uint32_t ErrorCode)
{
  CAN_PELI_ErrSegmentEnum errSeg;

  uint8_t eccSeg = (uint8_t)((ErrorCode & CAN_PELI_ECC_SEG_Msk) >> CAN_PELI_ECC_SEG_Pos);

  if(eccSeg >= (uint8_t)CAN_PELI_ERRSEG_ID28_21 || eccSeg <= (uint8_t)CAN_PELI_ERRSEG_ACK_OVERLOAD)
  {
    errSeg = (CAN_PELI_ErrSegmentEnum)eccSeg;

    if(eccSeg == CAN_PELI_ERRSEG_ACK_DELIMITER && CAN_PELI_ParseErrorType(ErrorCode) == CAN_PELI_ERRTYPE_OTHER)
    {
      errSeg = CAN_PELI_ERRSEG_CRC;
    }
  }
  else
  {
    errSeg =  CAN_PELI_ERRSEG_ACK_UNKNOWN;
  }

  return errSeg;
}

/**
 *******************************************************************************
 * @brief  Returns the CAN receive message counter.
 * @retval uint8_t: CAN receive message counter.
 ******************************************************************************/
uint8_t CAN_PELI_GetReceiveMessageCounter(void)
{
  return (uint8_t)CAN->CAN_PELIMODE.RMC;
}

/**
 *******************************************************************************
 * @brief  Returns the CAN receive error counter.
 * @retval uint8_t: CAN receive error counter.
 ******************************************************************************/
uint8_t CAN_PELI_GetReceiveErrorCounter(void)
{
  return (uint8_t)CAN->CAN_PELIMODE.RX_ERR;
}

/**
 *******************************************************************************
 * @brief  Returns the CAN transmitter error counter.
 * @retval uint8_t: CAN transmitter error counter.
 ******************************************************************************/
uint8_t CAN_PELI_GetTransmitErrorCounter(void)
{
  return (uint8_t)CAN->CAN_PELIMODE.TX_ERR;
}

/**
 *******************************************************************************
 * @brief  Set the CAN receive error counter.
 * @param  [in]  ErrorCnt: New incorrect count value.
 ******************************************************************************/
void CAN_PELI_SetReceiveErrorCounter(uint8_t ErrorCnt)
{
  CAN->CAN_PELIMODE.RX_ERR = (uint32_t)ErrorCnt;
}

/**
 *******************************************************************************
 * @brief  Set the CAN transmitter error counter.
 * @param  [in]  ErrorCnt: New incorrect count value.
 ******************************************************************************/
void CAN_PELI_SetTransmitErrorCounter(uint8_t ErrorCnt)
{
  CAN->CAN_PELIMODE.TX_ERR = (uint32_t)ErrorCnt;
}

/**
 *******************************************************************************
 * @brief  Enables or disables the specified CAN interrupts in peli workmode.
 * @param  [in]  CAN_PELI_IntType: specifies the CAN interrupt sources to be enabled or disabled.
 *               Any value of @ref CAN_PELI_IntTypeEnum.
 *                 @arg CAN_PELI_INT_TYPE_OVERR_HAP: overrun happen interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_BUS_ERR: bus error interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ARB_LOST: arbitration lost interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ERR_PASSIVE: error passive interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_OVERR: data overrun interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ERR_WARRING: error warning interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_TX: transmit interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_RX: receive interrupt enable.
 * @param  [in]  Newstate: new state of the specified CAN interrupts.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: disbale CAN interrupt.
 *                 @arg ENABLE: enable CAN interrupt.
 * @retval None.
 ******************************************************************************/
void CAN_PELI_IntCmd(uint32_t CAN_PELI_IntType, FunctionalState Newstate)
{
  if(Newstate != DISABLE)
  {
    /*Enable the selected CAN_PELI interrupt */
    CAN->CAN_PELIMODE.IE |= ((uint32_t)CAN_PELI_IntType);
  }
  else
  {
    /* Disable the selected CAN_PELI interrupt */
    CAN->CAN_PELIMODE.IE &= ((uint32_t)~CAN_PELI_IntType);
  }
}

/**
 *******************************************************************************
 * @brief  Get the specified CAN interrupt has enable or not.
 * @param  [in]  CAN_PELI_IntType: specifies the CAN interrupt sources to be enabled or disabled.
 *               Any value of @ref CAN_PELI_IntTypeEnum.
 *                 @arg CAN_PELI_INT_TYPE_OVERR_HAP: overrun happen interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_BUS_ERR: bus error interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ARB_LOST: arbitration lost interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ERR_PASSIVE: error passive interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_OVERR: data overrun interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_ERR_WARRING: error warning interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_TX: transmit interrupt enable.
 *                 @arg CAN_PELI_INT_TYPE_RX: receive interrupt enable.
 * @retval  FunctionalState:  Interrupt enable bit has enable or not.
 *              Any value of @ref FunctionalState.
 *                @arg DISABLE: Interrupt is disable.
 *                @arg ENABLE: Interrupt is enable.
 ******************************************************************************/
FunctionalState CAN_PELI_GetIntCmdStatus(uint32_t CAN_PELI_IntType)
{
  FunctionalState state = DISABLE;

  if(RESET != (CAN->CAN_PELIMODE.IE & CAN_PELI_IntType))
  {
    /* Interrupt is enable. */
    state = ENABLE;
  }
  else
  {
    /* Interrupt is disbale. */
    state = DISABLE;
  }

  /* Return the status of the interrupt enable bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief  Checks whether the specified CAN interrupt has occurred or not.
 * @param  [in]  CAN_PELI_IntFlag: specifies the flag to check.
 *               Any value of @ref I2C_IntFlagEnum.
 *                 @arg CAN_PELI_INT_FLAG_OVERR_HAP: overrun happen interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_BUS_ERR: bus error interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_ARB_LOST: arbitration lost interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_ERR_PASSIVE: error passive interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_OVERR: data overrun interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_ERR_WARRING: error warning interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_TX: transmit interrupt falg.
 *                 @arg CAN_PELI_INT_FLAG_RX: receive interrupt falg.
 * @retval FlagState: Interrupt flag has occurred or not.
 *               Any value of @ref FlagState.
 *                 @arg SET: Interrupt has occurred.
 *                 @arg RESET: Interrupt has not occurred.
 ******************************************************************************/
FlagState CAN_PELI_GetIntFlagStatus(uint32_t CAN_PELI_IntFlag)
{
  FlagState state = RESET;

  if(RESET != (CAN->CAN_PELIMODE.INTERRUPT & CAN_PELI_IntFlag))
  {
    /* Interrupt has occurred. */
    state = SET;
  }
  else
  {
    /* Interrupt has not occurred. */
    state = RESET;
  }

  /* Return the status of the interrupt flag bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief   Get the specified CAN status bit is set or not.
 * @param   [in]  CAN_PELI_Flag: Specifies the CAN status bit.
 *                This parameter can be a value of @ref CAN_PELI_FlagEnum.
 *                  @arg CAN_PELI_FLAG_OHS: overrun happen status.
 *                  @arg CAN_PELI_FLAG_BS: bus status.
 *                  @arg CAN_PELI_FLAG_ES: error status.
 *                  @arg CAN_PELI_FLAG_TS: transmit status.
 *                  @arg CAN_PELI_FLAG_RS: receive status.
 *                  @arg CAN_PELI_FLAG_TCS: transmission complete status.
 *                  @arg CAN_PELI_FLAG_TBS: transmit buffer  status.
 *                  @arg CAN_PELI_FLAG_DOS: data overrun status.
 *                  @arg CAN_PELI_FLAG_RBS: receive buffer status.
 * @retval  FlagState: The state of CAN_PELI_Flag (SET or RESET).
 ******************************************************************************/
FlagState CAN_PELI_GetFlagStatus(uint32_t CAN_PELI_Flag)
{
  FlagState state = RESET;

  if(RESET != (CAN->CAN_PELIMODE.STATUS & CAN_PELI_Flag))
  {
    /* Interrupt has occurred. */
    state = SET;
  }
  else
  {
    /* Interrupt has not occurred. */
    state = RESET;
  }

  /* Return the status of the interrupt flag bit. */
  return state;
}


#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic pop
#endif

#endif /* DPM32M08x */
