CanTp implements ISO 15765-2 segmented transfer over CAN. It connects downward to CanIf and upward to PduR. The configuration is consumed by CanTp.py; the example in this document is app/app/config/CanTp/CanTp.json and the generated code is CanTp_Cfg.c.
Each entry in channels creates one logical CanTp channel. A channel always owns exactly one RxPdu and one TxPdu - the generator derives their CanIf names from the channel name as ${name}_RX and ${name}_TX.
{
"class": "CanTp",
"channels": [
{ "name": "P2P" },
{ "name": "P2A", "ComType": "FUNCTIONAL" },
{ "name": "P2A_FW", "ComType": "FUNCTIONAL" }
],
"backup-channels": [
{ "name": "FW_CAN0_SECOC_MSG0" }
]
}
channels - physical and functional diagnostic channels. ComType is PHYSICAL (default) or FUNCTIONAL;backup-channels - channels used as a SecOC fallback path. A backup channel is instantiated but is not routed until SecOC switches to it.The corresponding CanIf PDUs must exist in CanIf.json with matching names and the up field set to CanTp:
"RxPdus": [
{ "name": "P2P_RX", "id": "0x731", "hoh": 0, "up": "CanTp" },
{ "name": "P2A_RX", "id": "0x7DF", "hoh": 0, "up": "CanTp" }
],
"TxPdus": [
{ "name": "P2P_TX", "id": "0x732", "hoh": 0, "up": "CanTp" },
{ "name": "P2A_TX", "id": "0x732", "hoh": 0, "up": "CanTp" }
]
Every field except name is optional and falls back to a compiled default:
| Field | Default | Description |
|---|---|---|
name |
- | Channel name; derives the CanIf ${name}_RX / ${name}_TX PDU names and the PduR routing IDs |
ComType |
PHYSICAL |
PHYSICAL for 1-to-1 physical addressing or FUNCTIONAL for functional requests (CAN ID 0x7DF) |
N_As |
0 | Time for transmitting a CAN frame (any N-PDU) on the sender side |
N_Bs |
0 | Time until the next flow control N-PDU is received (ISO 15765-2) |
N_Cr |
0 | Time until the next consecutive frame N-PDU is received (ISO 15765-2) |
STmin |
0 | Minimum separation time between two consecutive frames |
BS |
0 | Block size used in outgoing flow control frames |
WftMax |
8 | Number of consecutive wait (FC-WAIT) flow control frames allowed; must not be 0xFF |
LL_DL |
CANTP_LL_DL (8) |
Lower-layer data length: 8 for classic CAN, 64 for CAN FD |
padding |
0x55 |
Padding byte used when padding is enabled |
N_TA |
0 | Network target address, required only for extended addressing |
A top-level STMinAdjust lets the generated code add a constant correction to the negotiated STmin. In the host simulator, the environment variable LL_DL overrides LL_DL of every channel at process start, which makes it possible to switch the same build between classic CAN and CAN FD without regenerating.
The generated channel struct is:
typedef struct {
CanTp_AddressingFormatType AddressingFormat;
PduIdType CanIfTxPduId;
PduIdType PduR_RxPduId;
PduIdType PduR_TxPduId;
uint16_t N_As;
uint16_t N_Bs;
uint16_t N_Cr;
uint8_t STmin;
uint8_t BS;
uint8_t N_TA; /* only used with CANTP_EXTENDED addressing */
uint8_t CanTpRxWftMax; /* cannot be 0xFF */
uint8_t LL_DL; /* 8 for CAN, 64 for CAN FD */
uint8_t padding;
uint8_t *data; /* transmit buffer for segmented frames */
} CanTp_ChannelConfigType;
CanTp_Cfg.c directly.Configuration is processed by: CanTp.py, which emits GEN/CanTp_Cfg.c and GEN/CanTp_Cfg.h next to the JSON file.