2013-12-27 11:02:14 -08:00
|
|
|
ISO-TP (ISO 15765-2) Support Library in C
|
|
|
|
================================
|
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
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:
|
2013-12-27 11:02:14 -08:00
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
>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.
|
2013-12-31 13:29:07 -08:00
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
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
|
2013-12-31 13:29:07 -08:00
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
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.
|
2013-12-31 13:29:07 -08:00
|
|
|
void send_can(const uint16_t arbitration_id, const uint8_t* data,
|
|
|
|
const uint8_t size) {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
// optional, provide to receive debugging log messages
|
|
|
|
void debug(const char* format, ...) {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// not used in the current version
|
2013-12-31 13:29:07 -08:00
|
|
|
void set_timer(uint16_t time_ms, void (*callback)) {
|
|
|
|
...
|
2013-12-27 11:02:14 -08:00
|
|
|
}
|
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
With your shims in place, create an IsoTpShim object to pass them around:
|
|
|
|
|
|
|
|
IsoTpShim shims = isotp_init_shims(debug, send_can, set_timer);
|
|
|
|
|
|
|
|
### API
|
|
|
|
|
|
|
|
With your shims in hand, send an ISO-TP message:
|
2013-12-31 13:29:07 -08:00
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
// Optiona: 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.
|
2013-12-31 13:29:07 -08:00
|
|
|
void message_sent(const IsoTpMessage* message, const bool success) {
|
|
|
|
// You received the message! Do something with it.
|
|
|
|
}
|
|
|
|
|
2014-01-03 10:40:02 -08:00
|
|
|
IsoTpSendHandle handle = isotp_send(&shims, 0x100, NULL, 0, message_sent);
|
2013-12-31 13:29:07 -08:00
|
|
|
|
|
|
|
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
|
2014-01-03 10:40:02 -08:00
|
|
|
// 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);
|
2013-12-31 13:29:07 -08:00
|
|
|
|
|
|
|
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:
|
|
|
|
|
2014-01-03 10:18:06 -08:00
|
|
|
// Optional: This is your callback for when a complete ISO-TP message is
|
|
|
|
// received at the arbitration ID you specify. The completed message is
|
2014-01-03 10:40:02 -08:00
|
|
|
// also returned by isotp_continue_receive, which can sometimes be more
|
2014-01-03 10:18:06 -08:00
|
|
|
// useful since you have more context.
|
2013-12-31 13:29:07 -08:00
|
|
|
void message_received(const IsoTpMessage* message) {
|
|
|
|
}
|
|
|
|
|
2014-01-03 10:40:02 -08:00
|
|
|
IsoTpReceiveHandle handle = isotp_receive(&shims, 0x100, message_received);
|
2013-12-31 13:29:07 -08:00
|
|
|
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
|
2014-01-03 10:40:02 -08:00
|
|
|
IsoTpMessage message = isotp_continue_receive(&shims, &handle, 0x100, data, size);
|
2013-12-31 13:29:07 -08:00
|
|
|
|
2014-01-01 13:08:10 -08:00
|
|
|
if(message.completed && handle.completed) {
|
2013-12-31 13:29:07 -08:00
|
|
|
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.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-12-27 08:22:56 -08:00
|
|
|
|
|
|
|
## Testing
|
|
|
|
|
|
|
|
The library includes a test suite that uses the `check` C unit test library.
|
|
|
|
|
|
|
|
$ make test
|
|
|
|
|
2014-01-03 09:45:46 -08:00
|
|
|
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
|
|
|
|
|
2013-12-27 08:22:56 -08:00
|
|
|
## Authors
|
|
|
|
|
|
|
|
Chris Peplin cpeplin@ford.com
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
Copyright (c) 2013 Ford Motor Company
|
|
|
|
|
|
|
|
Licensed under the BSD license.
|