Eight bytes per frame, kilobytes per message
Diagnostics, calibration and flashing exchange messages of hundreds or thousands of bytes over a bus whose classical frames carry eight. The receiver decides how fast the sender may go, frames can be lost or arrive out of order, and the code runs on an ECU with a few kilobytes of RAM that will be reviewed against MISRA C.
Messages larger than a frame
Segmentation into First and Consecutive Frames, reassembly with sequence-number checks, the receiver's block size and separation time obeyed, N_Bs and N_Cr timeouts detected.
Tight embedded budgets
104 bytes per link plus the two message buffers you size at build time, at most 120 bytes of stack on a Cortex-M4; no allocation, no globals, no clock reads.
Code you can certify
Zero MISRA C:2012 violations, a documented deviation register, 100 % line and branch coverage and static analysis in CI.
A small library with a clear job
Two layers and 18 functions: a pure frame codec and a link that does the transport protocol. Time is an argument, the CAN driver is one callback.
Codec and link
Decode and encode SF, FF, CF and FC frames; segment, reassemble and pace whole messages.
Any CAN driver
One write callback and one call per received frame: bxCAN, FDCAN, MCP2515, SocketCAN or Zephyr CAN.
Working examples
A UDS-style ECU on a simulated bus (run in CI), a SocketCAN request tool and a Zephyr application.
An independent twin
A Python implementation of the codec cross-checks the C code; the C link is driven against it end to end.
Complete documentation
Guides, protocol chapter, API reference with every return value, and a printable PDF manual.
Quality gates in CI
100 % line and branch coverage, MISRA C:2012 gate, Cppcheck, CodeQL and clang-format on every pull request.
Quick start
A minimal ECU in one file¶
The library touches the hardware through two things you provide: a function that
writes one CAN frame, and the received frames you pass in together with the current
time in microseconds. Everything else — segmentation, flow control, timeouts — happens
inside isotp_link_receive() and isotp_link_poll(). This program echoes every
request it receives on CAN ID 0x7E0 back on 0x7E8, whatever its length:
#include "isotp.h"
static struct isotp_link link;
static int can_write(void* context, uint32_t can_id, const uint8_t* data, size_t length)
{
(void) context;
return board_can_write(can_id, data, length);
}
static void on_message(const uint8_t* data, uint32_t length, void* context)
{
(void) context;
(void) isotp_link_send(&link, data, length, board_micros()); /* echo */
}
int main(void)
{
struct isotp_link_config config;
uint8_t frame[8];
uint32_t can_id;
isotp_link_config_default(&config);
config.tx_id = 0x7E8U;
config.write = can_write;
config.on_message = on_message;
(void) isotp_link_init(&link, &config);
for (;;)
{
size_t length = board_can_read(&can_id, frame); /* 0: no frame waiting */
if ((length > 0U) && (can_id == 0x7E0U))
{
isotp_link_receive(&link, frame, length, board_micros());
}
isotp_link_poll(&link, board_micros());
}
}
board_can_write(), board_can_read() and board_micros() stand for your CAN driver
and a free-running microsecond timer; the examples implement them for a
simulated board, Linux SocketCAN and Zephyr.
Find your way¶
| If you want to… | Read |
|---|---|
| Understand what the library does and does not do | Introduction |
| Build it, run the tests, add it to your project | Getting Started |
| Understand the layers, the state machines and the timers | How It Works |
| Write an ECU or a tester with it | Using the Library |
| Add addressing modes, CAN FD or contribute | Extending the Library |
| Look up the bytes on the wire | Protocol |
| Look up a function | API Reference |
| Read everything offline or print it | PDF user manual |
SystemFromScratch®
Part of an open-source embedded portfolio
ISOTP-C is developed by Anton Vynohradov under SystemFromScratch® — embedded software and hardware built from the first schematic to certification.
SystemFromScratch® is a registered trademark. ISO 15765-2 is a standard of the International Organization for Standardization (ISO). ISOTP-C is an independent implementation and is not affiliated with or endorsed by ISO.