欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

XCP的移植(2)

程序员文章站 2024-01-16 22:07:46
...

本篇文章主要介绍CAN driver和xcp的交互。
1.首先是对XCP使用ID进行初始化(在main函数)

XCPCANInit(0x200,0x300,0x301,0x302,0x303);

函数原型如下:

void XCPCANInit (uint16 cro_id, 
                 uint16 dto_id, 
                 uint16 daq0_id, 
                 uint16 daq1_id,
                 uint16 daq2_id)
{
  uint8_t   i;

  CAN_C.MCR.R = 0x5000003F;       // Put in Freeze Mode & enable all 32 message buffers 
  CAN_C.CR.R = 0x01c90002;//0x01920004;        // 500K&12M OSC  for Monaco EVB

// CAN_C.CR.B.LPB = 1;          // Loopback mode for test ...
 
  for (i=0; i<32; i++) {          // MPC563x: init 32 message buffers 
    CAN_C.BUF[i].CS.B.CODE = 0;   // Inactivate all message buffers 
  } 


  CAN_C.BUF[CRO_BUF_N].CS.B.IDE = 0;           // MB0 will look for a standard ID 
  CAN_C.BUF[CRO_BUF_N].ID.B.STD_ID = cro_id;   // MB0 will be used as CRO  
  CAN_C.BUF[CRO_BUF_N].CS.B.CODE = 4;          // MB0 set to RX EMPTY 

  CAN_C.BUF[DTO_BUF_N].CS.B.CODE = 8;          // MB1 served for CTO, set to TX INACTIVE 
  CAN_C.BUF[DTO_BUF_N].CS.B.IDE = 0;           
  CAN_C.BUF[DTO_BUF_N].ID.B.STD_ID = dto_id;   // MB1  will be used as CTO  
  CAN_C.BUF[DTO_BUF_N].CS.B.RTR = 0;           // Data frame, not remote Tx request frame 
  CAN_C.BUF[DTO_BUF_N].CS.B.LENGTH = 8; 

  CAN_C.BUF[DAQ0_BUF_N].CS.B.CODE = 8;         
  CAN_C.BUF[DAQ0_BUF_N].CS.B.IDE = 0;           
  CAN_C.BUF[DAQ0_BUF_N].ID.B.STD_ID = daq0_id; // MB2 will be used as CTO  
  CAN_C.BUF[DAQ0_BUF_N].CS.B.RTR = 0;          // Data frame, not remote Tx request frame 
  CAN_C.BUF[DAQ0_BUF_N].CS.B.LENGTH = 8; 

  CAN_C.BUF[DAQ1_BUF_N].CS.B.CODE = 8;         
  CAN_C.BUF[DAQ1_BUF_N].CS.B.IDE = 0;           
  CAN_C.BUF[DAQ1_BUF_N].ID.B.STD_ID = daq1_id; // MB3  will be used as CTO  
  CAN_C.BUF[DAQ1_BUF_N].CS.B.RTR = 0;          // Data frame, not remote Tx request frame 
  CAN_C.BUF[DAQ1_BUF_N].CS.B.LENGTH = 8; 

  CAN_C.BUF[DAQ2_BUF_N].CS.B.CODE = 8;         
  CAN_C.BUF[DAQ2_BUF_N].CS.B.IDE = 0;           
  CAN_C.BUF[DAQ2_BUF_N].ID.B.STD_ID = daq2_id; // MB4  will be used as CTO  
  CAN_C.BUF[DAQ2_BUF_N].CS.B.RTR = 0;          // Data frame, not remote Tx request frame 
  CAN_C.BUF[DAQ2_BUF_N].CS.B.LENGTH = 8; 
  
  
  CAN_C.BUF[BOOTLOADER_BUF_RX_N].CS.B.IDE = 0; 
  CAN_C.BUF[BOOTLOADER_BUF_RX_N].ID.B.STD_ID = BOOTLOADER_DN_ID;   
  CAN_C.BUF[BOOTLOADER_BUF_RX_N].CS.B.CODE = 4;              

  //CAN_C.BUF[BOOTLOADER_BUF_RX_N].CS.B.RTR = 0;          // Data frame, not remote Tx request frame 
  //CAN_C.BUF[BOOTLOADER_BUF_RX_N].CS.B.LENGTH = 8;
  
  //CAN_C.BUF[BOOTLOADER_BUF_TX_N].CS.B.CODE = 8;         
  //CAN_C.BUF[BOOTLOADER_BUF_TX_N].CS.B.IDE = 0;           
  //CAN_C.BUF[BOOTLOADER_BUF_TX_N].ID.B.STD_ID = BOOTLOADER_DN_ID; // MB4  will be used as CTO  
  //CAN_C.BUF[BOOTLOADER_BUF_TX_N].CS.B.RTR = 0;          // Data frame, not remote Tx request frame 
  //CAN_C.BUF[BOOTLOADER_BUF_TX_N].CS.B.LENGTH = 8; 
  

  CAN_C.RXGMASK.R = 0x1FFFFFFF;   // Global acceptance mask 

  CAN_C.IMRL.B.BUF00M = 1;        // Enable MB0 interrupt; 
  CAN_C.IMRL.B.BUF01M = 1;        // Enable MB1 interrupt; 
  CAN_C.IMRL.B.BUF02M = 1;        // Enable MB2 interrupt; 
  CAN_C.IMRL.B.BUF03M = 1;        // Enable MB3 interrupt; 
  CAN_C.IMRL.B.BUF04M = 1;        // Enable MB4 interrupt; 
  CAN_C.IMRL.B.BUF05M = 1;        // Enable MB4 interrupt;
  
  INTC_InstallINTCInterruptHandler(CanBuf5ISR, 181, 10);
  INTC_InstallINTCInterruptHandler(CanBuf4ISR, 180, 10);
  INTC_InstallINTCInterruptHandler(CanBuf3ISR, 179, 10);
  INTC_InstallINTCInterruptHandler(CanBuf2ISR, 178, 10);
  INTC_InstallINTCInterruptHandler(CanBuf1ISR, 177, 10);
  INTC_InstallINTCInterruptHandler(CanBuf0ISR, 176, 10);
  
  SIU.PCR[87].R = 0x0E20;         // MPC565x: Configure pad as CNTXC, open drain 
  SIU.PCR[88].R = 0x0D00;         // MPC565x: Configure pad as CNRXC 
  CAN_C.MCR.R = 0x0000003F;       // Negate FlexCAN C halt state for 32 MB
} 

2.CAN发送函数(XCP调用)

void XCP_FN_TYPE XcpCan_DoTransmit(
    uint sessionId,
    uint channelId
)
{
    XcpCan_SessionCfg_t* const pSessionCfg     = XcpCan_SessionCfgs + sessionId;
    XcpCan_ChannelCfg_t* const pChannelCfg     = pSessionCfg->pChannelCfgs + channelId;
    Xcp_StatePtr32 const       pCanPos         = &( pSessionCfg->pQueuePositions[ channelId ].ctCanPos );
    XcpCan_QueueBuf_t* const   pQueueBuffer    = pSessionCfg->pQueueBuffers + *pCanPos;
    Xcp_StatePtr8 const        pQueueBufState  = pSessionCfg->pQueueBufferStates + *pCanPos;
    
    uint8 *pdat;

    uint8 i; 

    /* Find the CAN msg ID which has been configured for the specified channel. This is not entirely straightforward,
     * since the msg ID of a dynamic DAQ list can be set at runtime.
     *
     * We assume that a DAQ CAN channel index can be translated to the equivalent DAQ list ID by subtracting XCP_FIRST_DAQ_CHANNEL. */

    uint32 configuredMsgId = pChannelCfg->msgId;

#ifdef XCP_ENABLE_DYNDAQ

    if( channelId >= XCP_FIRST_DAQ_CHANNEL &&
        Xcp_SessionConfigs[ sessionId ].maxDynDaqLists > 0 &&
        pSessionCfg->pDynDaqMsgIds[ channelId - XCP_FIRST_DAQ_CHANNEL ] != XCPCAN_INVALID_MSGID )
    {
        /* The current channel is associated with a dynamic DAQ list, and the list has a msg ID which was configured
         * at runtime. */
        configuredMsgId = pSessionCfg->pDynDaqMsgIds[ channelId - XCP_FIRST_DAQ_CHANNEL ];
    }

#endif /* XCP_ENABLE_DYNDAQ */

    /* Note that the CAN DLC is encoded in the top nibble of bufferState. */
    
    //for(i=0; i< 8; i++)
    //{
     //can_data[i] =  (uint8 *)pQueueBuffer->msgBuffer++;	
    //}
    
    //pdat = (Xcp_StatePtr8)pQueueBuffer->msgBuffer;
    
    XcpApp_CanTransmit( pChannelCfg->msgObjId, configuredMsgId, (*pQueueBufState) >> 4,  (Xcp_StatePtr8)pQueueBuffer->msgBuffer );

    /* Clear the queue buffer associated with the transmitted message. */
    pQueueBuffer->msgBuffer[0] = 0;
    pQueueBuffer->msgBuffer[1] = 0;

    /* Set buffer to free */
    *pQueueBufState = XCP_TXRXFREE;

    /* Advance the current CAN buffer in the queue for the channel, wrapping if necessary. */
    if( *pCanPos != pChannelCfg->idxEnd )
    {
        ++( *pCanPos );
    }
    else
    {
        *pCanPos = pChannelCfg->idxStart;
    }
}

里边调用 XcpApp_CanTransmit 函数

void XcpApp_CanTransmit(
    XcpCan_MsgObjId_t   msgObjId,
    uint32              msgId,
    uint                numBytes,
    Xcp_StatePtr8       pBytes
)
{

    uint8  cnt;
    uint8  BufN;
    uint8  *msg;
    uint16 TxID;
    uint8 length;
    uint8_t i,j;
    
    BufN = (uint8)msgObjId;
    TxID = (uint16)msgId;
    
    length = numBytes;
    if (XcpTransCrmPossible(BufN)) 
    {    
        CAN_C.BUF[BufN].CS.B.IDE = 0;            // Use standard ID length 
        CAN_C.BUF[BufN].CS.B.RTR = 0;            // Data frame, not remote Tx request frame 
        CAN_C.BUF[BufN].CS.B.LENGTH = numBytes; 
        CAN_C.BUF[BufN].ID.B.STD_ID = TxID;      // Transmit ID 
        
        msg = pBytes;
        
        for(i=0;i<8;i++)
        {
          dat[i] = *msg++;	
        }
        for (cnt=0,j=0;cnt<8;cnt++,j++) 
        {
            CAN_C.BUF[BufN].DATA.B[cnt] = dat[j];//*pBytes++;  //*msg++;	
        }

        CAN_C.BUF[BufN].CS.B.SRR = 1;           // Tx frame (not req'd for standard frame)
        CAN_C.BUF[BufN].CS.B.CODE =0xC;         // Activate msg. buf. to transmit data frame
    }
}
注意:此处根据芯片不同写不同的candriver

3.CAN接收函数(XCP调用)

static void CanBuf0ISR(void)
{
    uint32 dummy;
    uint8 cnt;

    RxCode   = CAN_C.BUF[CRO_BUF_N].CS.B.CODE;    // Read CODE, ID, LENGTH, DATA, TIMESTAMP 
    Rec_Id = CAN_C.BUF[CRO_BUF_N].ID.B.STD_ID;
    length=(uint8)CAN_C.BUF[CRO_BUF_N].CS.B.LENGTH;

    for (cnt=0; cnt<8; cnt++) {
        tmpRevData[cnt] = CAN_C.BUF[CRO_BUF_N].DATA.B[cnt];
    }

    dummy = CAN_C.BUF[CRO_BUF_N].CS.B.TIMESTAMP; 
    dummy = CAN_C.TIMER.R;                // Read TIMER to unlock message buffers     

	CAN_C.IFRL.B.BUF00I = 1;   	// clear interrupt 

    XcpCan_RxCallback(Rec_Id, length, (uint8*)&tmpRevData[0]);
}

CAN中断根据不同的底层来匹配,通过 XcpCan_RxCallback(Rec_Id, length, (uint8*)&tmpRevData[0])函数和协议有所交互.
具体函数如下

void XCP_FN_TYPE XcpCan_RxCallback(
    uint32  msgId,
    uint8   msgLen,
    uint8*  pMsgData
)
{
    Xcp_StatePtr32        pCtCanPos;
    uint                  channelId;
    uint                  sessionId;
    XcpCan_SessionCfg_t*  pSessionCfg     = XcpCan_SessionCfgs;
    Xcp_StatePtr8         pQueueBufState;
#ifdef XCP_ENABLE_STIM
    uint                  pidOffEnabled;
    uint32                configuredMsgId;
    XcpCan_ChannelCfg_t*  pChannelCfg;
    Xcp_DaqConfig_t*      pDaqCfg;
    Xcp_Daq_t*            pDaqState;
#endif /* XCP_ENABLE_STIM */

    /* Search all CAN channels for all sessions to try to identify the CAN channel to which the RX message belongs. */

    for( sessionId = 0; sessionId < XCP_NUM_SESSIONS; ++sessionId )
    {
        /* Is the CAN message is a broadcast CMD_GET_SLAVE_ID? */
        if( msgId == pSessionCfg->broadcastMsgId &&
            pMsgData[0] == XCP_CMD_TRANSPORT_LAYER_CMD && pMsgData[1] == XCPCAN_CMD_GET_SLAVE_ID )
        {
            channelId = XCP_RX_CMD_CHANNEL;
            break;
        }
        /* Is the CAN message a command? Note that it is not sufficient just to check the message's PID since the message
         * could be:
         *  - a command message destined for another session;
         *  - a PID_OFF STIM message, with no valid PID. */
        else if( pMsgData[0] >= XCP_PID_CMD_LAST && msgId == pSessionCfg->pChannelCfgs[ XCP_RX_CMD_CHANNEL ].msgId )
        {
            /* The CAN message belongs to the XCP_RX_CMD_CHANNEL channel. */
            channelId = XCP_RX_CMD_CHANNEL;
            break;
        }
#ifdef XCP_ENABLE_STIM
        else
        {
            /* The CAN message does not contain a command, therefore it must contain a STIM DTO packet.
             * We search the CAN channels associated with STIM lists to find the channel to which the RX message belongs.
             *
             * Throughout, we assume that:
             *  - A CAN channel index can be translated to the equivalent DAQ list ID by subtracting XCP_FIRST_DAQ_CHANNEL.
             *  - The first STIM CAN channel has index XcpCan_SessionCfg_t::firstRxStimChannel.
             *  - The last STIM CAN channel has index XcpCan_SessionCfg_t::numChannels - 1.
             */

            channelId   = pSessionCfg->firstRxStimChannel;
            pChannelCfg = pSessionCfg->pChannelCfgs + channelId;
            pDaqState   = Xcp_SessionConfigs[ sessionId ].pDaqStates + channelId - XCP_FIRST_DAQ_CHANNEL;
            pDaqCfg     = Xcp_SessionConfigs[ sessionId ].pDaqConfigs + channelId - XCP_FIRST_DAQ_CHANNEL;

            for( ; channelId < pSessionCfg->numChannels; ++channelId )
            {
                /* Skip the current channel if it corresponds to a DAQ list which is not running or is not a STIM list. */
                if( ( XCP_DAQLISTMODE_RUNNING | XCP_DAQLISTMODE_DIRECTION ) != ( pDaqState->daqListMode & ( XCP_DAQLISTMODE_RUNNING | XCP_DAQLISTMODE_DIRECTION ) ) )
                {
                    ++pChannelCfg;
                    ++pDaqState;
                    ++pDaqCfg;
                    continue;
                }

                /* Find the CAN msg ID which has been configured for the current channel. This is not entirely straightforward,
                 * since the msg ID of a dynamic DAQ list can be set at runtime.*/

                configuredMsgId = pChannelCfg->msgId;

#ifdef XCP_ENABLE_DYNDAQ
                if( pSessionCfg->pDynDaqMsgIds &&
                    pSessionCfg->pDynDaqMsgIds[ channelId - XCP_FIRST_DAQ_CHANNEL ] != XCPCAN_INVALID_MSGID )
                {
                    /* The current channel is associated with a dynamic DAQ list, and the list has a msg ID which was configured
                     * at runtime. */
                    configuredMsgId = pSessionCfg->pDynDaqMsgIds[ channelId - XCP_FIRST_DAQ_CHANNEL ];
                }
#endif /* XCP_ENABLE_DYNDAQ */

                if( configuredMsgId == msgId )
                {
                    /* We have found a CAN channel which shares the same message ID as the RX message.
                     * If:
                     *  - the current channel is associated with a DAQ list configured for PID_OFF mode, or
                     *  - the current channel is not associated with a DAQ list configured for PID_OFF mode, and
                     *    the PID of the RX message is within the PID range of the DAQ list associated with the
                     *    current channel,
                     * then the RX message belongs to the current channel.*/

                    pidOffEnabled = pDaqState->daqListMode & XCP_DAQLISTMODE_PIDOFF;

                    if( pidOffEnabled ||
                        ( !pidOffEnabled && pMsgData[0] >= pDaqCfg->firstPid && pMsgData[0] < ( pDaqCfg->firstPid + pDaqCfg->numOdt ) ) )
                    {
                        /* The CAN message belongs to the current STIM channel. */
                        break;
                    }
                }
                ++pChannelCfg;
                ++pDaqState;
                ++pDaqCfg;
            }

            if( channelId < pSessionCfg->numChannels )
            {
                /* The inner loop successfully identified the STIM channel which is associated with the RX message. */
                break;
            }
        }
#endif /* XCP_ENABLE_STIM */

        ++pSessionCfg;
    }

    if(sessionId == XCP_NUM_SESSIONS )
    {
        /* The RX message is not associated with any of our CAN channels. */
        return;
    }

    pSessionCfg     = XcpCan_SessionCfgs + sessionId;
    pCtCanPos       = &( pSessionCfg->pQueuePositions[ channelId ].ctCanPos );
    pQueueBufState  = pSessionCfg->pQueueBufferStates + *pCtCanPos;

    /* Copy the received message to the current CAN buffer for the channel, if the current CAN buffer is free. */
    if( *pQueueBufState == XCP_TXRXFREE )
    {
        /* We could just copy msgLen bytes of data into the current CAN buffer for the channel, but we take advantage of the
         * following facts to copy the data in a multiple of whichever block size the current target finds most convenient:
         *  - msgLen is <= 8
         *  - the buffer has 8 bytes of space;
         *  - the buffer is aligned on a natural boundary. */
        if( msgLen % XCP_MEM_BLOCK_SIZE )
        {
            /* Round msgLen up to the next multiple of XCP_MEM_BLOCK_SIZE. */
            msgLen += XCP_MEM_BLOCK_SIZE - ( msgLen % XCP_MEM_BLOCK_SIZE );
        }
        /* msgLen is now guaranteed to be a multiple of XCP_MEM_BLOCK_SIZE. */
        Xcp_MemCopy( (Xcp_StatePtr8)pSessionCfg->pQueueBuffers[ *pCtCanPos ].msgBuffer, pMsgData, msgLen );

        /* Set current queue buffer to XCP_RXDATA */
        *pQueueBufState = XCP_RXDATA;

        /* Last buffer in queue? */
        if( *pCtCanPos != pSessionCfg->pChannelCfgs[ channelId ].idxEnd )
        {
            /* next queue buffer */
            ++( *pCtCanPos );
        }
        else
        {
            /* Back to queue start */
            *pCtCanPos = pSessionCfg->pChannelCfgs[ channelId ].idxStart;
        }
    }

    return;
}

DAQ 列表通过如下中断调用

static void CanBuf1ISR(void)
{
	CAN_C.IFRL.B.BUF01I = 1;   	// clear interrupt 
	XcpCan_TxCallback(1);

}
static void CanBuf2ISR(void)
{
	CAN_C.IFRL.B.BUF02I = 1;    // clear interrupt 
	XcpCan_TxCallback(2);	
}
static void CanBuf3ISR(void)
{
	CAN_C.IFRL.B.BUF03I = 1;    // clear interrupt 
	XcpCan_TxCallback(3);
}

相关标签: XCP CCP在线标定