Code Monkey home page Code Monkey logo

iso15765-canbus's Introduction

ISO15765-2 CANBus TP

C/C++ CI Codacy Badge

Compiler flags: -O3 -Wfatal-errors -Wall -std=c11

An implementation of the ISO15765-2 (ISO-TP) protocol in a platform agnostic C library. The library interacts in a transparent way with the lower ISO layers which means that the user must define the connection for the reception and the transmission of the CANBus frames. In this way you have a complete control and reusability of this library in different platforms. This library can support UDS, OBDII and any other application layer protocol that requires ISO15765-2 TP.

This ISO defines common requirements for vehicle diagnostic systems implemented on a Controller Area Network (CAN) communication link, as specified in ISO 11898. Although primarily intended for diagnostic systems, it also meets requirements from other CAN-based systems needing a network layer protocol.

How to use

  • Include the header file iso15765_2.h
  • Define an iso15765_t handler, create and attach the required shim/callbacks (send_frame on_error get_ms) of the handler
/* Required shim/callback functions */
static uint8_t send_frame(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt);
static void usdata_indication(n_indn_t* info);
static void on_error(n_rslt err_type);
static uint32_t getms();

/* ISOTP handler */
static iso15765_t handler =
{
	.addr_md = N_ADM_FIXED,		     // Selected address mode of the TP
	.fr_id_type = CBUS_ID_T_EXTENDED,    // CANBus frame type
	.config.stmin = 0x05,		     // Default min. frame transmission separation
	.config.bs = 0x0F,		     // Maximun size of the block sequence
	.config.n_bs = 800,		     // Time until reception of the next FlowControl N_PDU
 	.config.n_cr = 250,		     // Time until reception of the next ConsecutiveFrame N_PDU
	.clbs.get_ms = getms,		     // Time-source for the library in ms(required)
	.clbs.on_error = on_error,	     // Callback which will be executed in any occured error.
	.clbs.send_frame = send_frame,	     // This callback will be fired when a transmission of a canbus frame is ready.
	.clbs.indn = usdata_indication	     // Indication Callback: Will be fired when a reception
					     // is available or an error occured during the reception.
};

static uint8_t send_frame(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt)
{
    // Here transmit the frame through CANBus
    return 0;
}

static void usdata_indication(n_indn_t* info)
{
    // Use the incoming message. This function should be fired by the library when a new complete message arrives.
}

static void on_error(n_rslt err_type)
{
    // Check the errors etc..
}

static uint32_t getms()
{
    // return time in ms; 
    // ex. return GetTickCount();
}
  • In your main, first initialize the iso15765_t handler iso15765_init(&handler);

  • To send a message, create a n_req_t and use the function iso15765_send. For example:

n_req_t frame =
{
    .n_ai.n_pr = 0x06,		// Network Address Priority
    .n_ai.n_sa = 0x01,		// Network Source Address
    .n_ai.n_ta = 0x02,		// Network Target Address
    .n_ai.n_ae = 0x00,		// Network Address Extension
    .n_ai.n_tt = N_TA_T_PHY,	// Network Target Address type
    .fr_fmt = CBUS_FR_FRM_STD,	// CANFD or CANSTD
    .msg = {1,2,3,4,5,6,7,8,	// Message
    	    9,10,11,12,13,14,
	    15,16,17,18,19,20},
    .msg_sz = 20,		// Message size
};
...
iso15765_send(&handler, &frame);
  • To push an incoming frame to the library use the function iso15765_enqueue(&handler, &frame);. It is suggested to put this function inside the frame reception callback of your interface
  • Use the iso15765_process(&handler); to allow the library to process the in/out streams of data. Normally you could put this function in a thread to run continuously.
  • As described before, any new/completed incoming message should be handled in the callback static void usdata_indication(indn_t* info)

Below is a complete loopback example. The service send a message to itself by enqueing the transmitted frame in the inbound stream.

#include <stdio.h>
#include <stdlib.h>
#include "iso15765_2.h"
#include <windows.h>
#include <sysinfoapi.h>

/******************************************************************************
* Declaration | Static Functions
******************************************************************************/

static uint8_t send_frame(canbus_md md, uint32_t id, uint8_t dlc, uint8_t* dt);
static void on_error(n_rslt err_type);
static uint32_t getms();

/******************************************************************************
* Enumerations, structures & Variables
******************************************************************************/

static iso15765_t handler =
{
        .addr_md = N_ADM_FIXED,
        .fr_id_type = CBUS_ID_T_EXTENDED,
        .clbs.send_frame = send_frame1,
        .clbs.on_error = on_error,
        .clbs.get_ms = getms,
        .clbs.indn = indn1,
        .config.stmin = 0x3,
        .config.bs = 0x0f,
        .config.n_bs = 100,
        .config.n_cr = 3
};

n_req_t frame =
{
        .n_ai.n_pr = 0x07,
        .n_ai.n_sa = 0x01,
        .n_ai.n_ta = 0x02,
        .n_ai.n_ae = 0x00,
        .n_ai.n_tt = N_TA_T_PHY,
        .fr_fmt = CBUS_FR_FRM_FD,
        .msg = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23},
        .msg_sz = 23,
};

/******************************************************************************
* Definition  | Static Functions
******************************************************************************/

static uint32_t getms()
{
        return GetTickCount();
}

static uint8_t send_frame(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt)
{
        printf("%d  #1# - id:%x    dlc:%02x    ",GetTickCount(), id, dlc);
        for (int i = 0; i < 8; i++) printf("%02x ", dt[i]);
        printf("\n");
        canbus_frame_t frame = { .id = id, .dlc = dlc, .id_type = id_type, .fr_format= fr_fmt };
        memmove(frame.dt, dt, dlc);
        iso15765_enqueue(&handler, &frame);
        return 0;
}

static void on_error(n_rslt err_type)
{
        printf("ERROR OCCURED!:%d", err_type);
}

/******************************************************************************
* Definition  | Public Functions
******************************************************************************/

int main()
{
        iso15765_init(&handler);

        iso15765_send(&handler, &frame);
        while(1)
        {
                iso15765_process(&handler);
                Sleep(5);
        }
        return 0;
}

Please check the folder exm for more examples

Development

This library is experimental and is still under development. The purpose is to create a complete ISO15765 library with all the described features. Feel free to suggest anything. If you use this library please ref.

Contributing

We would love you to contribute to iso15765-canbus, pull requests are welcome!

Support

Support this project though https://paypal.me/iikem or https://github.com/sponsors/devcoons

License

This project is released under the MIT License

iso15765-canbus's People

Contributors

devcoons avatar turlupin3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iso15765-canbus's Issues

Multi-node communication

How would simultaneous multi-node communication be handled?
Should I just create multiple handlers and then call the correct handler on the correct incoming frames based on arbitration ID?

Flow Control Management?

What is the intended solution for sending flow control frames on a received first frame? I haven't found any option to configure on which IDs it should reply.
Or is it intended to implement it manually in usdata_indication?

N_UNE_PDU return value in process_in_cf()

Hi
Thank you for the great work.

In function lib_iso15765.c::process_in_cf there is a return of N_UNE_PDU when last continuos frame is received and correctly signalled to the upper levels. Is it correct?

	if (ih->in.msg_pos >= ih->in.msg_sz)
	{
		signaling(N_INDN, &ih->in, (void*)ih->clbs.indn, ih->in.msg_sz, N_OK);
		memset(&ih->in, 0, sizeof(n_iostream_t));
		ih->in.last_upd.n_cr = 0;
		//	ih->in.sts = N_S_IDLE;
		return N_UNE_PDU;
	}

Thank you very much

Bugs?

The following code may be wrong.

  1. lib_iso15765.c // sequence issue
    /* Increase the CF counter and check if the reception sequence is ok */
    ih->in.cf_cnt = ih->in.cf_cnt + 1 > 0x0F ? 1 : ih->in.cf_cnt + 1;
    =>
    ih->in.cf_cnt = ih->in.cf_cnt + 1 > 0x0F ? 0 : ih->in.cf_cnt + 1;

  2. lib_iso15765.c // reach max counter issue
    /* if we reach the max CF counter, then we send a FC frame */
    ...
    if (ih->in.cf_cnt % ih->config.bs)
    =>
    if ((ih->in.cf_cnt % ih->config.bs) == 0)

[Question] How interact with hardware

Hello,

I implement this library in my small project. I have custom PCB with rp pico and CAN transceiver.

I need create frames and send it as bytes via UART to onboard CAN transceiver.
I added method for sending bytes to UART in send_frame callback function.
But my question is how I can receive some data from UART? I need read incoming bytes from UART
and assemble canbus_frame_t from it. I thought that usda_indication() is for that, but I dont know
how invoke it from my UART reader.

Is that possible?

Thank you!

Error in operator precedence in n_pdu_unpack()

First and foremost, I would like to thank you for the excellent work you have done !
This is my first ever issue on an open source project so feel free to let me know if I've done things incorrectly.

I found a small bug concerning operator precedence in the function n_pdu_unpack().
When doing (uint8_t)(id & 0x0000FF00) >> 8 and similar operations, the type cast has precedence over the bitshift operation. (See cpprefence and MS C)
This results in the value being casted to an uint8_t with a value of zero before the bitshift which is incorrect.

Just adding an extra set of parentheses around the bit shift operation does the job:

        case N_ADM_MIXED29:
                n_pdu->n_ai.n_ae = dt[0];
-               n_pdu->n_ai.n_pr = (uint8_t)(id & 0x1C000000) >> 26;
+               n_pdu->n_ai.n_pr = (uint8_t)((id & 0x1C000000) >> 26);
                n_pdu->n_ai.n_tt = (uint8_t)(((id & 0x00FF0000) >> 16) == 0xCE ? N_TA_T_PHY : N_TA_T_FUNC);
-               n_pdu->n_ai.n_ta = (uint8_t)(id & 0x0000FF00) >> 8;
-               n_pdu->n_ai.n_sa = (uint8_t)(id & 0x000000FF) >> 0;
+               n_pdu->n_ai.n_ta = (uint8_t)((id & 0x0000FF00) >> 8);
+               n_pdu->n_ai.n_sa = (uint8_t)((id & 0x000000FF) >> 0);
                break;

I tested the fix against pylessard's can-isotp. Before the fix, the two libraries had issues talking to each other and now it works just fine.
I am fairly confident about applying the fix to N_ADM_MIXED29 and N_ADM_FIXED addressing modes but I am not so sure about N_ADM_NORMAL and N_ADM_EXTENDED since the correspondence between N_AI and the CAN ID is left open in those modes.

Do you want me to fork and open a short PR ? If so, do I also add an extra set of parentheses in the N_ADM_NORMAL and N_ADM_EXTENDED cases ?

Thank you for you time and, again, thank you for your work !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.