一.前言:
通信模塊可以大致分為三大功能:數(shù)據(jù)發(fā)送功能,數(shù)據(jù)接收功能,狀態(tài)切換和管理功能。
我們的系列按照這樣的功能排序和自底向上的模塊排序,每次只介紹其中的一個(gè)模塊的其中一個(gè)功能的實(shí)現(xiàn),所以在每篇文章中對(duì)于模塊不會(huì)事無(wú)巨細(xì)的介紹所有它所具備的功能,而是選擇性的介紹三大功能中的其中一個(gè)。BSW往上的所有模塊示例,為最大程度了解其設(shè)計(jì)思路以及避免侵權(quán)風(fēng)險(xiǎn),將會(huì)采用遵循AUTOSAR架構(gòu)的非商業(yè)代碼作為示例,其部分細(xì)節(jié)不保證完全遵循AUTOSAR最新的標(biāo)準(zhǔn),不保證所有功能的具備,敬請(qǐng)理解。
二.Canif模塊及其發(fā)送函數(shù)CanIf_Transmit
在上節(jié)的文章中介紹了CAN模塊的發(fā)送底層邏輯,Can_Write函數(shù)的介紹。Can_Write函數(shù)已經(jīng)對(duì)CAN驅(qū)動(dòng)進(jìn)行了抽象。抽象為了HOH供上層使用。而它的上層就是CanIf層.在CanIf模塊中,主要實(shí)現(xiàn)的功能如下:
1.傳輸請(qǐng)求(Transmit request)
傳輸請(qǐng)求功能的實(shí)現(xiàn)主體函數(shù)是CanIf_Transmit,這個(gè)函數(shù)內(nèi)部調(diào)用Can_Write進(jìn)行報(bào)文的發(fā)送
2.傳輸確認(rèn)(Transmit confirmation)
傳輸確認(rèn)功能的實(shí)現(xiàn)主體函數(shù)是CanIf_TxConfirmation,這個(gè)函數(shù)在CAN發(fā)送完成后被調(diào)用,作用是調(diào)用更上層的發(fā)送確認(rèn)回調(diào)函數(shù)通知更上層的各個(gè)模塊對(duì)應(yīng)的PDU已發(fā)送成功。
3.接收提示(Reception indication)
傳輸確認(rèn)功能的實(shí)現(xiàn)主體函數(shù)是CanIf_RxIndication,這個(gè)函數(shù)在CAN發(fā)送完成后被調(diào)用,作用是調(diào)用更上層的發(fā)送確認(rèn)回調(diào)函數(shù)通知更上層的各個(gè)模塊對(duì)應(yīng)的PDU已發(fā)送成功。
4.CAN控制器模式切換(Controller mode control)
controller模式切換的功能實(shí)現(xiàn)主體函數(shù)是CanIf_SetControllerMode,涉及到模式切換的功能后面專題詳解
5.PDU模式切換(PDU mode control)
PDU模式切換的功能實(shí)現(xiàn)主體函數(shù)是CanIf_SetPduMode,涉及到模式切換的功能后面專題詳解
整個(gè)CanIf模塊實(shí)現(xiàn)的基本函數(shù)如下:
本文側(cè)重介紹CanIf模塊的發(fā)送功能。CanIf的報(bào)文發(fā)送功能由CanIf_Transmit函數(shù)實(shí)現(xiàn),此函數(shù)原型如下:
Std_ReturnType CanIf_Transmit(PduIdType CanTxPduId,
const PduInfoType *PduInfoPtr)
此函數(shù)會(huì)調(diào)用MCAL的Can模塊中的Can_Write函數(shù)進(jìn)行報(bào)文的發(fā)送。在上節(jié)介紹Can_Write函數(shù)的時(shí)候,說(shuō)過(guò)其傳入的參數(shù)是以下:
- HOH
- CAN id:報(bào)文ID
- length:報(bào)文長(zhǎng)度
- sdu:報(bào)文數(shù)據(jù)
- swPduHandle :tx_confirm的ID
而CanIf層的傳入?yún)?shù)變?yōu)榱耍?/p>
- CanTxPduId,
- PduInfoPtr這個(gè)參數(shù)包括了SduDataPtr和SduLength
所以CanTxPduId對(duì)Can_Write函數(shù)所需的HOH,CAN ID,swPduHandle做了抽象。我們基本也可以推斷出CanIf的TxPDU所需要配置的主要內(nèi)容了。
三.Canif模塊的發(fā)送配置解析
以下例子用于說(shuō)明CanIf層的tx配置。
Canif涉及到發(fā)送報(bào)文的主要配置結(jié)構(gòu)體如下:
const CanIf_InitConfigType CanIfInitConfig =
{
.CanIfConfigSet = 0,
.CanIfNumberOfCanRxPduIds = sizeof(CanIfRxPduConfigData)/sizeof(CanIf_RxPduConfigType),
.CanIfNumberOfCanTXPduIds = sizeof(CanIfTxPduConfigData)/sizeof(CanIf_TxPduConfigType),
.CanIfNumberOfDynamicCanTXPduIds = 0,
// Containers
.CanIfHohConfigPtr = CanIfHohConfigData,
.CanIfRxPduConfigPtr = CanIfRxPduConfigData,
.CanIfTxPduConfigPtr = CanIfTxPduConfigData,
};
我們以下主要關(guān)注:
1.HOH的配置結(jié)構(gòu)體CanIfHohConfigData,
2.發(fā)送PDU配置結(jié)構(gòu)體CanIfTxPduConfigData
1.HOH的配置結(jié)構(gòu)體CanIfHohConfigData,
對(duì)于HOH的配置結(jié)構(gòu)體CanIfHohConfigData的結(jié)構(gòu)如下:
const CanIf_InitHohConfigType CanIfHohConfigData[] = {
{
#if(CANIF_CONTROL_CAN_DRIVER ==STD_ON)
.CanConfigSet = &CanConfigSetData,
#endif
.CanIfHrhConfig = CanIfHrhConfigData_Hoh_1,
.CanIfHthConfig = CanIfHthConfigData_Hoh_1,
},
};
其中配置了發(fā)送的HTH和接收的HRH。對(duì)于發(fā)送的HTH配置如下:
const CanIf_HthConfigType CanIfHthConfigData_Hoh_1[] =
{
{
.CanIfHthType = CAN_BASIC,
.CanIfCanControllerIdRef = CANIF_Channel_1,
.CanIfHthIdSymRef = HOH_3_UDSTX_Node,
},
{
.CanIfHthType = CAN_BASIC,
.CanIfCanControllerIdRef = CANIF_Channel_1,
.CanIfHthIdSymRef = HOH_3_NMTX_Node,
},
{
.CanIfHthType = CAN_BASIC,
.CanIfCanControllerIdRef = CANIF_Channel_1,
.CanIfHthIdSymRef = HOH_3_XCPTX_Node,
},
{
.CanIfHthType = CAN_BASIC,
.CanIfCanControllerIdRef = CANIF_Channel_1,
.CanIfHthIdSymRef = HOH_3_EcuTestNode_CanCluster,
},
};
主要就是引用了上節(jié)文章例子中介紹的CAN模塊配置的四個(gè)HOH。
2.發(fā)送PDU配置結(jié)構(gòu)體數(shù)組CanIfTxPduConfigData
這個(gè)結(jié)構(gòu)體數(shù)組有所有的發(fā)送PDU配置,每個(gè)PDU都是一個(gè)結(jié)構(gòu)體成員,其中的一個(gè)成員配置示例如下:
const CanIf_TxPduConfigType CanIfTxPduConfigData[] = {
{
.CanIfTxConfrimPduId = CANTP_PDU_ID_UDS_PHYS_TX,
.CanIfCanTxPduIdCanId = 0x7ea,
.CanIfCanTxPduIdDlc = 8,
.CanIfCanTxPduType = CANIF_PDU_TYPE_STATIC,
#if ( CANIF_READTXPDU_NOTIFY_STATUS_API == STD_ON )
.CanIfReadTxPduNotifyStatus = false,
#endif
.CanIfTxPduIdCanIdType = CANIF_CAN_ID_TYPE_11,
.CanIfUserTxConfirmation = CanTp_TxConfirmation,
.CanIfCanTxPduHthRef = &CanIfHthConfigData_Hoh_1[0],
.PduIdRef = NULL,
},
.....
}
關(guān)鍵的參數(shù)解釋如下:
- CanIfTxConfrimPduId :用于為swPduHandle 復(fù)值,向?qū)?yīng)的TxConfirm函數(shù)傳入?yún)?shù)。
- CanIfCanTxPduIdCanId:對(duì)應(yīng)PDU的報(bào)文ID
- CanIfCanTxPduIdDlc:對(duì)應(yīng)PDU的報(bào)文長(zhǎng)度
- CanIfUserTxConfirmation:發(fā)送確認(rèn)回調(diào)函數(shù)
- CanIfCanTxPduHthRef:發(fā)送此PDU要使用的HOH
類似上節(jié)的結(jié)尾說(shuō)到的抽象。這些配置元素打包成一個(gè)結(jié)構(gòu)體數(shù)組元素,
CanIf_Transmit需要傳入的CanTxPduId,即代表這個(gè)配置結(jié)構(gòu)體數(shù)組的數(shù)組下標(biāo)。用來(lái)索引到其抽象的對(duì)象屬性。說(shuō)起來(lái)比較枯燥,以下是CanIf_Transmit的實(shí)現(xiàn)函數(shù):
Std_ReturnType CanIf_Transmit(PduIdType CanTxPduId,
const PduInfoType *PduInfoPtr)
{
Can_PduType canPdu;
const CanIf_TxPduConfigType *txEntry;
CanIf_ControllerModeType csMode;
CanIf_ChannelGetModeType pduMode;
VALIDATE(CanIf_Global.initRun, CANIF_TRANSMIT_ID, CANIF_E_UNINIT );
VALIDATE((PduInfoPtr != 0), CANIF_TRANSMIT_ID, CANIF_E_PARAM_POINTER );
// Get the controller from L-PDU handle
txEntry = CanIf_FindTxPduEntry(CanTxPduId);
if (txEntry == 0)
{
VALIDATE(FALSE, CANIF_TRANSMIT_ID, CANIF_E_INVALID_TXPDUID);
return E_NOT_OK;
}
CanIf_Arc_ChannelIdType channel = txEntry- >CanIfCanTxPduHthRef- >CanIfCanControllerIdRef;
// Get and verify the controller mode
if (CanIf_GetControllerMode(channel, &csMode) == E_NOT_OK){
return E_NOT_OK;
}
if (csMode != CANIF_CS_STARTED){ // CANIF_161
return E_NOT_OK;
}
// Get and verify the PDU channel mode control
if (CanIf_GetPduMode(channel, &pduMode) == E_NOT_OK){
return E_NOT_OK;
}
if ((pduMode != CANIF_GET_TX_ONLINE) && (pduMode != CANIF_GET_ONLINE)){
return E_NOT_OK;
}
canPdu.id = txEntry- >CanIfCanTxPduIdCanId;
canPdu.length = PduInfoPtr- >SduLength;
canPdu.sdu = PduInfoPtr- >SduDataPtr;
canPdu.swPduHandle = CanTxPduId;
Can_ReturnType rVal = Can_Write(txEntry- >CanIfCanTxPduHthRef- >CanIfHthIdSymRef, &canPdu);
if (rVal == CAN_NOT_OK){
return E_NOT_OK;
}
if (rVal == CAN_BUSY) // CANIF 082, CANIF 161
{
// Tx buffering not supported so just return.
return E_NOT_OK;
}
return E_OK;
}
注意到其中CanIf_Transmit的傳入?yún)?shù)CanTxPduId的使用方式:
txEntry = CanIf_FindTxPduEntry(CanTxPduId);
CanIf_FindTxPduEntry的函數(shù)原型如下
static const CanIf_TxPduConfigType * CanIf_FindTxPduEntry(PduIdType id)
{
if (id >= CanIf_ConfigPtr- >InitConfig- >CanIfNumberOfCanTXPduIds) {
return NULL;
} else {
return &CanIf_ConfigPtr- >InitConfig- >CanIfTxPduConfigPtr[id];
}
}
就是以CanIf_Transmit的傳入?yún)?shù)CanTxPduId為下標(biāo),找到對(duì)應(yīng)的CanIfTxPduConfigData的數(shù)組成員。并獲取其屬性,對(duì)Can_Write函數(shù)的傳入?yún)?shù)進(jìn)行配置。調(diào)用Can_Write函數(shù)進(jìn)行發(fā)送。
四.發(fā)送確認(rèn)函數(shù):CanIf_TxConfirmation
CanIf_TxConfirmation是由Can模塊底層驅(qū)動(dòng)在PDU傳輸完成后調(diào)用的。之前講到Can_Write函數(shù)的其中一個(gè)傳入?yún)?shù):swPduHandle是用來(lái)在底層標(biāo)記傳輸?shù)腜DU ID,在更新MessageBuffer前記住PDU對(duì)應(yīng)的swPduHandle參數(shù),在對(duì)應(yīng)的PDU發(fā)出去后,底層驅(qū)動(dòng)函數(shù)調(diào)用CanIf_TxConfirmation傳入swPduHandle。
而我們的CanIf_TxConfirmation實(shí)現(xiàn)如下:
void CanIf_TxConfirmation(PduIdType canTxPduId)
{
VALIDATE_NO_RV(CanIf_Global.initRun, CANIF_TXCONFIRMATION_ID, CANIF_E_UNINIT)
VALIDATE_NO_RV(canTxPduId < CanIf_ConfigPtr- >InitConfig- >CanIfNumberOfCanTXPduIds, CANIF_TXCONFIRMATION_ID, CANIF_E_PARAM_LPDU);
const CanIf_TxPduConfigType* entry =
&CanIf_ConfigPtr- >InitConfig- >CanIfTxPduConfigPtr[canTxPduId];
if (entry- >CanIfUserTxConfirmation != NULL)
{
CanIf_ChannelGetModeType mode;
CanIf_GetPduMode(entry- >CanIfCanTxPduHthRef- >CanIfCanControllerIdRef, &mode);
if ((mode == CANIF_GET_TX_ONLINE) || (mode == CANIF_GET_ONLINE)
|| (mode == CANIF_GET_OFFLINE_ACTIVE) || (mode == CANIF_GET_OFFLINE_ACTIVE_RX_ONLINE) )
{
entry- >CanIfUserTxConfirmation(entry- >CanIfTxPduId); /* CANIF053 */
}
}
return;
}
在這個(gè)函數(shù)中,會(huì)直接向上文CanIfTxPduConfigData配置的CanIfUserTxConfirmation中傳入swPduHandle。
而在CanIf_Transmit中,swPduHandle又是由CanIfTxPduConfigData配置的CanIfTxConfrimPduId決定的。所以CanIfTxConfrimPduId會(huì)作為參數(shù)傳入對(duì)應(yīng)的CanIfUserTxConfirmation。
這期的介紹就到這,本期介紹了CanIf主要實(shí)現(xiàn)的功能,主要函數(shù),主要的發(fā)送配置以及CanIf_Transmit,CanIf_TxConfirmation的機(jī)制,可以了解CanIf做了更進(jìn)一步的抽象,將HOH進(jìn)一步抽象為了PDU。各個(gè)AUTOSAR架構(gòu)的代碼實(shí)現(xiàn)并不一致,文中所有的函數(shù)實(shí)現(xiàn)和配置思路僅作參考。
-
CAN通信
+關(guān)注
關(guān)注
5文章
97瀏覽量
18427 -
接收機(jī)
+關(guān)注
關(guān)注
9文章
1224瀏覽量
54580 -
AUTOSAR
+關(guān)注
關(guān)注
10文章
380瀏覽量
22673 -
PDU
+關(guān)注
關(guān)注
0文章
96瀏覽量
17336 -
CAN控制器
+關(guān)注
關(guān)注
3文章
75瀏覽量
15340
發(fā)布評(píng)論請(qǐng)先 登錄
ZYNQ進(jìn)階:PL端UART 發(fā)送設(shè)計(jì)案例

使用CAN以及CANIF配置了S32K310的CAN驅(qū)動(dòng)模塊,如何進(jìn)行報(bào)文的接收呢?
求助,使用EB配置S32K310 MCAL CAN模塊時(shí)遇到的疑問(wèn)求解
cubemx配置的串口中斷發(fā)送HAL_UART_Transmit_IT不行
請(qǐng)問(wèn)怎么用HAL_UART_Transmit發(fā)送數(shù)值型數(shù)據(jù)?
AUTOSAR_MCAL_CAN_IM.pdf提示找不到 config/CanIf.xdm怎么解決?
在EB tresos 23.0.0中配置模塊時(shí)出錯(cuò)怎么解決?
Verilog實(shí)現(xiàn)UART之二:發(fā)送模塊

發(fā)送隊(duì)列長(zhǎng)度功率控制

基于CAN總線進(jìn)行網(wǎng)絡(luò)管理與Transceiver的關(guān)系梳理

AUTOSAR通信之CanIf模塊簡(jiǎn)介1

AUTOSAR通信之CanIf模塊簡(jiǎn)介2

AUTOSAR通信之CanIf模塊簡(jiǎn)介3

EthIf模塊的主要作用是什么?Ethif的常見(jiàn)函數(shù)接口有哪些呢?
PduR模塊的發(fā)送機(jī)制 PduR這個(gè)模塊對(duì)什么進(jìn)行了抽象呢?

評(píng)論