Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/openxc/isotp-c

An implementation of the ISO-TP (ISO15765-2) CAN protocol in C
https://github.com/openxc/isotp-c

Last synced: 3 months ago
JSON representation

An implementation of the ISO-TP (ISO15765-2) CAN protocol in C

Awesome Lists containing this project

README

        

ISO-TP (ISO 15765-2) Support Library in C
================================

This is a platform agnostic C library that implements the ISO 15765-2 (also
known 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 packets
>over a CAN-Bus. The protocol allows for the transport of messages that exceed
>the eight byte maximum payload of CAN frames. ISO-TP segments longer messages
>into multiple frames, adding metadata that allows the interpretation of
>individual frames and reassembly into a complete message packet by the
>recipient. 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 or
the underlying interface to CAN. It uses dependency injection to give you
complete control.

The current version supports *only single frame ISO-TP messages*. This is fine
for OBD-II diagnostic messages, for example, but this library needs some
additional work before it can support sending larger messages.

## Usage

First, create some shim functions to let this library use your lower level
system:

// 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.
bool send_can(const uint32_t arbitration_id, const uint8_t* data,
const uint8_t size) {
...
}

// optional, provide to receive debugging log messages
void debug(const char* format, ...) {
...
}

// not used in the current version
bool 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);

### API

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.
}
}
}
}

## Testing

The library includes a test suite that uses the `check` C unit test library.

$ make test

You can also see the test coverage if you have `lcov` installed and the
`BROWSER` environment variable set to your choice of web browsers:

$ BROWSER=google-chrome-stable make coverage

## Authors

* Chris Peplin [email protected]
* David Boll [email protected] (the inspiration for the library's API is from David)

## License

Copyright (c) 2013 Ford Motor Company

Licensed under the BSD license.