/***********************************************************************************************************************
* Copyright (C) All rights reserved.
***********************************************************************************************************************/

/***********************************************************************************************************************
* @file    can.c
* @brief   This file implements device driver for CAN module.
* @version 1.0.0  
* @date    2019/12/24
***********************************************************************************************************************/

/***********************************************************************************************************************
Includes
***********************************************************************************************************************/
#define  GLOBALS_BSP_CAN
#include "BAT32A239.h"
#include "userdefine.h"
#include "can.h"
#include "gpio.h"
#include "CAN_User.h"
#include "uds_includes.h"
#include "U2_uds_includes.h"
#include "CAN_User.h"

#define MSGBUF_BASE_ADD          0x40045500

typedef union
{
    struct
    {
        uint16_t TSEG1     :4;
        uint16_t reserved0 :4;
        uint16_t TSEG2     :3;
        uint16_t reserved1 :1;
        uint16_t SJW       :2;
        uint16_t reserved2 :2;
    }bits;
    uint16_t C0BTR_Data;
}C0BTR_REG_t;

typedef union
{
    struct
    {
        uint16_t  ClearTransmission    :1;
        uint16_t  ClearReception       :1;
        uint16_t  ClearErrorStatus     :1;
        uint16_t  ClearProtocolError   :1;
        uint16_t  ClearArbitrationLoss :1;
        uint16_t  ClearWakeup          :1;
        uint16_t  no0                  :2;

        uint16_t  SetTransmission    :1;
        uint16_t  SetReception       :1;
        uint16_t  SetErrorStatus     :1;
        uint16_t  SetProtocolError   :1;
        uint16_t  SetArbitrationLoss :1;
        uint16_t  SetWakeup          :1;
        uint16_t  no1                :2;
    }bits;
    uint16_t C0IE_Data;
}C0IE_REG_t;

enum
{
    MaskReg1 = 1,
    MaskReg2,
    MaskReg3,
    MaskReg4,
    DedicatedBuf,
};


C0BTR_REG_t C0BTR_Reg;
C0IE_REG_t  C0IE_Reg;

typedef union
{
    struct
    {
        uint16_t  RECS    :2;
        uint16_t  TECS    :2;
        uint16_t  BOFF     :1;
        uint16_t  no1      :3;
    }bits;
    uint8_t C0INFOm_Data;
}C0INFm_REG_t;


CanState_t GetBusOffState(void)
{
    C0INFm_REG_t m_C0INFO;
    CanState_t CanState;
    m_C0INFO.C0INFOm_Data = CAN0->CINFO;
    
    if(m_C0INFO.bits.BOFF == 0)
    {
        CanState = Canm_BusOk;
    }
    else if ((m_C0INFO.bits.TECS == 1)||(m_C0INFO.bits.RECS == 1))  
    {
        CanState =  Canm_ActiveErr;
    }
    else if ((m_C0INFO.bits.TECS == 3)||(m_C0INFO.bits.RECS == 3))  
    {
        CanState = Canm_PassiveErr;
    }
    else if(m_C0INFO.bits.BOFF)
    {
        CanState = Canm_busoff;
    }
    
    return CanState;
}

/******************************************************************************
函数名：MSCAN0_Get_Wake_Up_Flag
功  能：获取MSCAN0的唤醒状态
参  数：无
返回值：0 - 未被唤醒 1 - 已被唤醒
******************************************************************************/
uint8_t CAN0_Get_Wake_Up_Flag ( void )
{
    uint8_t flag = 0u;
    if (CAN0->CCTRL & 0x0008)
    {
        flag = 0;
    }
    else
    {
        flag = 1;
    }
    return flag;
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_MaskCheck
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
uint16_t cantemp16[4];
void bsp_CAN_MaskCheck(void)
{

    if(CAN0->CMASK1H != 0x0000)
    {
        CAN0->CMASK1H = 0x0000;
    }
    
    if(CAN0->CMASK2H != 0x0000)
    {
        CAN0->CMASK2H = 0x0000;
    }

    if(CAN0->CMASK3H != 0x067c)
    {
        CAN0->CMASK3H = 0x067c;
    }
    
    if(CAN0->CMASK4H != 0x005C)
    {
        CAN0->CMASK4H = 0x005C;
    }
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_tx_msgbuf_abort
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_tx_msgbuf_abort(uint8_t buffer_number)
{
    uint32_t  Buff_address;
    uint16_t  *C0MCTRLm;

    Buff_address = (MSGBUF_BASE_ADD + (0x10 * buffer_number));
    C0MCTRLm = ((uint16_t *)(Buff_address + 0x0e));
    *C0MCTRLm = 0x0002; /* C0MCTRLmn clear TRQ bit */
}
/*-------------------------------------------------------------------------
* Function Name  : bsp_rx_mask_init
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_rx_mask_init(uint8_t MaskReg_n,uint32_t maskData)
{
    uint32_t mask = 0u;
    mask = ~maskData;
    /* Set C0MCONFm register */
    switch(MaskReg_n)
    {
        case 1:
            CAN0->CMASK1L = 0x0000;
            CAN0->CMASK1H = mask << 2;
            break;
        case 2: 
            CAN0->CMASK2L = 0x0000;
            CAN0->CMASK2H = mask << 2;
            break;
        case 3:
            CAN0->CMASK3L = 0x0000;
            CAN0->CMASK3H = mask << 2;
            break;
        case 4:
            CAN0->CMASK4L = 0x0000;
            CAN0->CMASK4H = mask << 2;
            break;
        default:
            break;
    } 
}
/*-------------------------------------------------------------------------
* Function Name  : bsp_rx_msgbuf_init
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_rx_msgbuf_init(uint8_t buf_num,uint32_t id,uint8_t MaskReg_n)
{
    uint32_t  MsgBuf_address;
    uint16_t  *C0MIDLm;   /* CAN0 message ID register L */
    uint16_t  *C0MIDHm;   /* CAN0 message ID register H */
    uint8_t   *C0MCONFm;  /* CAN0 message configuration register m */
    uint16_t  *C0MCTRLm;  /* CAN0 message control register m */

    MsgBuf_address = (MSGBUF_BASE_ADD + (0x10 * buf_num));

    C0MIDLm = ((uint16_t *)(MsgBuf_address + 0x0a));
    C0MIDHm = ((uint16_t *)(MsgBuf_address + 0x0c));
    C0MCONFm = ((uint8_t *)(MsgBuf_address + 0x09));
    C0MCTRLm = ((uint16_t *)(MsgBuf_address + 0x0e));

    /* Set C0MCONFm register */
    switch(MaskReg_n)
    {
        case 1:  /* Receive message buffer(mask 1), MA0=1,msg buffer used */
            *C0MCONFm = 0x91;
            *C0MIDLm = 0x0000;
            *C0MIDHm = ((id << 2) & 0x1fff);
            break;
        case 2: 
            *C0MCONFm = 0x99;
            *C0MIDLm = 0x0000;
            *C0MIDHm = ((id << 2) & 0x1fff);
            break;
        case 3:
            *C0MCONFm = 0xA1;
            *C0MIDLm = 0x0000;
            *C0MIDHm = ((id << 2) & 0x1fff);
            break;
        case 4:
            *C0MCONFm = 0xA9;
            *C0MIDLm = 0x0000;
            *C0MIDHm = ((id << 2) & 0x1fff);
            break;
        case 5:  /* (no mask setting) : 只能接收对应ID的报文*/
            *C0MCONFm = 0x89;
            *C0MIDLm = 0x0000;
            *C0MIDHm = ((id << 2) & 0x1fff);
            break;
    }

    /* Set C0MCTRLm register */
    *C0MCTRLm = 0x0916;    
    /* 
    set IE=1,Valid message reception completion interrupt enabled.
    Set RDY bit
    clear MOW,DN,TRQ bit
    MOV=0,The message buffer is not overwritten by a newly received data frame.
    DN=0,A data frame or remote frame is not stored in the message buffer.
    TRQ=0,No message frame transmitting request that is pending or being transmitted
    */
    *C0MCTRLm = 0x0100;    /* set RDY=1,The CAN module can write to the message buffer */
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_tx_msgbuf_init
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_tx_msgbuf_init(uint8_t buffer_number,uint32_t tx_msg_ID,uint8_t tx_msg_DLC)
{
    uint32_t      MsgBuf_address;
    uint16_t      data_cnt;

    uint16_t  *C0MIDLm;   /* CAN0 message ID register L */
    uint16_t  *C0MIDHm;   /* CAN0 message ID register H */
    uint8_t   *C0MCONFm;  /* CAN0 message configuration register m */
    uint16_t  *C0MCTRLm;  /* CAN0 message control register m */
    uint8_t   *C0MDLCm;
//    uint16_t  *C0MDBm00;     /* CAN0 message data byte */

    /* Set CAN message buffer[n] register address */
    MsgBuf_address = (MSGBUF_BASE_ADD + (0x10 * buffer_number));

    C0MIDLm = ((uint16_t *)(MsgBuf_address + 0x0a));
    C0MIDHm = ((uint16_t *)(MsgBuf_address + 0x0c));
    C0MCONFm = ((uint8_t *)(MsgBuf_address + 0x09));
    C0MCTRLm = ((uint16_t *)(MsgBuf_address + 0x0e));
    C0MDLCm = ((uint8_t *)(MsgBuf_address + 0x08));
 //   C0MDBm00 = ((uint16_t *)MsgBuf_address);  
    
    *C0MCONFm = 0x01;      /* Transmit message buffer, MA0=1,msg buffer used */

    /* Set C0MIDLm,C0MIDHm register */
    *C0MIDLm = 0x0000;
    *C0MIDHm = ((tx_msg_ID << 2) & 0x1fff);

    *C0MDLCm = tx_msg_DLC;     /* set C0MDLCm,data length is 8 bytes */

    /* Clear C0MDATAxm register */
    for(data_cnt = 0 ; data_cnt < tx_msg_DLC ; data_cnt++)
    {
        *(uint8_t *)(MsgBuf_address + data_cnt) = 0x00;    /* clear each byte data=0x00 */
    }

    /* Set C0MCTRLm register */
    *C0MCTRLm = 0x0816;     /* clear MOW,IE,DN,TRQ bit0x001e; */
    /* 
    MOV=0,The message buffer is not overwritten by a newly received data frame.
    IE=0,Normal message transmission completion interrupt disabled
    DN=0,A data frame or remote frame is not stored in the message buffer.
    TRQ=0,No message frame transmitting request that is pending or being transmitted
     */
    /* Set RDY bit */
    *C0MCTRLm = 0x0100;    /* set RDY=1,The CAN module can write to the message buffer */

}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CanBuf_Clear
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CanBuf_Clear(void)
{
    uint8_t   buffer_num;
    uint32_t  MsgBuff_address;
    uint8_t   *C0MCONFm;  /* CAN0 message configuration register m */
    uint16_t  *C0MCTRLm;  /* CAN0 message control register m */
    
    /* Init all message buffer */
    for (buffer_num = 0 ; buffer_num < 16 ; buffer_num++)
    {
        /* Set CAN message buffer[n] register address */
        MsgBuff_address = (MSGBUF_BASE_ADD + (0x10 * buffer_num));
        
        C0MCONFm = ((uint8_t *)(MsgBuff_address + 0x09));
        C0MCTRLm = ((uint16_t *)(MsgBuff_address + 0x0e));
        
        /*  Clear RDY bit */
        *C0MCTRLm = 0x0001; /* can module cannot write buffer */

        /* Clear MA0 bit */
        *C0MCONFm &= 0xf8;  /* Message buffer not used. */

        /* Clear TRQ, DN bit */
        *C0MCTRLm = 0x0006;
    }
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CanBuf_Init
* Description    : buffer初始化
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CanBuf_Init(void)
{
    //bsp_tx_msgbuf_init(txResNum,DIAG_ID_Tx,8);
    //bsp_tx_msgbuf_init(txCommon,0x120,8);

    /*
    maskData:0x18000000
    接收BUF0 的ID设置 0x08000000,那么只有0x08xxxxxx的报文可以进入BUF0
    */
    bsp_rx_mask_init(MaskReg1,0xffff);/* 全零不比较 */
    bsp_rx_mask_init(MaskReg2,0xffff);
    bsp_rx_mask_init(MaskReg3,ID_PhyAddr);
    bsp_rx_mask_init(MaskReg4,U2_ID_BCM_ResAddr);
    
    bsp_rx_msgbuf_init(0,0x125,MaskReg1);
    bsp_rx_msgbuf_init(1,0x401,MaskReg1);
    bsp_rx_msgbuf_init(2,0x111,MaskReg1);
    bsp_rx_msgbuf_init(3,0x101,MaskReg1);
    bsp_rx_msgbuf_init(4,0x12B,MaskReg1);
    bsp_rx_msgbuf_init(5,0x402,MaskReg1);
    bsp_rx_msgbuf_init(6,0x113,MaskReg1);
    bsp_rx_msgbuf_init(7,0x55C,MaskReg1);
  //  bsp_rx_msgbuf_init(8,0x400,MaskReg2);
   // bsp_rx_msgbuf_init(9,0x400,MaskReg2);
    bsp_rx_msgbuf_init(8,0x400,MaskReg1);
    bsp_rx_msgbuf_init(9,0x7DF,MaskReg1);
    bsp_rx_msgbuf_init(10,ID_PhyAddr,MaskReg3);
    bsp_rx_msgbuf_init(11,U2_ID_BCM_ResAddr,MaskReg4);
}

void SetBaudRadio(uint16_t Baud)
{
    if(Baud == 500)
    {
        CAN0->CBRP = 0x00;     
    }
    else
    {
        CAN0->CBRP = 0x01; /* fCANMOD/2 */
    }
    
    /* Baud-rate: 500kbps,81% sample */
    C0BTR_Reg.bits.TSEG1 = 11;
    C0BTR_Reg.bits.TSEG2 = 2;
    C0BTR_Reg.bits.SJW = 0;
    CAN0->CBTR = C0BTR_Reg.C0BTR_Data;   
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_Init
* Description    : can初始化
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CAN_Init(void)
{
    CGC->PER0 |= CGC_PER0_CAN0EN_Msk;    /* enables input clock supply */

    CAN0->CGMCS = 7;//fclk/8 64MHz/8 => 8MHz
    CAN0->CGMCTRL= 0x0100;       /* set GOM=1; enable CAN module operation */

    CAN0->CCTRL = 0x807f;     /* set initialization mode */
    __NOP();
    __NOP();
    while((CAN0->CCTRL & 0X0007)!=0);

    SetBaudRadio(500);

    /* enable receive and wakeup interupt */
    C0IE_Reg.C0IE_Data = 0;
    C0IE_Reg.bits.SetTransmission = 1;
    C0IE_Reg.bits.SetReception = 1;
    C0IE_Reg.bits.SetWakeup = 1;
    CAN0->CIE = C0IE_Reg.C0IE_Data;   

    CAN0->CLEC  =  0;

    bsp_CanBuf_Clear();
    bsp_CanBuf_Init();
    bsp_tx_msgbuf_init(txResNum,ID_ResAddr,8);
    bsp_tx_msgbuf_init(U2_txResNum,U2_ID_BCM_PhyAddr,5);
    bsp_tx_msgbuf_init(txCommon,0x0000,8);
    
    INTC_ClearPendingIRQ(CAN0REC_IRQn); /* clear REV flag */
    INTC_EnableIRQ(CAN0REC_IRQn);/* Enable Rev Interrupt */

//    INTC_ClearPendingIRQ(CAN0WUP_IRQn);/* clear WUP flag */
//    INTC_EnableIRQ(CAN0WUP_IRQn);/* Enable Wup Interrupt */

    INTC_ClearPendingIRQ(CAN0TRX_IRQn);/* clear TX flag */
    INTC_EnableIRQ(CAN0TRX_IRQn);/* Enable TX Interrupt */
    
    CAN0->CCTRL   = 0x817E;   
    /* clear AL,Valid(no receive Valid message),PSMODE1,PSMODE0(no power save mode)
    clear OPMODE2,OPMODE1 and set OPMODE0(normal mode)
    set CCERC(clear C0ERC and C0INFO registers in initialization mode) */
    
    /* Set CAN0TXD pin */
    CTXD0_PORT_SETTING();
    /* Set CAN0RXD pin */
    CRXD0_PORT_SETTING();
    
    PORT_ClrBit(CAN_STB_MCU);

    CanSendLock = 0;
  
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_Rev_isr
* Description    :
* Input          :
* Output         :
* Return         :
* onther         :

--------------------------------------------------------------------------*/  
void memcpy1(uint8_t* destin,uint8_t* source, uint32_t len)
{
    uint32_t i;
    for(i=0; i<len; i++){
        destin[i] = source[i];
    }

}
void  bsp_CAN0_Rev_isr(void)
{
//    uint16_t      stand_id;
//    uint32_t      MsgBuf_address = 0;
//    uint8_t       rx_buff_num = 0;
//    uint8_t       CAN0RXDLR_DLC;
//    uint8_t       Tmp_Data[8];
////    uint16_t      *C0MIDLm;   /* CAN0 message ID register L */
//    uint16_t      *C0MIDHm;   /* CAN0 message ID register H */
//    uint8_t       *C0MDLCm;
//    uint16_t      *C0MCTRLm;  /* CAN0 message control register m */
//    uint16_t      *C0MDBm00;  /* CAN0 message data byte */
//    uint32_t rgpt;
//    INTC_ClearPendingIRQ(CAN0REC_IRQn);
//    rx_buff_num = CAN->C0LIPT;
//    MsgBuf_address = (MSGBUF_BASE_ADD + (0x10 * rx_buff_num));
//
//    C0MDBm00 = ((uint16_t *)MsgBuf_address);
//    C0MDLCm = ((uint8_t *)(MsgBuf_address + 0x08));
////    C0MIDLm = ((uint16_t *)(MsgBuf_address + 0x0a));
//    C0MIDHm = ((uint16_t *)(MsgBuf_address + 0x0c));
//    C0MCTRLm = ((uint16_t *)(MsgBuf_address + 0x0e));
//
//    rgpt = CAN->C0RGPT;
//    
//    /* Check DN bit */
//    if ((*C0MCTRLm & 0x0004) != 0)
//    {
//        *C0MCTRLm = 0x0004; /* Clear DN bit */
//
//        stand_id = (*C0MIDHm >> 2) & 0x07ff;
//        CAN0RXDLR_DLC = *C0MDLCm;
//        
//
//       
//       memcpy1((uint8_t*)&Tmp_Data[0],(uint8_t*)C0MDBm00,CAN0RXDLR_DLC);   
//        switch(stand_id)
//        {
//
//        case ID_FunAddr:
//            if((DiagnoCtl.SessionType == SubExtSession) || (DiagnoCtl.SessionType == SubProgSession))
//            {
//                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
//            }
//            LK_Link_main(ID_FunAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
//            break;         
//        case ID_PhyAddr:
//            if((DiagnoCtl.SessionType == SubExtSession) || (DiagnoCtl.SessionType == SubProgSession))
//            {
//                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
//            }
//            LK_Link_main(ID_PhyAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
//            break; 
//        case U2_ID_BCM_ResAddr:
//            U2_LK_Link_main(U2_ID_BCM_ResAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
//            break; 
//         default:
//			Can_Receive_Msg(stand_id, CAN0RXDLR_DLC, (uint8_t*)Tmp_Data);
//            break;
//        }
//    
//    }
//  //  Api_SetCanTimer(T_8s,(_Clock *)&g_Clock);
//
//    CAN->C0INTS = 0x0002;
//    Set_CanSleepDelayTime(8000);
//





	CANMSG_Type* pCMsg;
	uint8_t* pMdb;
	uint32_t rgpt;
	uint8_t msgnum,i;
    uint16_t      stand_id;
	uint8_t       CAN0RXDLR_DLC;
    uint8_t       Tmp_Data[8];
    INTC_ClearPendingIRQ(CAN0REC_IRQn);
	if(CAN0->CINTS & INTS_RX_READ)
	{
		CAN0->CINTS = INTS_RX_CLR;
        
	    rgpt = CAN0->CRGPT;
	
        if(rgpt&RGPT_ROVF_READ)
    	{
    		CAN0->CRGPT = RGPT_ROVF_CLR;
    	}
    	
    	while(!(rgpt&RGPT_RHPM_READ))
    	{
    		msgnum = (rgpt>>8)&0x0f;
    		pCMsg = (CANMSG_Type*)CAN0MSG00+msgnum;
    		
    		pCMsg->CMCTRL = MCTRL_DN_CLR;//clear DN
    		stand_id = (pCMsg->CMIDH >> 2) & 0x07ff;
            CAN0RXDLR_DLC = pCMsg->CMDLC;
    		pMdb = (uint8_t*)&(pCMsg->CMDB0);
           
            memcpy1((uint8_t*)&Tmp_Data[0],(uint8_t*)pMdb,CAN0RXDLR_DLC);   
            switch(stand_id)
            {

            case ID_FunAddr:
                if((DiagnoCtl.SessionType == SubExtSession) || (DiagnoCtl.SessionType == SubProgSession))
                {
                    App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
                }
                LK_Link_main(ID_FunAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
                break;         
            case ID_PhyAddr:
                if((DiagnoCtl.SessionType == SubExtSession) || (DiagnoCtl.SessionType == SubProgSession))
                {
                    App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
                }
                LK_Link_main(ID_PhyAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
                break; 
            case U2_ID_BCM_ResAddr:
                U2_LK_Link_main(U2_ID_BCM_ResAddr, (uint8_t*)Tmp_Data, (CAN0RXDLR_DLC & 0x0f));
                break; 
             default:
    			Can_Receive_Msg(stand_id, CAN0RXDLR_DLC, (uint8_t*)Tmp_Data);
                break;
            }


            
    //		can0MsgRec[msgnum].MsgRxStatus = 1;
    //		RxCount++;
#if 0		
    		if((can0MsgRec[msgnum].Id&0x000007ff)==0x231)
    		{
    			date_time.year  = pMdb[0];
    			date_time.month = pMdb[1];
    			date_time.day   = pMdb[2];
    			date_time.week  = pMdb[3];
    			date_time.hour  = pMdb[4];
    			date_time.min   = pMdb[5];
    			date_time.sec   = pMdb[6];
    			RTC_Set_CounterValue(&date_time);
    		}
#endif
    //		if((can0MsgRec[msgnum].Id&0x07ff)==0x702)
    //		{
    //			PORT->P7 ^= 0x06U;
    //		}
#if 0		
    		printf("RxCount %d\n",++RxCount);
    		printf("Receive a message buffer%d from CAN0\n",msgnum);
    		
    		printf("ID 0x%08x\n",can0MsgRec[msgnum].Id);
    		printf("DLC %d\n",can0MsgRec[msgnum].Dlc);
    		for(i=0;i<can0MsgRec[msgnum].Dlc;i++)
    		{
    			printf("Data%d 0x%02x\n",i,can0MsgRec[msgnum].Msgbuff[i]);
    		}
#endif		
    		rgpt = CAN0->CRGPT;
    	}
   }
   Set_CanSleepDelayTime(8000);
}


/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN0_Tx_isr
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CAN0_Tx_isr(void)
{
    INTC_ClearPendingIRQ(CAN0TRX_IRQn);
//    if(DiagDtc[ EE_BusOff ].PassTimes < 5)
//    {
//        DiagDtc[ EE_BusOff ].PassTimes ++;
//    }
//    DiagDtc[ EE_BusOff ].ErrorTimes = 0;
    CanSendLock = 0;
    CAN0->CINTS = 0x0001;
}


/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_BusOff_Recover
* Description    : can bus off
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CAN_BusOff_Recover(void)
{
    CAN0->CCTRL = 0x807f;     //set initialization mode
    __NOP();
    __NOP();

    SetBaudRadio(500);   

    /* enable receive and wakeup interupt */
    C0IE_Reg.C0IE_Data = 0;
    C0IE_Reg.bits.SetTransmission = 1;
    C0IE_Reg.bits.SetReception = 1;
    C0IE_Reg.bits.SetWakeup = 1;
    CAN0->CIE = C0IE_Reg.C0IE_Data; 

    CAN0->CLEC  =  0;
    
   
    INTC_ClearPendingIRQ(CAN0REC_IRQn); /* clear REV flag */
    INTC_EnableIRQ(CAN0REC_IRQn);/* Enable Rev Interrupt */

//    INTC_ClearPendingIRQ(CAN0WUP_IRQn);/* clear WUP flag */
//    INTC_EnableIRQ(CAN0WUP_IRQn);/* Enable Wup Interrupt */

    INTC_ClearPendingIRQ(CAN0TRX_IRQn);/* clear TX flag */
    INTC_EnableIRQ(CAN0TRX_IRQn);/* Enable TX Interrupt */

    CAN0->CCTRL   = 0x817E;
    
    /* Set CAN0TXD pin */
    CTXD0_PORT_SETTING();
    /* Set CAN0RXD pin */
    CRXD0_PORT_SETTING();
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_SleepRelease
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CAN_SleepRelease(void)
{
    CAN0->CCTRL = 0x0018;   //clear PSMODE0=0,release sleep mode by software
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CAN_Sleep
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void bsp_CAN_Sleep(void)
{
    CAN0->CCTRL = 0x0810;   //set PSMODE0=1,PSMODE1=0, setting CAN sleep mode
}

uint8_t bsp_Is_CAN_Sleep(void)
{
    uint8_t temp8 = 0;
    if((CAN0->CCTRL & CTRL_PSMODE_READ) == 0x08){
        temp8 = 1;
    }//20221026  CANH与CANL短路/CANH接地不睡眠
    else if(Get_RSCAN0Busoff_Status() >= RSCAN0_BUS_OFF_LV1){
        bsp_CAN_BusOff_Recover();
        bsp_tx_msgbuf_abort(txResNum);
        bsp_tx_msgbuf_abort(txCommon);    
        bsp_tx_msgbuf_abort(U2_txResNum);  
        bsp_CAN_Sleep();			
        temp8 = 1;
    }
    return temp8;
}

/*-------------------------------------------------------------------------
* Function Name  : Get_CH0_BusOffStatus
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
uint8_t Get_CH0_BusOffStatus(void)
{
    if(CAN0->CINFO & 0x10)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/*-------------------------------------------------------------------------
* Function Name  : bsp_CANSendFrame
* Description    :
* Input          :
* Output         : None
* Return         : dwPGN
* onther         :
--------------------------------------------------------------------------*/

uint8_t bsp_CANSendFrame (uint32_t id,uint8_t buff_num,uint8_t *txdata,uint8_t length)
{
    uint32_t  MsgBuf_address;
    uint8_t   i;

    uint16_t  *C0MIDLm;   /* CAN0 message ID register L */
    uint16_t  *C0MIDHm;   /* CAN0 message ID register H */
    uint16_t  *C0MCTRLm;  /* CAN0 message control register m */
    uint8_t   *C0MDLCm;
    uint8_t   *C0MCONFm;  /* CAN0 message configuration register m */

    /* Set CAN message buffer[n] register address */
    MsgBuf_address = (MSGBUF_BASE_ADD + (0x10 * buff_num));

    C0MCONFm = ((uint8_t *)(MsgBuf_address + 0x09));
    C0MIDLm = ((uint16_t *)(MsgBuf_address + 0x0a));
    C0MIDHm = ((uint16_t *)(MsgBuf_address + 0x0c));
    C0MCTRLm = ((uint16_t *)(MsgBuf_address + 0x0e));
    C0MDLCm = ((uint8_t *)(MsgBuf_address + 0x08));

    *C0MCONFm = 0x01;
    /* Check TRQ bit */
    if((*C0MCTRLm & 0x0002) != 0)
    {
        return 0;
    }

    /* Clear RDY bit */
    *C0MCTRLm = 0x0001;/* clear RDY=1,The message buffer can be written by software. */

    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();

    /* Set C0MIDLm,C0MIDHm register */
    *C0MIDLm =  0x0000;
    *C0MIDHm = (id << 2) & 0x1fff;
    *C0MDLCm = length; /* set length of C0MDLCm */

    /* Set C0MDATAxm register */
    if((*C0MCTRLm & 0x0001) == 0)
    {
        for(i = 0 ; i < length ; i ++)
        {
            *((uint8_t *)(MsgBuf_address + i)) = txdata[ i ];
        }
        /* Set RDY bit Set TRQ bit */
        *C0MCTRLm = 0x0B00;
    }
    Set_CanSleepDelayTime(8000);
    return 1;
}

