- Notifications
You must be signed in to change notification settings - Fork0
An implementation of the ISO-TP (ISO15765-2) CAN protocol in C
License
lmiori92/isotp-c
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is a platform agnostic C library that implements the ISO 15765-2 (alsoknown as ISO-TP) protocol, which runs over a CAN bus. Quoting Wikipedia:
ISO 15765-2, or ISO-TP, is an international standard for sending data packetsover a CAN-Bus. The protocol allows for the transport of messages that exceedthe eight byte maximum payload of CAN frames. ISO-TP segments longer messagesinto multiple frames, adding metadata that allows the interpretation ofindividual frames and reassembly into a complete message packet by therecipient. It can carry up to 4095 bytes of payload per message packet.
This library doesn't assume anything about the source of the ISO-TP messages orthe underlying interface to CAN. It uses dependency injection to give youcomplete control.
The current version supportsonly single frame ISO-TP messages. This is finefor OBD-II diagnostic messages, for example, but this library needs someadditional work before it can support sending larger messages.
First, create some shim functions to let this library use your lower levelsystem:
// required, this must send a single CAN message with the given arbitration// ID (i.e. the CAN message ID) and data. The size will never be more than 8// bytes.void send_can(const uint16_t arbitration_id, const uint8_t* data, const uint8_t size) { ...}// optional, provide to receive debugging log messagesvoid debug(const char* format, ...) { ...}// not used in the current versionvoid set_timer(uint16_t time_ms, void (*callback)) { ...}
With your shims in place, create an IsoTpShims object to pass them around:
IsoTpShims shims = isotp_init_shims(debug, send_can, set_timer);
With your shims in hand, send an ISO-TP message:
// Optional: This is your callback that will be called when the message is// completely sent. If it was single frame (the only type supported right// now), this will be called immediately.void message_sent(const IsoTpMessage* message, const bool success) { // You received the message! Do something with it.}IsoTpSendHandle handle = isotp_send(&shims, 0x100, NULL, 0, message_sent);if(handle.completed) { if(!handle.success) { // something happened and it already failed - possibly we aren't able to // send CAN messages return; } else { // If the message fit in a single frame, it's already been sent // and you're done }} else { while(true) { // Continue to read from CAN, passing off each message to the handle // this will return true when the message is completely sent (which // may take more than one call if it was multi frame and we're waiting // on flow control responses from the receiver) bool complete = isotp_continue_send(&shims, &handle, 0x100, data, size); if(complete && handle.completed) { if(handle.success) { // All frames of the message have now been sent, following // whatever flow control feedback it got from the receiver } else { // the message was unable to be sent and we bailed - fatal // error! } } }}
Finally, receive an ISO-TP message:
// Optional: This is your callback for when a complete ISO-TP message is// received at the arbitration ID you specify. The completed message is// also returned by isotp_continue_receive, which can sometimes be more// useful since you have more context.void message_received(const IsoTpMessage* message) {}IsoTpReceiveHandle handle = isotp_receive(&shims, 0x100, message_received);if(!handle.success) { // something happened and it already failed - possibly we aren't able to // send CAN messages} else { while(true) { // Continue to read from CAN, passing off each message to the handle IsoTpMessage message = isotp_continue_receive(&shims, &handle, 0x100, data, size); if(message.completed && handle.completed) { if(handle.success) { // A message has been received successfully } else { // Fatal error - we weren't able to receive a message and // gave up trying. A message using flow control may have // timed out. } } }}
The library includes a test suite that uses thecheck
C unit test library.
$ make test
You can also see the test coverage if you havelcov
installed and theBROWSER
environment variable set to your choice of web browsers:
$ BROWSER=google-chrome-stable make coverage
- Chris Peplincpeplin@ford.com
- David Bolldboll2@ford.com (the inspiration for the library's API is from David)
Copyright (c) 2013 Ford Motor Company
Licensed under the BSD license.