CanTP — Transport Protocol, for CAN communication in AUTOSAR BSW.

Abhishek Anand
9 min readAug 25, 2020

--

The CanTp module offers services for segmentation, transmission with flow control, and reassembly of messages. Its main purpose is to transmit and receive messages that may or may not fit into a single CAN frame. Messages that do not fit into a single CAN frame are segmented into multiple parts, such that each can be transmitted in a single CAN frame.

Position in the BSW

States and sub-states of CanTp

  • CanTp has two states CANTP_OFF and CANTP_ON.
  • On Power On the default state is CANTP_OFF. The state shall change to CANTP_ON only on a successful call to CanTp_Init().
  • To change state from CANTP_ON to CANTP_OFF, call CanTp_Shutdown()
  • Within the CANTP_ON state each connection channel shall be in their default states, CANTP_RX_WAIT and CANTP_TX_WAIT.
  • Only when a N-PDU is being received or transmitted, the state will change to CANTP_RX_PROCESSING and CANTP_TX_PROCESSING, respectively.
  • Calling CanTp_Init() when the CanTp is already in CANTP_ON will cause it to lose all current connection and come to ideal state where it is not processing any messages.

Interfaces from PduR and CanIf used by CanTp

CanTp-PduR Interfaces

CanTp uses the callback functions of PduR

  • PduR_CanTpRxIndication : Indicates reception complete
  • PduR_CanTpStartOfReception : Indicates start of reception
  • PduR_CanTpCopyRxData : Copy received data
  • PduR_CanTpCopyTxData : Copy transmit data
  • PduR_CanTpTxConfirmation : Indicates transmission confirmation

CanTp-CanIf Interfaces

  • CanIf_Transmit : to transmit the data

Interface provided by CanTp to PduR and CanIf

Interface provided to PduR

CanTp_Transmit()

  • This allows the upper layers to request for CanTp services.
  • After the transmit request is accepted, CanTp will notify the upper layer of the result of the transmit, once it has completed the transmit process. by calling PduR_CanTpTxConfirmation().
  • The function CanTp_Transmit() is asynchronous.

CanTp_CancelTransmit()

  • This allows the upper layer to cancel an ongoing transmission.
  • This feature can be deactivated by static configuration parameter, CanTpTc.
  • This is used when a new diagnostic request has been received on a protocol of higher priority.
  • After a call to this the currently ongoing transmit will be aborted, and this will cause a timeout error on the receiver side.
  • After a successful call to CanTp_CancelTransmit(), CanTp module shall call PduR_CanTpTxConfirmation() with result E_NOT_OK.

Interface provided to CanIf

CanTp_TxConfirmation()

  • This is provided as a callback to the CanIf module.
  • CanIf calls this to indicate that the CAN frame transmission was successful.
  • If this transmit confirmation is not received within N_As, then CanTp assumes the transmission to have failed and will not acknowledge any confirmation received after N_As timeout.

CanTp_RxIndication()

  • CanIf will call CanTp_RxIndication() to indicate that a new frame has been received.
  • This reception indication shall be performed in ISR context as per CanIf configuration.

Internal Behaviour

N-SDU Reception

During N-SDU Reception, CanTp will receive SF or FF or, a CF if the request to receive is accepted and is required to send FC for the sender. Before we see the behaviour we need to know about the interfaces involved.

PduR_CanTpStartOfReception()

  • When receiving a SF or FF N-PDU, CanTp shall notify PduR of the incoming transmission by calling PduR_CanTpStartOfReception().
  • This call will let PduR know of the size of the incoming message.
  • PduR is expected to allocate a buffer to receive this message and returns the size of the buffer allocated (PduLenType* bufferSizePtr) and the result of the call (BufReq_ReturnType) indicating whether the connection has been accepted or rejected.

PduR_CanTpCopyRxData()

  • This is called to copy the received data to the PduR buffer.
  • On every call it provides the size of the remaining buffer. This can be used to get the amount of buffer remaining in the PduR module.

PduR_CanTpRxIndication()

This is used to indicate an I-PDU has been received from the lower layers.

It is easier if we have a reference to the segmentation sequence flow diagram.

Lets see the behaviour of CanTp when receiving either of these frames.

About CF,

On reception of each CF, PduR_CanTpCopyRxData() is called to copy the data to PduR and the N_Cr timer is started (except the last CF). This timer is also started at the confirmation of FC.CTS transmission. If this N_Cr timer timeout occurs then CanTp will call PduR_CanTpRxIndication() with result E_NOT_OK. Also, the Sequence number of the CF is also checked by CanTp. If the SN is found to be incorrect, CanTp will abort the reception and notify the upper layer by calling PduR_CanTpRxIndication() with E_NOT_OK.

After receiving one complete block, i.e after the last CF of one block of messages, PduR_CanTpCopyRxData() is called and if it returns BUFREQ_OK, but the remaining buffer size is not sufficient for the reception of the next block, CanTp will continue with the reception and start the N_Br timer. While N_Br is active, CanTp will keep calling PduR_CanTpCopyRxData() with data length 0 and data buffer as NULL_PTR. If the the buffer size is still not big enough for the next block when the N_Br expires, CanTp will send a FC with status as WAIT and restart the N_Br timer. It will keep doing this until FC.WAIT has been sent WFTmax times. Once this limit has been reached, the reception will be aborted, PduR_CanTpRxIndication() with E_NOT_OK will be called. CanTp will not send any FC after this and hence on the sender side N_Bs timeout will occur and the sender will also abort the transmission.

If the buffer size is found to be big enough, after the receiving the FF or the last CF, CanTp will continue with the reception, and send FC.CTS to indicate that.

At any time during the reception of the block of CFs, if the PduR_CanTpCopyRxData() returns BUFREQ_E_NOT_OK, CanTp will abort the receive and notify PduR by calling PduR_CanTpRxIndication() with result E_NOT_OK.

About FC,

When a FF has been received, FC is sent only after receiving the result of PduR_CanTpStartOfReception(). The FC sent depends on the result of this call.

The Block Size and STmin cannot be changed for a segmented reception. It can only be changed for another N-SDU reception.

If N_Ar timeout occurs for the FC that has been sent by CanTp, the receive will be aborted and PduR_CanTpRxIndication() will be called with E_NOT_OK.

Sequence Diagram for a typical n-SDU Reception

N-SDU Transmission

During N-SDU transmission, CanTp will send out SF or FF and then CF if the connection has been accepted and it has received a FC. Before we check the behaviour let us check out the involved interfaces first.

CanTp_Transmit()

Upper layer, i.e PduR call this to initiate transmission of a N-SDU.

  • After this is called, CanTp will start the timer N_Cs before calling the PduR_CanTpCopyTxData().
  • If the N_Cs timeout occurs before PduR_CanTpCopyTxData() is called, CanTp will abort the transmission of the N-SDU.

PduR_CanTpCopyTxData()

  • PduR_CanTpTxCopyData() is called for each segment that is sent, SF/FF/CF.
  • If the upper layer cannot transmit the data then PduR_CanTpTxCopyData() returns E_NOT_OK. The transmission is aborted then and CanTP notifies the upper layer of the aborted transmission by calling PduR_CanTpTxConfirmation() with E_NOT_OK.
  • If the upper layer does not have the buffer allocated, call to PduR_CanTpTxCopyData() rerturns BUFREQ_E_BUSY. In this case CanTp will retry to copy the transmit data until the N_Cs timer has expired. If the data is not available within the N_Cs timeout, CanTp aborts the transmission and notifies the upper layer by calling PduR_CanTpTxConfirmation() with E_NOT_OK.
  • If CanTp does not receive transmit confirmation from CanIf within the N_As timeout window, it aborts the transmission and notifies the upper layer by calling PduR_CanTpTxConfirmation() with E_NOT_OK.
  • PduR_CanTpCopyTxData() contains a parameter for the recovery mechanism, but since ISO15765 does not support recovery mechanisms, this parameter is always set to NULL.
  • If FC.OVFL or any invalid FC Flow State is received the transmission will be aborted and the upper layer will be notified.
  • N_Bs timeout is started by CanTp after sending the FF or the last CF of the block. If the timeout occurs before the FC is received, CanTp aborts the transmission and notifies the upper layer.

PduR_CanTpTxConfirmation()

Sequence Diagram for a typical n-SDU Transmission

Concurrent Connections

  • CAN Transport Layer runs only in an event triggered mode.
  • CAN Transport Layer implementation supports half and full-duplex communication.
  • Transport Protocol facilities can be used by both diagnostic and COM I-PDUs and thus supports multiple simultaneous connections.
  • The number of connections is statically configured and has an impact on the complexity and resource consumption.
  • Each SDU is statically linked to one connection channel but a connection channel can be shared by multiple SDUs.
  • A connection channel is independent of other connection channels and has its own resources such as buffers, timers and state machines.
  • Each N-SDU is routed through the correct connection channel, and it cannot process multiple N-SDUs with the same SDU Id parallelly.
  • CanTP has no buffer. It operates directly on the buffers of other layers. When the buffer is being used, it is expected that the upper layer has locked the buffer. This is done to ensure the data consistency.
  • During transmit, the buffer is locked when CanTp_Transmit() return = E_OK and is unlocked when PduR_CanTpTxConfirmation() is called.
  • During receive, the buffer is locked when PduR_CanTpStartOfReception() return = E_OK and unlocked again when PduR_CanTpRxIndication().
  • CAN FD and CAN frames will be mapped to different PDUs by CanIf depending on the frame format (CAN FD or CAN 2.0). Therefore, it is possible to distinguish between CAN FD and classic CAN communication in CanTp.

Padding

  • In both the cases, where padding is used or not, CanTp will only transmit data bytes to the upper layer, not the padding bytes.
  • CANTP_PADDING_BYTE : This is the value that will be used for padding.
  • CanTpTxPaddingActivation, this is the configuration parameter for activating/deactivating padding on the transmit messages.
  • When CanTpTxPaddingActivation = CANTP_ON, any transmit message will have the padding bytes filled with CANTP_PADDING_BYTE.
  • Any FC received with size < 8 will result in CanTp aborting the transmit.
  • If the data length being transmitted does not match the permissible DLC values (0..8, 12, 16, 20, 24, 32, 48, or 64) CanTP will pad those bytes with CANTP_PADDING_BYTE.

CanTpRxPaddingActivation, this is the configuration parameter for checking the padding on the incoming messages.

  • If the CanTpRxPaddingActivation = CANTP_ON, then any incoming SDU with length less than 8 will be rejected. If it is the last CF of a block, then PduR_CanTpRxIndication()
    with the result E_NOT_OK will be called.
  • Any FC sent when the CanTpRxPaddingActivation = CANTP_ON, will have padding bytes set to the value specified by CANTP_PADDING_BYTE.

Handling Unexpected N-PDU

This handling is dependent on the type of channel.

Half-Duplex Channel

Full Duplex Channel

--

--