基于Autosar 架构CANif层路由Canopen协议栈
基于现有can驱动框架,在canif层增加路由功能,从而兼容canopen协议栈。
一、数据处理过程
1、接收数据处理流程
数据接收处理流程,如下图所示,整体软件架构为BSP 层、If层、应用层。在bsp层处理rx中断,产生回调函数,调用can if 层的回调函数,然后进行can的有效性删选,之后有效的pdu报文会发送给canopen协议栈,其处理流程图如下所示。
注意:在can bsp层初始化中,会配置can的筛选器,属于非法的can id是无法产生中断的,也就是说,非法的can id是无法发起如下流程的。
2、数据发送处理流程
与接收的报文的相似,数据发送报文的处理流程如下图所示。
3、CAN 软件框架
注意:由于历史原因 CAN2.0的协议栈暂未集成CAN TP协议,采用外挂的can tp协议,同时该协议与uds的dcm处理结合度比较大。在下一版规划中,CAN2.0协议栈将集成CAN TP,并释放DCM的接口。
二、头文件配置
头文件配置需要对如下两个文件进行配置canopen_adpt_cfg.h、can_if_cfg.h
1、canopen_adpt_cfg.h 配置
canopen_adpt_cfg.h头文件的配置中主要包含如下配置pduID和CAN id的配置。
对TX、RX报文数量进行配置。
注意:在本次配置中只增加RX PDO的ID,其他canopen类型的报文暂时没有接受(部分CANopen协议栈已经做了修改)
#define CANOPEN_RX_NUM (14)
#define CANOPEN_TX_NUM (4)
//PDU ID
#define CANOPEN_ROUTING_PATH_RPDO1 (1)
#define CANOPEN_ROUTING_PATH_RPDO2 (2)
...
//CAN ID
#define CANOPEN_RPDO1_CAN_ID (0x187)
#define CANOPEN_RPDO2_CAN_ID (0x181) ...
2、can_if_cfg.h配置
(1)需要修改 CANIF的所需要收发的PDU数量。
/* define number of transmit and receive pdu*/
#define CANIFRX_TOTAL_NUM (14 +UDS_RX_TOTAL_NUM+CANOPEN_RX_NUM)
#define CANIFTX_TOTAL_NUM (5 + 1+CANOPEN_TX_NUM) //ADD UDS TX
(2)需要开启canopen的宏定义,使其功能开启
#define USE_CANOPEN TX PDU ID
三、源文件配置
1、can_if_cfg.c配置
在can if的配置参数表中增加 canopen相关的pdu。
(1)接收配置
const CanIf_RxPduConfigType CanIfRxPduConfigData[CANIFRX_TOTAL_NUM] =
{
CANOPEN_PDU_REGISTER(CANOPEN_PDU_ID_RPDO1, CANOPEN_RPDO1_CAN_ID),
}
(2)发送配置
const CanIf_TxPduConfigType CanIfTxPduConfigData[CANIFTX_TOTAL_NUM] =
{
...
//CANOPEN
CANOPEN_TX_PDU_REGISTER(CANOPEN_PDU_ID_TX_PDO_1, CANOPEN_CAN_ID_TX_PDO_1),
CANOPEN_TX_PDU_REGISTER(CANOPEN_PDU_ID_TX_PDO_2, CANOPEN_CAN_ID_TX_PDO_2),
CANOPEN_TX_PDU_REGISTER(CANOPEN_PDU_ID_TX_PDO_3, CANOPEN_CAN_ID_TX_PDO_3),
CANOPEN_TX_PDU_REGISTER(CANOPEN_PDU_ID_TX_PDO_4, CANOPEN_CAN_ID_TX_PDO_4),
CANOPEN_TX_PDU_REGISTER(CANOPEN_PDU_ID_TX_SDO, CANOPEN_PDU_ID_TX_SDO),
...
四、接口文件适配
1、canopen_adpt.c配置
(1)canopen接收回调函数接口
增加接口函數,调用canopen的port中接收中断函数。
/**
* @brief CAN UDS RX callback
* @param CanRxPduId
* @param PduInfoPtr
*/
void Canopen_RxInCallback(uint32_t CanId, const PduInfoType *PduInfoPtr)
{
if (PduInfoPtr == NULL)
return;
canopen_adpt_rcv(CanId, PduInfoPtr->SduLength, NULL, PduInfoPtr->SduDataPtr);
}
(2)canopen发送函数接口
/**
* @brief Canopen tx msg
* @param handle not use
* @param msg can msg
*/
unsigned char Canopen_TxSend(unsigned char ** handle, CanMsgTypedef *msg)
{
PduInfoType PduInfoPtr; PduInfoPtr.SduLength = msg->len;
PduIdType PDUId = 0;
if (msg->len <= 8)
{
Canif_FindTxPduid(msg->cob_id, &PDUId);
PduInfoPtr.SduDataPtr = msg->data;
if (STD_ERR_OK == (CanIf_Transmit(PDUId, &PduInfoPtr)))
{
return 0;
}
else
{
__NOP();
return 1;
}
} else
{
return 1;
}
}
2、can_if.c
(1)接收回调需要增加如下case
switch (entry->CanIfRxUserType)
{
...
case CANIF_USER_TYPE_CANOPEN:
#if defined(USE_CANOPEN)
{
PduInfoType CanopenRxPdu;
CanopenRxPdu.SduLength = CanDlc;
CanopenRxPdu.SduDataPtr = (uint8_t *)CanSduPtr;
Canopen_RxInCallback(entry->CanIfCanRxPduCanId, &CanopenRxPdu);
} return;
#endif
break;
...
}
}
entry++;
}