소스 검색

feat:添加解析库源码
module:15765
ticket_ID:15765

yangyongkai 3 년 전
부모
커밋
4ae59ede72

+ 4 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/.github/FUNDING.yml

@@ -0,0 +1,4 @@
+# These are supported funding model platforms
+
+github: [devcoons]
+

+ 34 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/.github/workflows/build.yml

@@ -0,0 +1,34 @@
+name: C/C++ CI
+
+on:
+  push:
+    branches:    
+      # Push events on master branch
+      - master
+  pull_request:
+    branches:    
+      # Push events on master branch
+      - master
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: make
+      run: make
+    - name: Get current date
+      id: date
+      run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
+    - name: Create Release
+      id: create_release
+      uses: actions/create-release@v1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        tag_name: ${{steps.date.outputs.date}}
+        release_name: ${{steps.date.outputs.date}} 
+        draft: false
+        prerelease: false
+    - name: make clean
+      run: make clean

+ 21 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Ioannis D. (devcoons)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 95 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/Makefile

@@ -0,0 +1,95 @@
+$(info  Starting building process)
+
+# include configurations
+
+include Makefile.conf
+
+$(info  - Makefile.conf loaded)
+
+# find project files
+
+H_FILES   :=    $(shell find -L ./$(INC_DIRECTORY) -name '*.h' -exec dirname {} \; | sed 's/ /\\ /g' | uniq)
+
+C_FILES   :=    $(shell find ./$(SRC_DIRECTORY) -name '*.c' -type f | sed 's/ /\\ /g' | uniq)
+
+CXX_FILES :=    $(shell find ./$(SRC_DIRECTORY) -name '*.cpp' -type f | sed 's/ /\\ /g' | uniq)
+
+O_FILES   :=    $(C_FILES:.c=.o)
+
+O_FILES   +=    $(CXX_FILES:.cpp=.o)
+
+H_FILES   :=    $(notdir  $(H_FILES))
+
+C_FILES   :=    $(notdir  $(C_FILES))
+
+CXX_FILES :=    $(notdir  $(CXX_FILES))
+
+INCLUDES  :=    $(H_FILES:%=-I%)
+
+$(info  - Project Files Loaded)
+
+
+ifeq ($(DEBUG),yes)
+
+   $(info  - Debug flag added [makefile.conf DEBUG = yes])
+
+   CFLAGS := -g $(CFLAGS)
+
+endif
+
+
+ifeq ($(IS_LIBRARY),yes)
+
+   $(info  - Set Parameters for Shared Library build process)
+
+   ALL_PARAMETERS = lib$(PROJECT_NAME).so.$(PROJECT_VERSION) clean
+
+   ALL_TYPE = lib$(PROJECT_NAME).so.$(PROJECT_VERSION): $(O_FILES)
+   
+   LIBFLAGS = -shared -Wl,-soname,lib$(PROJECT_NAME).so
+   
+   CFLAGS :=  -fPIC $(CFLAGS)
+   
+   CXXFLAGS := -fPIC $(CXXFLAGS)
+else
+
+   $(info  - Set Parameters for Application build process)
+
+   ALL_PARAMETERS = $(PROJECT_NAME) clean
+
+   ALL_TYPE = $(PROJECT_NAME): $(O_FILES)
+   
+   LIBFLAGS =
+
+endif
+
+# Build Process
+
+all: $(ALL_PARAMETERS)
+
+$(ALL_TYPE)
+	@echo -  [OUTPUT][CXX] $@ @[$(BIN_DIRECTORY)]
+	@$(CXX) $(CFLAGS) $(INCLUDES) $(LDFLAGS) $(LIBFLAGS) -o $(BIN_DIRECTORY)/$@ $^ $(LDLIBS)
+
+%.o: %.c
+	@echo -  [CC] $@
+	@$(CC) $(CFLAGS) -c $(INCLUDES) -o $@ $< $(LFLAGS)
+
+%.o: %.cpp
+	@echo -  [CXX] $@
+	@$(CXX) $(CXXFLAGS) -c $(INCLUDES) -o $@ $< $(LFLAGS)
+	
+# Clear Objects
+	
+clean:
+	$(info  - Remove all .o [object] files)
+	@find . -name \*.o -type f -delete
+	
+	
+# Clear Objects & Executables 
+	
+cleanall:	
+	$(info  - Remove all .o [object] files)
+	@find . -name \*.o -type f -delete
+	$(info  - Remove all files in $(BIN_DIRECTORY))
+	@find $(BIN_DIRECTORY) -name \*.* -type f -delete

+ 52 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/Makefile.conf

@@ -0,0 +1,52 @@
+# Project Configurations
+
+   # Project Name 
+      PROJECT_NAME               =           iso15765
+
+   # Project Version
+      PROJECT_VERSION            =           0.1
+
+   # Program or Shared Library
+      IS_LIBRARY                 =           yes
+
+   # Source Files Directory
+      SRC_DIRECTORY              =           src lib
+
+   # Header Files Directory
+      INC_DIRECTORY              =           src lib
+
+   # Library Header Files Directory  
+      LIB_DIRECTORY              =           lib
+
+   # Build Output Directory	  
+      BIN_DIRECTORY              =           bin
+
+   # Installation Directory Exec
+     INS_DIRECTORY               =           /usr/bin/
+	 
+   # Installation Directory Headers
+     INS_HEARERS_DIRECTORY       =           /usr/include/
+	 
+   # Installation Directory SO		
+	 INS_SO_DIRECTORY            =           /usr/lib/
+
+   # C Flags
+      CFLAGS                     =           -O3 -D_GNU_SOURCE -Wfatal-errors -Wall -std=c11
+	  
+   # C++ Flags
+      CXXFLAGS                   =           $(CFLAGS)
+	  
+   # Linker Flags
+      LDFLAGS                    =           $(shell dpkg-buildflags --get LDFLAGS)
+	  
+   # Linker Libraries
+      LDLIBS                     =           -fno-inline
+   
+   # Debug Yes / No
+      DEBUG                      =           no
+
+   # C Compiler
+      CC                         =           gcc
+   
+   # C++ Compiler
+      CXX                        =           g++

+ 190 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/README.md

@@ -0,0 +1,190 @@
+# ISO15765-2 CANBus TP 
+![C/C++ CI](https://github.com/devcoons/iso15765-canbus/workflows/C/C++%20CI/badge.svg)  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/5a80fc004df744e888729e512eec1fda)](https://www.codacy.com/manual/devcoons/iso15765-canbus?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=devcoons/iso15765-canbus&amp;utm_campaign=Badge_Grade)
+
+*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
+```C
+/* 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:
+
+```C
+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.
+
+```C
+#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

+ 0 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/bin/.gitkeep


+ 0 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/doc/.gitkeep


BIN
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/doc/ISO-15765-2-2016.pdf


+ 235 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/exm/ISO15765Development.c

@@ -0,0 +1,235 @@
+//#define ISO16765Example
+#ifdef ISO16765Example
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "lib_iso15765.h"
+#include <windows.h>
+#include <sysinfoapi.h>
+#include <conio.h>
+
+/******************************************************************************
+* Declaration | Static Functions
+******************************************************************************/
+
+static uint8_t send_frame1(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt);
+static uint8_t send_frame2(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt);
+static void indn1(n_indn_t* info);
+static void indn2(n_indn_t* info);
+static void on_error(n_rslt err_type);
+static uint32_t getms();
+
+/******************************************************************************
+* Enumerations, structures & Variables
+******************************************************************************/
+
+static iso15765_t handler1 =
+{
+        .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
+};
+
+static iso15765_t handler2 =
+{
+        .addr_md = N_ADM_FIXED,
+        .fr_id_type = CBUS_ID_T_EXTENDED,
+        .clbs.send_frame = send_frame2,
+        .clbs.on_error = on_error,
+        .clbs.indn = indn2,
+        .clbs.get_ms = getms,
+        .config.stmin = 0x3,
+        .config.bs = 0x0f,
+        .config.n_bs = 100,
+        .config.n_cr = 3
+};
+
+n_req_t frame1 =
+{
+        .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_STD,
+        .msg = {0},
+        .msg_sz = 0,
+};
+
+n_req_t frame2 =
+{
+        .n_ai.n_pr = 0x07,
+        .n_ai.n_sa = 0x02,
+        .n_ai.n_ta = 0x01,
+        .n_ai.n_ae = 0x00,
+        .n_ai.n_tt = N_TA_T_PHY,
+        .fr_fmt = CBUS_FR_FRM_STD,
+        .msg = {0},
+        .msg_sz = 0,
+};
+
+/******************************************************************************
+* Definition  | Static Functions
+******************************************************************************/
+uint16_t f_sz1 = 1;
+uint16_t f_sz2 = 1;
+
+static void rand_string(char* str, size_t size)
+{
+        const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK";
+
+        for (size_t n = 0; n < size; n++) 
+        {
+                int key = rand() % ((int)sizeof(charset) - 1);
+                str[n] = charset[key];
+        }
+
+}
+
+
+static uint32_t getms()
+{
+          return GetTickCount();;
+}
+
+static void print_frame(uint8_t instance,uint8_t tp_mode, cbus_id_type mode, uint32_t id, uint8_t ctp_ft, uint8_t dlc, uint8_t* dt)
+{
+        printf(" (%d) - %d | TpMode: [%02x] | FrameType: [%2d]   IdType: [%d]   Id: [%8x]   DLC: [%02d]\t\t", instance, GetTickCount(), tp_mode, mode, ctp_ft, id, dlc);
+
+        for (int s = 0; s < (int)dlc; s += 8)
+        {
+                int elements = (int)dlc - s > 8 ? 8 : (int)dlc - s;
+
+                for (int i = s; i < (s+8); i++)
+		{
+                        printf((i< (s+elements))? "%02x " : "   ", dt[i]);
+		}
+                printf("\t");
+                if ((s+elements) == (int)dlc)
+		{
+                        printf("\n");
+		}
+                else
+		{
+                        printf("\n     |\t\t\t\t\t\t\t\t\t\t\t\t\t");
+		}
+        }
+
+}
+
+static uint8_t send_frame1(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt)
+{
+        print_frame(1,handler2.addr_md, id_type,  id, fr_fmt,  dlc,  dt);
+
+        canbus_frame_t frame = { .id = id, .dlc = dlc, .id_type = id_type, .fr_format= fr_fmt };
+        memmove(frame.dt, dt, dlc);
+        iso15765_enqueue(&handler2, &frame);
+        return 0;
+}
+
+
+static uint8_t send_frame2(cbus_id_type id_type, uint32_t id, cbus_fr_format fr_fmt, uint8_t dlc, uint8_t* dt)
+{     
+        print_frame(2, handler1.addr_md, id_type, id, fr_fmt, dlc, dt);
+        
+        canbus_frame_t frame = { .id = id, .dlc = dlc, .id_type = id_type,  .fr_format = fr_fmt };
+        memmove(frame.dt, dt, dlc);
+        iso15765_enqueue(&handler1, &frame);
+        return 0;
+}
+
+static void on_error(n_rslt err_type)
+{
+        printf("ERROR OCCURED!:%04x", err_type);
+}
+
+static void indn1(n_indn_t* info)
+{
+        uint8_t v = 'X';
+        uint8_t s = 'X';
+
+        if (info->msg_sz == frame2.msg_sz)
+	{
+                s = 'V';
+	}
+	
+        if (memcmp(info->msg, frame2.msg, info->msg_sz) == 0)
+	{
+                v = 'V';
+	}
+	
+        printf("- Reception of H1. Msg_sz:[%d] | SZ_CH[%c] MSG_CH[%c]\n",info->msg_sz,s,v);
+   
+        if ((v != 'V') || (s != 'V'))
+        {
+                printf("--------- ERROR -----------\n");
+                Sleep(1000);
+        }
+        printf("- END OF TRANSMISSION/RECEPTION -\n\n\n");
+
+        frame1.msg_sz = f_sz1;
+        rand_string(frame1.msg, frame1.msg_sz);
+        f_sz1 = f_sz1 == 512 ? 0 : f_sz1 + 1;
+        iso15765_send(&handler1, &frame1);
+}
+static void indn2(n_indn_t* info)
+{
+        uint8_t v = 'X';
+        uint8_t s = 'X';
+
+        if (info->msg_sz == frame1.msg_sz)
+	{
+                s = 'V';
+	}
+	
+        if (memcmp(info->msg, frame1.msg, info->msg_sz) == 0)
+	{
+                v = 'V';
+	}
+	
+        printf("- Reception of H2. Msg_sz:[%d] | SZ_CH[%c] MSG_CH[%c]\n", info->msg_sz, s, v);
+       
+        if ((v != 'V') || (s != 'V'))
+        {
+                printf("--------- ERROR -----------\n");
+                Sleep(1000);
+        }
+        printf("- END OF TRANSMISSION/RECEPTION -\n\n\n");
+	
+        frame2.msg_sz = f_sz2;
+        rand_string(frame2.msg, frame2.msg_sz);
+        f_sz2 = f_sz2 == 512 ? 0 : f_sz2 + 1;
+        iso15765_send(&handler2, &frame2);
+}
+/******************************************************************************
+* Definition  | Public Functions
+******************************************************************************/
+
+int main()
+{
+        
+        iso15765_init(&handler1);
+        iso15765_init(&handler2);
+
+        frame1.msg_sz = f_sz1;
+        rand_string(frame1.msg, frame1.msg_sz);
+	
+        f_sz1++;
+
+        iso15765_send(&handler1, &frame1);
+        while (1)
+        {
+                iso15765_process(&handler1);
+                iso15765_process(&handler2);
+              
+        }
+        return 0;
+}
+#endif

+ 140 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/lib/lib_iqueue.c

@@ -0,0 +1,140 @@
+/*!
+	@file   lib_iqueue.c
+	@brief  <brief description here>
+	@t.odo	-
+	---------------------------------------------------------------------------
+
+	MIT License
+	Copyright (c) 2018 Io. D (Devcoons)
+
+	Permission is hereby granted, free of charge, to any person obtaining a copy
+	of this software and associated documentation files (the "Software"), to deal
+	in the Software without restriction, including without limitation the rights
+	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+	copies of the Software, and to permit persons to whom the Software is
+	furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be included in all
+	copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+	SOFTWARE.
+*/
+/******************************************************************************
+* Preprocessor Definitions & Macros
+******************************************************************************/
+
+/******************************************************************************
+* Includes
+******************************************************************************/
+
+#include "lib_iqueue.h"
+
+/******************************************************************************
+* Enumerations, structures & Variables
+******************************************************************************/
+
+/******************************************************************************
+* Declaration | Static Functions
+******************************************************************************/
+
+/******************************************************************************
+* Definition  | Static Functions
+******************************************************************************/
+
+/******************************************************************************
+* Definition  | Public Functions
+******************************************************************************/
+
+i_status iqueue_init(iqueue_t* _queue, int _max_elements, size_t _element_size, void* _storage)
+{
+	if (_queue != NULL)
+	{	
+		memset(_storage, 0x00, _element_size * _max_elements);
+		_queue->element_size = _element_size;
+		_queue->max_elements = _max_elements;
+		_queue->first = 0;
+		_queue->next =  _storage;
+		_queue->storage = _storage;
+		return I_OK;
+	}
+	return I_ERROR;
+}
+
+volatile void* iqueue_get_next_enqueue(iqueue_t* _queue)
+{
+	return _queue->next;
+}
+
+i_status iqueue_advance_next(iqueue_t* _queue)
+{
+	if (_queue->first != _queue->next)
+	{	
+		_queue->first = _queue->first == 0 ? _queue->next : _queue->first;
+		_queue->next = _queue->next + _queue->element_size == (uintptr_t)_queue->storage + (_queue->element_size * _queue->max_elements)
+			? (uintptr_t)_queue->storage : _queue->next + _queue->element_size;
+		return I_OK;
+	}
+	return I_FULL;
+}
+
+i_status iqueue_enqueue(iqueue_t* _queue, void* _element)
+{
+	if (_queue->first != _queue->next)
+	{	
+		memmove((void*)_queue->next, (void*)_element, _queue->element_size);
+		_queue->first = _queue->first == 0 ? _queue->next : _queue->first;
+		_queue->next = _queue->next + _queue->element_size == (uintptr_t)_queue->storage + (_queue->element_size * _queue->max_elements)
+			? (uintptr_t)_queue->storage : _queue->next + _queue->element_size;
+		return I_OK;
+	}
+	return I_FULL;
+}
+
+i_status iqueue_dequeue(iqueue_t* _queue, void* _element)
+{
+	if (_queue->first != (void*)0)
+	{
+		memmove((void*)_element, (void*)_queue->first, _queue->element_size);
+		_queue->first = _queue->first + _queue->element_size == (uintptr_t)_queue->storage + (_queue->element_size * _queue->max_elements)
+			? (uintptr_t)_queue->storage : _queue->first + _queue->element_size;
+		_queue->first = _queue->first == _queue->next ? 0 : _queue->first;
+
+		return I_OK;
+	}
+	return I_EMPTY;
+}
+
+void* iqueue_dequeue_fast(iqueue_t* _queue)
+{
+	if (_queue->first != 0)
+	{	
+		uintptr_t x = _queue->first;
+		_queue->first = _queue->first + _queue->element_size == (uintptr_t)_queue->storage + (_queue->element_size * _queue->max_elements)
+			? (uintptr_t)_queue->storage : _queue->first + _queue->element_size;
+		_queue->first = _queue->first == _queue->next ? 0 : _queue->first;
+		return (void*)x;
+	}
+	return NULL;
+}
+
+
+i_status iqueue_size(iqueue_t* _queue, uint32_t* _size)
+{
+	*_size = _queue->first == 0
+		? 0
+		: _queue->first < _queue->next
+		? (_queue->next - _queue->first) / _queue->element_size
+		: _queue->max_elements - ((_queue->first - _queue->next) / _queue->element_size);
+
+	return I_OK;
+}
+
+/******************************************************************************
+* EOF - NO CODE AFTER THIS LINE
+******************************************************************************/

+ 112 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/lib/lib_iqueue.h

@@ -0,0 +1,112 @@
+/*!
+	@file   lib_iqueue.h
+	@brief  <brief description here>
+	@t.odo	-
+	---------------------------------------------------------------------------
+
+	MIT License
+	Copyright (c) 2018 Io. D (Devcoons)
+
+	Permission is hereby granted, free of charge, to any person obtaining a copy
+	of this software and associated documentation files (the "Software"), to deal
+	in the Software without restriction, including without limitation the rights
+	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+	copies of the Software, and to permit persons to whom the Software is
+	furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be included in all
+	copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+	SOFTWARE.
+*/
+/******************************************************************************
+* Preprocessor Definitions & Macros
+******************************************************************************/
+
+#ifndef LIBRARIES_INC_LIB_IQUEUE_H_
+#define LIBRARIES_INC_LIB_IQUEUE_H_
+
+/******************************************************************************
+* Includes
+******************************************************************************/
+
+#include <inttypes.h>
+#include <string.h>
+
+/******************************************************************************
+* Enumerations, structures & Variables
+******************************************************************************/
+
+#if !defined(ENUM_I_STATUS)
+#define ENUM_I_STATUS
+typedef enum
+{
+	I_OK 				= 0x00,
+	I_INVALID 			= 0x01,
+	I_EXISTS 			= 0x02,
+	I_NOTEXISTS 		= 0x03,
+	I_FAILED 			= 0x04,
+	I_EXPIRED 			= 0x05,
+	I_UNKNOWN 			= 0x06,
+	I_INPROGRESS 		= 0x07,
+	I_IDLE				= 0x08,
+	I_FULL				= 0x09,
+	I_EMPTY				= 0x0A,
+	I_YES				= 0x0B,
+	I_NO				= 0x0C,
+	I_SKIP				= 0x0D,
+	I_DEBUG_01 			= 0xE0,
+	I_DEBUG_02 			= 0xE1,
+	I_DEBUG_03 			= 0xE2,
+	I_DEBUG_04 			= 0xE3,
+	I_DEBUG_05 			= 0xE4,
+	I_DEBUG_06 			= 0xE5,
+	I_DEBUG_07 			= 0xE6,
+	I_DEBUG_08 			= 0xE7,
+	I_DEBUG_09 			= 0xE8,
+	I_DEBUG_10 			= 0xE9,
+	I_DEBUG_11 			= 0xEA,
+	I_DEBUG_12 			= 0xEB,
+	I_DEBUG_13 			= 0xEC,
+	I_DEBUG_14 			= 0xED,
+	I_DEBUG_15 			= 0xEE,
+	I_DEBUG_16 			= 0xEF,
+	I_MEMUNALIGNED 		= 0xFD,
+	I_NOTIMPLEMENTED 	= 0xFE,
+	I_ERROR 			= 0xFF
+	}i_status;
+#endif
+
+
+typedef struct
+{
+	volatile void * storage;
+	volatile uintptr_t first;
+	volatile uintptr_t next;
+	volatile size_t element_size;
+	volatile uint32_t max_elements;
+}
+iqueue_t;
+
+/******************************************************************************
+* Declaration | Public Functions
+******************************************************************************/
+
+i_status iqueue_init   (iqueue_t * _queue, int _max_elements, size_t _element_size, void * _storage);
+i_status iqueue_enqueue(iqueue_t * _queue, void * _element);
+i_status iqueue_dequeue(iqueue_t * _queue, void * _element);
+i_status iqueue_size   (iqueue_t * _queue, uint32_t * _size);
+i_status iqueue_advance_next(iqueue_t * _queue);
+volatile void* iqueue_get_next_enqueue(iqueue_t * _queue);
+void* iqueue_dequeue_fast(iqueue_t * _queue);
+
+/******************************************************************************
+* EOF - NO CODE AFTER THIS LINE
+******************************************************************************/
+#endif

+ 1187 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/src/lib_iso15765.c

@@ -0,0 +1,1187 @@
+/*!
+@file   iso15765_2.c
+@brief  Source file of the ISO15765-2 library
+@t.odo	-
+---------------------------------------------------------------------------
+
+MIT License
+Copyright (c) 2020 Io. D (Devcoons.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+/******************************************************************************
+* Preprocessor Definitions & Macros
+******************************************************************************/
+
+/******************************************************************************
+* Includes
+******************************************************************************/
+#include "sys_log.h"
+#include "lib_iso15765.h"
+
+/******************************************************************************
+* Enumerations, structures & Variables
+******************************************************************************/
+#define  DEBUG_LOG_EN 0
+/* Structs used by the service to inform the user(upper layer) of an event */
+static n_indn_t sgn_indn;
+static n_ff_indn_t sgn_ff_indn;
+static n_cfm_t sgn_conf;
+static n_chg_param_cfm_t sgn_chg_cfm;
+
+/******************************************************************************
+* Declaration | Static Functions
+******************************************************************************/
+
+/******************************************************************************
+* Definition  | Static Functions
+******************************************************************************/
+
+/*
+ * Default empty callback functions. The user can assing his own during the init
+ * of the service.
+ */
+static void indn(n_indn_t* info)
+{
+	ISO_15675_UNUSED(info);
+}
+
+static void ff_indn(n_ff_indn_t* info)
+{
+	ISO_15675_UNUSED(info);
+}
+
+static void cfm(n_cfm_t* info)
+{
+	ISO_15675_UNUSED(info);
+}
+
+static void cfg_cfm(n_chg_param_cfm_t* info)
+{
+	ISO_15675_UNUSED(info);
+}
+
+/*
+ * Helper function to find the closest can_dl
+ */
+inline static uint8_t n_get_closest_can_dl(uint8_t size, cbus_fr_format tmt)
+{
+	uint8_t rval = 0;
+
+	if (tmt == CBUS_FR_FRM_STD)
+	{
+		rval = (size <= 0x08U) ? size : 0x08U;
+	}
+	else
+	{
+		if (size <= 8)
+		{
+			rval = size;
+		}
+		else if (size <= 12)
+		{
+			rval = 12;
+		}
+		else if (size <= 16)
+		{
+			rval = 16;
+		}
+		else if (size <= 20)
+		{
+			rval = 20;
+		}
+		else if (size <= 24)
+		{
+			rval = 24;
+		}
+		else if (size <= 32)
+		{
+			rval = 32;
+		}
+		else if (size <= 48)
+		{
+			rval = 48;
+		}
+		else
+		{
+			rval = 64;
+		}
+	}
+
+	return rval;
+}
+
+/*
+ * Helper function to find the closest can_dl
+
+ */
+inline static uint8_t n_get_dt_offset(addr_md address, pci_type pci, uint16_t data_size)
+{
+	uint8_t addr_mode = address;
+	if(address == N_ADM_BMW)
+	{
+		addr_mode = N_ADM_EXTENDED;
+	}
+
+	uint8_t offset = (addr_mode & 0x01); //固定为1.
+
+	switch (pci)
+	{
+	case N_PCI_T_SF:
+		offset += 1;
+		offset += data_size <= (8 - offset) ? 0 : 1;
+		break;
+	case N_PCI_T_FF:
+		offset += 2;
+		offset += data_size > 4095 ? 4 : 0;
+		break;
+	case N_PCI_T_CF:
+		offset += 1;
+		break;
+	case N_PCI_T_FC:
+		offset += 3;
+		break;
+	default:
+		offset = 0;
+		break;
+	}
+	return offset;
+}
+
+/*
+ * Helper function to find which PCI_Type the outbound stream has to use
+ */
+inline static pci_type n_out_frame_type(iso15765_t* instance)
+{
+	pci_type result = N_PCI_T_CF;
+
+	addr_md tmp_addr_md = instance->addr_md;
+
+	if(instance->addr_md == N_ADM_BMW)
+	{
+		tmp_addr_md = N_ADM_EXTENDED;
+	}
+
+	if (instance->out.cf_cnt == 0)
+	{
+		if ((tmp_addr_md & 0x01) == 1)
+		{
+			if (instance->out.fr_fmt == CBUS_FR_FRM_STD)
+			{
+				result = instance->out.msg_sz <= 6 ? N_PCI_T_SF : N_PCI_T_FF;
+			}
+			else
+			{
+				result = instance->out.msg_sz <= 61 ? N_PCI_T_SF : N_PCI_T_FF;
+			}
+		}
+		else
+		{
+			if (instance->out.fr_fmt == CBUS_FR_FRM_STD)
+			{
+				result = instance->out.msg_sz <= 7 ? N_PCI_T_SF : N_PCI_T_FF;
+			}
+			else
+			{
+				result = instance->out.msg_sz <= 62 ? N_PCI_T_SF : N_PCI_T_FF;
+			}
+		}
+	}
+	return result;
+}
+
+/*
+ * Convert partially the CANBus Frame from the PCI
+ */
+inline static n_rslt n_pci_pack(addr_md mode, n_pdu_t* n_pdu, const uint8_t* dt)
+{
+	n_rslt result = N_ERROR;
+	addr_md addr_mode = mode;
+
+	if (n_pdu != NULL && dt != NULL)
+	{
+		if(mode == N_ADM_BMW)
+		{
+			addr_mode = N_ADM_EXTENDED;
+		}
+#if DEBUG_LOG_EN
+		LOG_D("addr_mode:0x%x", addr_mode);
+#endif //DEBUG_LOG_EN
+		uint8_t offs = (addr_mode & 0x01);
+
+		switch (n_pdu->n_pci.pt)
+		{
+		case N_PCI_T_SF:
+			if (n_pdu->n_pci.dl <= (uint16_t)(7 - offs))
+			{
+				n_pdu->dt[0 + offs] = (n_pdu->n_pci.pt) << 4
+					| (uint8_t)(n_pdu->n_pci.dl & 0x0F);
+			}
+			else
+			{
+				n_pdu->dt[0 + offs] = 0 + ((n_pdu->n_pci.pt) << 4);
+				n_pdu->dt[1 + offs] = (uint8_t)n_pdu->n_pci.dl;
+			}
+			result = N_OK;
+			break;
+		case N_PCI_T_CF:
+			n_pdu->dt[0 + offs] = (n_pdu->n_pci.pt) << 4
+				| n_pdu->n_pci.sn;
+			result = N_OK;
+			break;
+		case N_PCI_T_FF:
+			n_pdu->dt[0 + offs] = (n_pdu->n_pci.pt) << 4
+				| (n_pdu->n_pci.dl & 0x0F00) >> 8;
+			n_pdu->dt[1 + offs] = n_pdu->n_pci.dl & 0x00FF;
+			result = N_OK;
+			break;
+		case N_PCI_T_FC:
+			n_pdu->dt[0 + offs] = (n_pdu->n_pci.pt) << 4
+				| n_pdu->n_pci.fs;
+			n_pdu->dt[1 + offs] = n_pdu->n_pci.bs;
+			n_pdu->dt[2 + offs] = n_pdu->n_pci.st;
+			result = N_OK;
+			break;
+		default:
+			result = N_ERROR;
+			break;
+		}
+	}
+	return result;
+}
+
+/*
+ * Convert the PCI from the CANBus Frame
+ */
+inline  static n_rslt n_pci_unpack(addr_md mode, n_pdu_t* n_pdu, uint8_t dlc, uint8_t* dt)
+{
+	n_rslt result = N_ERROR;
+	addr_md addr_mode = mode;
+	if(addr_mode == N_ADM_BMW)
+	{
+		addr_mode = N_ADM_EXTENDED;
+	}
+#if DEBUG_LOG_EN
+	LOG_D("dlc:%d,data:", dlc);
+	for(int i=0; i<dlc; i++)
+	{
+		printf("%02X", dt[i]);
+	}
+	printf("\r\n");
+#endif //DEBUG_LOG_EN
+	if (n_pdu != NULL && dt != NULL)
+	{
+		uint8_t offs = (addr_mode & 0x01); //固定为1.
+		n_pdu->n_pci.pt = (dt[0 + offs] & 0xF0) >> 4; //判断是首帧流控帧?
+#if DEBUG_LOG_EN
+		LOG_D("n_pdu->n_pci.pt:0x%x", n_pdu->n_pci.pt);
+#endif 
+		switch (n_pdu->n_pci.pt)
+		{
+		case N_PCI_T_SF: //单帧
+			n_pdu->n_pci.dl = dlc <= 8 ? (dt[0 + offs] & 0x0F) : (dt[1 + offs]); //计算返回应用的payload的长度.单帧dlc长度可以大于8么.?
+			result = N_OK;
+#if DEBUG_LOG_EN
+			LOG_D("N_PCI_T_SF,n_pdu->n_pci.dl:%d", n_pdu->n_pci.dl);
+#endif //DEBUG_LOG_EN			
+			break;
+		case N_PCI_T_FF: //首帧
+			n_pdu->n_pci.dl = (dt[0 + offs] & 0x0F) << 8 | dt[1 + offs];
+			n_pdu->sz = dlc - (2 + offs);
+			result = N_OK;
+#if DEBUG_LOG_EN
+			LOG_D("N_PCI_T_FF,n_pdu->n_pci.dl:%d,n_pdu->sz:%d", n_pdu->n_pci.dl, n_pdu->sz);
+#endif //DEBUG_LOG_EN			
+			break;
+		case N_PCI_T_FC: //流控帧
+			n_pdu->n_pci.fs = dt[0 + offs] & 0x0F;
+			n_pdu->n_pci.bs = dt[1 + offs];
+			n_pdu->n_pci.st = dt[2 + offs];
+			n_pdu->sz = dlc - (2 + offs);
+			result = N_OK;
+#if DEBUG_LOG_EN
+			LOG_D("N_PCI_T_FF,n_pdu->n_pci.fs:%d,n_pdu->n_pci.bs:%d,n_pdu->n_pci.st:%d,n_pdu->sz:%d", n_pdu->n_pci.fs,n_pdu->n_pci.bs,n_pdu->n_pci.st,n_pdu->sz);
+#endif //DEBUG_LOG_EN			
+			break;
+		case N_PCI_T_CF: //连续帧
+			n_pdu->n_pci.sn = (dt[0 + offs] & 0x0F);
+			n_pdu->sz = dlc - (1 + offs);
+			result = N_OK;
+#if DEBUG_LOG_EN
+			LOG_D("N_PCI_T_CF,n_pdu->n_pci.sn:%d,n_pdu->sz:%d", n_pdu->n_pci.sn, n_pdu->sz);
+#endif //DEBUG_LOG_EN			
+			break;
+		default:
+			result = N_ERROR;
+			break;
+		}
+	}
+	return result;
+}
+
+/*
+ * Helper function of 'n_pdu_pack' to use the frame payload.
+ */
+inline static n_rslt n_pdu_pack_dt(addr_md mode, n_pdu_t* n_pdu, uint8_t* dt)
+{
+	n_rslt result = N_ERROR;
+	addr_md addr_mode = mode;
+
+	if (dt != NULL)
+	{
+		if(mode == N_ADM_BMW)
+		{
+			addr_mode = N_ADM_EXTENDED;
+		}
+		switch (n_pdu->n_pci.pt)
+		{
+		case N_PCI_T_SF:
+			memmove(&n_pdu->dt[n_get_dt_offset(addr_mode, N_PCI_T_SF, n_pdu->sz)], dt, n_pdu->sz);
+			break;
+		case N_PCI_T_FF:
+			memmove(&n_pdu->dt[n_get_dt_offset(addr_mode, N_PCI_T_FF, n_pdu->sz)], dt, n_pdu->sz);
+			break;
+		case N_PCI_T_CF:
+			memmove(&n_pdu->dt[n_get_dt_offset(addr_mode, N_PCI_T_CF, n_pdu->sz)], dt, n_pdu->sz);
+			break;
+		case N_PCI_T_FC:
+			memmove(&n_pdu->dt[n_get_dt_offset(addr_mode, N_PCI_T_FC, n_pdu->sz)], dt, n_pdu->sz);
+
+			break;
+
+		default:
+			break;
+		}
+		result = N_OK;
+	}
+	return result;
+}
+
+/*
+ * Helper function of 'n_pdu_unpack' to use the frame payload.
+ */
+inline static n_rslt n_pdu_unpack_dt(addr_md mode, n_pdu_t* n_pdu, uint8_t* dt)
+{
+	n_rslt result = N_ERROR;
+	addr_md addr_mode = mode;
+	if(mode == N_ADM_BMW)
+	{
+		addr_mode = N_ADM_EXTENDED;
+	}
+
+	if ((n_pdu != NULL) && (dt != NULL))
+	{
+		switch (n_pdu->n_pci.pt)
+		{
+		case N_PCI_T_SF: //首帧.获取从哪个地方开始拷贝.
+#if DEBUG_LOG_EN
+			LOG_D("copy N_PCI_T_SF data, len:%d", n_pdu->n_pci.dl);
+#endif //DEBUG_LOG_EN			
+			memmove(n_pdu->dt, &dt[n_get_dt_offset(addr_mode, N_PCI_T_SF, n_pdu->n_pci.dl)], n_pdu->n_pci.dl);
+			result = N_OK;
+			break;
+		case N_PCI_T_FF:
+#if DEBUG_LOG_EN
+			LOG_D("copy N_PCI_T_FF data, len:%d", n_pdu->sz);
+#endif //DEBUG_LOG_EN			
+			memmove(n_pdu->dt, &dt[n_get_dt_offset(addr_mode, N_PCI_T_FF, n_pdu->sz)], n_pdu->sz);
+			result = N_OK;
+			break;
+		case N_PCI_T_CF:
+#if DEBUG_LOG_EN
+			LOG_D("copy N_PCI_T_CF data, len:%d", n_pdu->sz);
+#endif //DEBUG_LOG_EN			
+			memmove(n_pdu->dt, &dt[n_get_dt_offset(addr_mode, N_PCI_T_CF, n_pdu->sz)], n_pdu->sz);
+			result = N_OK;
+			break;
+		case N_PCI_T_FC:
+#if DEBUG_LOG_EN
+			LOG_D("copy N_PCI_T_FC data, len:%d", n_pdu->sz);
+#endif //DEBUG_LOG_EN
+			memmove(n_pdu->dt, &dt[n_get_dt_offset(addr_mode, N_PCI_T_FC, n_pdu->sz)], n_pdu->sz);
+			result = N_OK;
+			break;
+		default:
+			result = N_ERROR;
+			break;
+		}
+	}
+	return result;
+}
+
+/*
+ * Convert CANBus frame from PDU
+ */
+inline static n_rslt n_pdu_pack(addr_md mode, n_pdu_t* n_pdu, uint32_t* id, uint8_t* dt)
+{
+	if ((dt == NULL) || (id == NULL))
+	{
+		return N_ERROR;
+	}
+#if DEBUG_LOG_EN
+	LOG_D("pack_mode:0x%x", mode);
+#endif //DEBUG_LOG_EN
+	switch (mode)
+	{
+	case N_ADM_EXTENDED:
+		n_pdu->dt[0] = n_pdu->n_ai.n_ta;
+	case N_ADM_NORMAL:
+		*id = 0x80
+			| n_pdu->n_ai.n_pr << 8
+			| n_pdu->n_ai.n_ta << 3
+			| n_pdu->n_ai.n_sa
+			| (n_pdu->n_ai.n_tt == N_TA_T_PHY ? 0x40U : 0x00U);
+		break;
+	case N_ADM_MIXED29:
+		*id = n_pdu->n_ai.n_pr << 26
+			| (n_pdu->n_ai.n_tt == N_TA_T_PHY ? 0xCE : 0xCD) << 16
+			| n_pdu->n_ai.n_ta << 8
+			| n_pdu->n_ai.n_sa;
+		n_pdu->dt[0] = n_pdu->n_ai.n_ae;
+		break;
+	case N_ADM_FIXED:
+		*id = n_pdu->n_ai.n_pr << 26
+			| (n_pdu->n_ai.n_tt == N_TA_T_PHY ? 0xDA : 0xDB) << 16
+			| n_pdu->n_ai.n_ta << 8
+			| n_pdu->n_ai.n_sa;
+		break;
+	case N_ADM_MIXED11:
+		*id = 0x80
+			| n_pdu->n_ai.n_pr << 8
+			| n_pdu->n_ai.n_ta << 3
+			| n_pdu->n_ai.n_sa
+			| (n_pdu->n_ai.n_tt == N_TA_T_PHY ? 0x40U : 0x00U);
+		n_pdu->dt[0] = n_pdu->n_ai.n_ae;
+		break;
+	case N_ADM_BMW:
+		*id = (n_pdu->n_ai.n_pr << 8) + n_pdu->n_ai.n_sa;
+		n_pdu->dt[0] = n_pdu->n_ai.n_ta;
+#if DEBUG_LOG_EN
+		LOG_D("*id:0x%x,n_pdu->dt[0]:0x%x", *id,n_pdu->dt[0]);
+#endif //DEBUG_LOG_EN
+		break;
+	default:
+		return N_ERROR;
+		break;
+	}
+
+	n_pci_pack(mode, n_pdu, dt);
+	return n_pdu_pack_dt(mode, n_pdu, dt);
+}
+
+/*
+ * Convert PDU from CANBus frame
+ */
+inline static n_rslt n_pdu_unpack(addr_md mode, n_pdu_t* n_pdu, uint32_t id, uint8_t dlc, uint8_t* dt)
+{
+	if (n_pdu == NULL || dt == NULL)
+	{
+		return N_ERROR;
+	}
+#if DEBUG_LOG_EN
+	LOG_D("n_pdu_unpack,mode:0x%x",mode);
+#endif //DEBUG_LOG_EN
+	addr_md addr_mode = mode;
+
+	switch (addr_mode)
+	{
+	case N_ADM_MIXED11:
+		n_pdu->n_ai.n_ae = dt[0];
+	case N_ADM_NORMAL:
+		n_pdu->n_ai.n_pr = (uint8_t)((id & 0x700U) >> 8);
+		n_pdu->n_ai.n_ta = (uint8_t)((id & 0x38U) >> 3);
+		n_pdu->n_ai.n_sa = (uint8_t)(id & 0x07U);
+		n_pdu->n_ai.n_tt = (uint8_t)(((id & 0x40U) >> 6) == 1 ? N_TA_T_PHY : N_TA_T_FUNC);
+		break;
+	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_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);
+		break;
+	case N_ADM_FIXED:
+		n_pdu->n_ai.n_pr = (uint8_t)((id & 0x1C000000) >> 26);
+		n_pdu->n_ai.n_tt = (uint8_t)(((id & 0x00FF0000) >> 16) == 0xDA ? 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);
+		break;
+	case N_ADM_EXTENDED:
+		n_pdu->n_ai.n_pr = (uint8_t)((id & 0x700U) >> 8);
+		n_pdu->n_ai.n_ta = (uint8_t)((id & 0x38U) >> 3);
+		n_pdu->n_ai.n_sa = (uint8_t)(id & 0x07U);
+		n_pdu->n_ai.n_tt = (uint8_t)((id & 0x40U) >> 6 == 1 ? N_TA_T_PHY : N_TA_T_FUNC);
+		n_pdu->n_ai.n_ae = dt[0];
+		break;
+	case N_ADM_BMW:
+		n_pdu->n_ai.n_pr = (uint8_t)((id & 0x700U) >> 8);
+		n_pdu->n_ai.n_ta = (uint8_t)((id & 0xFF));
+		n_pdu->n_ai.n_sa = (uint8_t)((id >> 8) & 0xFF);
+		n_pdu->n_ai.n_tt = (uint8_t)((id & 0x40U) >> 6 == 1 ? N_TA_T_PHY : N_TA_T_FUNC);
+		n_pdu->n_ai.n_ae = dt[0];
+#if DEBUG_LOG_EN
+		LOG_D("n_pr:0x%x,n_ta:0x%x,n_sa:0x%x,n_tt:0x%x,n_ae:0x%x", n_pdu->n_ai.n_pr,n_pdu->n_ai.n_ta,n_pdu->n_ai.n_sa,n_pdu->n_ai.n_tt,n_pdu->n_ai.n_ae);
+#endif //DEBUG_LOG_EN
+		break;
+	default:
+		return N_UNE_PDU;
+	}
+
+	n_pci_unpack(mode, n_pdu, dlc, dt);  //获取帧类型和payload长度.
+	n_pdu_unpack_dt(mode, n_pdu, dt);    //拷贝数据.
+#if DEBUG_LOG_EN
+	LOG_D("n_pdu_unpack_finish");
+#endif //DEBUG_LOG_EN
+	return N_OK;
+}
+
+/*
+ * Given the correct parameters, the service informs the upper-layer/user about
+ * an event by using the appropriate callbacks. The function does not support
+ * the N_CHG_P_CONF signal type.
+ */
+inline static void signaling(signal_tp tp, n_iostream_t* strm, void(*cb)(void*), uint16_t msg_sz, n_rslt sgn_rslt)
+{
+#if DEBUG_LOG_EN
+	LOG_D("tp:0x%x", tp);
+#endif //DEBUG_LOG_EN
+	if (cb != NULL)
+	{
+		switch (tp)
+		{
+		case N_INDN: 
+			//首帧抛到上层.
+			sgn_indn.rslt = sgn_rslt;
+			sgn_indn.msg_sz = msg_sz;
+			sgn_indn.fr_fmt = strm->fr_fmt;
+			memmove(&sgn_indn.n_ai, &strm->pdu.n_ai, sizeof(n_ai_t));
+			memmove(&sgn_indn.n_pci, &strm->pdu.n_pci, sizeof(n_pci_t));
+			memmove(&sgn_indn.msg, strm->msg, msg_sz);
+			strm->sts = N_S_IDLE;
+#if DEBUG_LOG_EN
+			LOG_D("send event to upper,N_INDN,strm->sts:0x%x", strm->sts);
+#endif //DEBUG_LOG_EN
+			cb(&sgn_indn);//抛到上层.
+			break;
+		case N_FF_INDN:
+			sgn_ff_indn.fr_fmt = strm->fr_fmt;
+			sgn_ff_indn.msg_sz = msg_sz;
+			memmove(&sgn_ff_indn.n_ai, &strm->pdu.n_ai, sizeof(n_ai_t));
+			memmove(&sgn_ff_indn.n_pci, &strm->pdu.n_pci, sizeof(n_pci_t));
+			strm->sts = (uint8_t)((uint32_t)strm->sts | (uint32_t)N_S_RX_BUSY);
+#if DEBUG_LOG_EN			
+			LOG_D("send event to upper,N_FF_INDN,strm->sts:0x%x", strm->sts);
+#endif //DEBUG_LOG_EN
+			cb(&sgn_ff_indn);
+			break;
+		case N_CONF:
+			sgn_conf.rslt = sgn_rslt;
+			memmove(&sgn_conf.n_ai, &strm->pdu.n_ai, sizeof(n_ai_t));
+			memmove(&sgn_conf.n_pci, &strm->pdu.n_pci, sizeof(n_pci_t));
+#if DEBUG_LOG_EN			
+			LOG_D("send event to upper,N_CONF,strm->sts:0x%x", strm->sts);
+#endif //DEBUG_LOG_EN
+			cb(&sgn_conf);
+			break;
+		default:
+			return;
+		}
+	}
+	return;
+}
+
+/*
+ * Check if any timeout should be occured.
+ */
+inline static n_rslt process_timeouts(iso15765_t* ih)
+{
+	if (ih->out.sts != N_S_TX_WAIT_FC || ih->out.last_upd.n_bs == 0 || ih->config.n_bs == 0
+		|| (ih->out.last_upd.n_bs + ih->config.n_bs) >= ih->clbs.get_ms())
+	{
+		return N_OK;
+	}
+
+	/* if timeout occures then reset the counters and report to the upper layer */
+	ih->out.cf_cnt = 0x0;
+	signaling(N_INDN, &ih->out, (void*)ih->clbs.indn, ih->out.msg_sz, N_TIMEOUT_Bs);
+	ih->clbs.on_error(N_TIMEOUT_Bs);
+	return N_TIMEOUT_Bs;
+}
+
+/*
+ * Sends a Flow Control Frame upon request from the reception procedure
+ */
+static n_rslt send_N_PCI_T_FC(iso15765_t* ih)
+{
+	uint32_t id;
+
+	ih->out.sts |= N_S_TX_BUSY;
+	ih->fl_pdu.n_pci.pt = N_PCI_T_FC;
+	ih->fl_pdu.n_pci.bs = ih->config.bs;
+	ih->fl_pdu.n_pci.st = ih->config.stmin;
+	ih->fl_pdu.n_ai.n_ae = ih->in.pdu.n_ai.n_ae;
+	ih->fl_pdu.n_ai.n_sa = ih->in.pdu.n_ai.n_ta;
+	ih->fl_pdu.n_ai.n_ta = ih->in.pdu.n_ai.n_sa;
+	ih->fl_pdu.n_ai.n_pr = ih->in.pdu.n_ai.n_pr;
+	ih->fl_pdu.n_ai.n_tt = ih->in.pdu.n_ai.n_tt;
+	ih->in.cfg_bs = ih->config.bs;
+#if DEBUG_LOG_EN
+	LOG_D("n_pdu_pack");
+#endif //DEBUG_LOG_EN
+	if (n_pdu_pack(ih->addr_md, &ih->fl_pdu, &id, ih->out.msg) != N_OK)
+	{
+		ih->out.sts = (ih->out.sts & (~N_S_TX_BUSY));
+		return N_ERROR;
+	}
+#if DEBUG_LOG_EN
+	LOG_D("send_N_PCI_T_FC,send_frame");
+#endif //DEBUG_LOG_EN
+	ih->clbs.send_frame(ih->fr_id_type, id, ih->in.fr_fmt, n_get_dt_offset(ih->addr_md, N_PCI_T_FC, ih->fl_pdu.sz), ih->fl_pdu.dt);
+	ih->out.sts = (ih->out.sts & (~N_S_TX_BUSY));
+#if DEBUG_LOG_EN
+	LOG_D("ih->out.sts:%d", ih->out.sts);
+#endif //DEBUG_LOG_EN
+	return N_OK;
+}
+
+/*
+ * Helper function to set some basic stream parameters value
+ */
+inline static void set_stream_data(n_iostream_t* ist, uint8_t cf, uint8_t wf, stream_sts sts)
+{
+	ist->cf_cnt = cf;
+	ist->wf_cnt = wf;
+	ist->sts = sts;
+}
+
+/*
+ * Check if current Wait Flow status counter reached the max WFS
+ */
+inline static n_rslt check_max_wf_capacity(iso15765_t* ih)
+{
+	if (ih->out.wf_cnt < ih->config.wf)
+	{
+		return N_OK;
+	}
+
+	ih->clbs.on_error(N_WFT_OVRN);
+	set_stream_data(&ih->out, 0, 0, N_S_IDLE);
+	return N_WFT_OVRN;
+}
+
+/*
+ * Process inbound First Frame reception and report to the upper layer using the
+ * indication callback function.
+ */
+static n_rslt process_in_ff(iso15765_t* ih, canbus_frame_t* frame)
+{
+	if (ih->in.msg_sz > I15765_MSG_SIZE)
+	{
+		ih->clbs.on_error(N_INV_REQ_SZ);
+		return N_INV_REQ_SZ;
+	}
+	/* If reception is in progress: Terminate the current reception, report an
+	* N_USData.indication, with <N_Result> set to N_UNEXP_PDU, to the upper layer, and
+	* process the FF N_PDU as the start of a new reception.*/
+	if ((ih->in.sts & N_S_RX_BUSY) != 0)
+	{
+#if DEBUG_LOG_EN
+		LOG_E("N_UNE_PDU");
+#endif //DEBUG_LOG_EN
+		ih->clbs.on_error(N_UNE_PDU);
+		signaling(N_INDN, &ih->in, (void*)ih->clbs.indn, ih->in.msg_sz, N_UNE_PDU);
+	}
+
+	/* Copy all data, init the CFrames reception parameters and send a FC */
+	memmove(ih->in.msg, ih->in.pdu.dt, ih->in.pdu.sz);
+	ih->in.msg_sz = ih->in.pdu.n_pci.dl; //记录总长度
+	ih->in.msg_pos = ih->in.pdu.sz;
+#if DEBUG_LOG_EN	
+	LOG_D("msg_sz:%d,msg_pos:%d", ih->in.msg_sz, ih->in.msg_pos);
+#endif //DEBUG_LOG_EN
+	ih->in.cf_cnt = 0;
+	ih->in.wf_cnt = 0;
+	signaling(N_FF_INDN, &ih->in, (void*)ih->clbs.ff_indn, ih->in.msg_sz, N_OK);
+#if DEBUG_LOG_EN
+	LOG_D("send_N_PCI_T_FC");
+#endif //DEBUG_LOG_EN
+	send_N_PCI_T_FC(ih);
+	return N_OK;
+}
+
+/*
+ * Process inbound Single Frame reception and report to the upper layer using the
+ * indication callback function.
+ */
+static n_rslt process_in_sf(iso15765_t* ih, canbus_frame_t* frame)
+{
+	/* If reception is in progress: Terminate the current reception, report an
+	* N_USData.indication, with <N_Result> set to N_UNEXP_PDU, to the upper layer, and
+	* process the SF N_PDU as the start of a new reception.*/
+#if DEBUG_LOG_EN
+	LOG_D("ih->in.sts:0x%x", ih->in.sts); //这个初始值是IDLE是从哪设置的?
+#endif //DEBUG_LOG_EN
+	if ((ih->in.sts & N_S_RX_BUSY) != 0)
+	{
+#if DEBUG_LOG_EN
+		LOG_E("N_UNE_PDU");
+#endif //DEBUG_LOG_EN
+		ih->clbs.on_error(N_UNE_PDU);
+		signaling(N_INDN, &ih->in, (void*)ih->clbs.indn, ih->in.msg_sz, N_UNE_PDU);
+	}
+	memmove(&ih->in.msg[0], ih->in.pdu.dt, ih->in.pdu.n_pci.dl);//拷贝payload.
+	ih->in.sts = N_S_IDLE;
+	//往上层抛出事件.
+	signaling(N_INDN, &ih->in, (void*)ih->clbs.indn, ih->in.pdu.n_pci.dl, N_OK);
+	return N_OK;
+}
+
+/*
+ * Process inbound Consecutive Frames. Perform all the required checks according
+ * to (ref: iso15765-2 p.26) and if everything is ok copy all the data to the
+ * inbound stream buffer and update the reception parameters (CF_cnt,timeouts etc)
+ */
+static n_rslt process_in_cf(iso15765_t* ih, canbus_frame_t* frame)
+{
+	n_rslt rslt = N_OK;
+
+	/* According to (ref: iso15765-2 p.26) if we are not in progress of
+	* reception we should ignore it */
+	if ((ih->in.sts & N_S_RX_BUSY) == 0)
+	{
+		rslt = N_UNE_CF;
+		goto in_cf_error;
+	}
+
+	/* Increase the CF counter and check if the reception sequence is ok */
+	ih->in.cf_cnt = ih->in.cf_cnt + 1 > 0x0F ? 0 : ih->in.cf_cnt + 1;
+#if DEBUG_LOG_EN
+	LOG_D("ih->in.cf_cnt:%d,val:%d", ih->in.cf_cnt, ih->in.cf_cnt & 0x0f);
+	LOG_D("ih->in.pdu.n_pci.sn:%d", ih->in.pdu.n_pci.sn);
+#endif //DEBUG_LOG_EN
+	if ((ih->in.cf_cnt & 0x0f) != ih->in.pdu.n_pci.sn)
+	{
+		rslt = N_INV_SEQ_NUM;
+		goto in_cf_error;
+	}
+
+	/* As long as everything is ok the we copy the frame data to the inbound
+	* stream buffer. Afterwards check if the message size is completed and
+	* signal the user and afterwards reset the inboud stream */
+	memmove(&ih->in.msg[ih->in.msg_pos], ih->in.pdu.dt, ih->in.pdu.sz);
+	ih->in.msg_pos += ih->in.pdu.sz;
+
+	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_OK;
+	}
+	/* if we reach the max CF counter, then we send a FC frame */
+#if DEBUG_LOG_EN
+	LOG_D("ih->config.bs:0x%x,ih->in.cf_cnt:0x%x",ih->config.bs,ih->in.cf_cnt);
+#endif //DEBUG_LOG_EN
+	if(ih->config.bs != 0)
+	{
+		if (ih->in.cf_cnt == ih->config.bs)
+		{
+			// ih->in.cf_cnt = 0;
+			// LOG_D("send_N_PCI_T_FC");
+			// send_N_PCI_T_FC(ih);
+		}
+	}
+	/* Update the Cr timer */
+	ih->in.last_upd.n_cr = ih->clbs.get_ms();
+	return rslt;
+
+in_cf_error:
+	ih->clbs.on_error(rslt);
+	ih->in.sts = N_S_IDLE;
+	return rslt;
+}
+
+/*
+ * Process inbound Flow Control Frames. Outcome depends on the stream status
+ * (if it is busy etc) as well as the Flow Control Status.
+ */
+static n_rslt process_in_fc(iso15765_t* ih, canbus_frame_t* frame)
+{
+	n_rslt rslt = N_UNE_PDU;
+
+	/* According to (ref: iso15765-2 p.26) if we are not expecting FC frame
+	* we should ignore it */
+	if (ih->out.sts != N_S_TX_WAIT_FC)
+	{
+		return rslt;
+	}
+
+	switch (ih->in.pdu.n_pci.fs)
+	{
+	case N_WAIT:
+		/* Increase the WF counter, check if we reached the WF Limit to abort
+		* the reception and (if not WF overflow) update the Bs time */
+		ih->out.wf_cnt += 1;
+		if (check_max_wf_capacity(ih) != N_WFT_OVRN)
+		{
+			return N_OK;			
+		}
+		ih->out.last_upd.n_bs = ih->clbs.get_ms();
+		rslt = N_WFT_OVRN;
+		break;
+	case N_OVERFLOW:
+		rslt = N_BUFFER_OVFLW;
+		break;
+	case N_CONTINUE:
+		/* Store the requested transmission parameters (from receiver)
+		* to the outbound stream, reset the counters of CFs(1) and WFs(0)
+		* and change the outbound stream status to Ready */
+		ih->out.cfg_bs = ih->in.pdu.n_pci.bs;
+		ih->out.stmin = ih->in.pdu.n_pci.st;
+		set_stream_data(&ih->out, 1, 0, N_S_TX_READY);
+		return N_OK;
+	default:
+		rslt = N_UNE_FC_STS;
+		break;
+	}
+
+	/* If there is an error (only way to be here) then reset the
+	* outbound stream, set the counters of CFs(0) and WFs(0)
+	* and change the outbound stream status to Idle. Use on_error
+	* callback to inform the upper layer */
+	set_stream_data(&ih->out, 0, 0, N_S_IDLE);
+	ih->clbs.on_error(rslt);
+	ih->in.sts = N_S_IDLE;
+	return rslt;
+}
+
+/*
+ * Inbound stream process. The function receives a canbus frame dequeued by
+ * the 'iso15765_process' and performs any needed operation to identify and
+ * consume the underlying information.
+ */
+inline static n_rslt iso15765_process_in(iso15765_t* ih, canbus_frame_t* frame)
+{
+	/* Converting the canbus frame to PDU format and process it by its PCI Type */
+	ih->in.fr_fmt = frame->fr_format;
+#if DEBUG_LOG_EN
+	LOG_D("process_frame:0x%x", frame->fr_format);
+	LOG_D("can_frame_id:0x%x", frame->id);
+#endif //DEBUG_LOG_EN
+	if (n_pdu_unpack(ih->addr_md, &ih->in.pdu, frame->id, (uint8_t)frame->dlc, frame->dt) == N_OK)
+	{
+#if DEBUG_LOG_EN
+		LOG_D("ih->in.pdu.n_pci.pt:0x%x", ih->in.pdu.n_pci.pt);
+#endif //DEBUG_LOG_EN
+		switch (ih->in.pdu.n_pci.pt)
+		{
+		case N_PCI_T_SF:
+#if DEBUG_LOG_EN
+			LOG_D("now process N_PCI_T_SF");
+#endif //DEBUG_LOG_EN
+			return process_in_sf(ih, frame);
+		case N_PCI_T_FF:
+#if DEBUG_LOG_EN
+			LOG_D("now process N_PCI_T_FF");
+#endif //DEBUG_LOG_EN
+			return process_in_ff(ih, frame);
+		case N_PCI_T_CF:
+#if DEBUG_LOG_EN
+			LOG_D("now process N_PCI_T_CF");
+#endif //DEBUG_LOG_EN
+			return process_in_cf(ih, frame);
+		case N_PCI_T_FC:
+#if DEBUG_LOG_EN
+			LOG_D("now process N_PCI_T_FC");
+#endif //DEBUG_LOG_EN
+			return process_in_fc(ih, frame);
+		default:
+			break;
+		}
+	}
+
+	/* According to (ref: iso15765-2 p.26) if PDU is not valid
+	* we should ignore it */
+	ih->clbs.on_error(N_INV_PDU);
+	return N_INV_PDU;
+}
+
+/*
+ * Procces the outbound stream.
+ */
+static n_rslt iso15765_process_out(iso15765_t* ih)
+{
+	/* if there is no pending action just return */
+	if (ih->out.sts != N_S_TX_BUSY && ih->out.sts != N_S_TX_READY)
+	{
+		return N_IDLE;
+	}
+
+	uint32_t id;
+	n_rslt rslt = N_ERROR;
+	addr_md addr_mode = ih->addr_md;
+
+	if(ih->addr_md == N_ADM_BMW)
+	{
+		addr_mode = N_ADM_EXTENDED;
+	}
+
+	/* Find the PCI type of the pending outbound stream */
+	ih->out.pdu.n_pci.pt = n_out_frame_type(ih);
+#if DEBUG_LOG_EN
+	LOG_D("ih->out.pdu.n_pci.pt:0x%x", ih->out.pdu.n_pci.pt);
+#endif //DEBUG_LOG_EN
+	switch (ih->out.pdu.n_pci.pt)
+	{
+	case N_PCI_T_SF:
+		/* Copy all the data of the SF to the outbound stream, pack and send the canbus frame */
+		ih->out.pdu.n_pci.dl = ih->out.msg_sz;
+		ih->out.pdu.sz = ih->out.msg_sz;
+#if DEBUG_LOG_EN
+		LOG_D("n_pdu_pack");
+#endif //DEBUG_LOG_EN
+		if (n_pdu_pack(ih->addr_md, &ih->out.pdu, &id, ih->out.msg) != N_OK)
+		{
+			goto iso15765_process_out_cfm;
+		}
+			
+		rslt = ih->clbs.send_frame(ih->fr_id_type, id, ih->out.fr_fmt, n_get_closest_can_dl(ih->out.pdu.sz + n_get_dt_offset(addr_mode, N_PCI_T_SF, ih->out.pdu.sz), ih->out.fr_fmt), ih->out.pdu.dt) == 0 ? N_OK : N_ERROR;
+		goto iso15765_process_out_cfm;
+		break;
+
+	case N_PCI_T_FF:
+		/* Copy all the data of the FF to the outbound stream for transmission and prepare the service
+		* for a multi-frame reception */
+#if DEBUG_LOG_EN
+		LOG_D("addr_mode:0x%x", addr_mode);
+#endif //DEBUG_LOG_EN
+		ih->out.pdu.n_pci.dl = ih->out.msg_sz;
+		ih->out.wf_cnt = 0;
+		ih->out.pdu.sz = ih->out.fr_fmt == CBUS_FR_FRM_STD ? ((addr_mode & 0x01) == 0 ? 6 : 5) : ((addr_mode & 0x01) == 0 ? 62 : 61);
+		ih->out.msg_pos = ih->out.pdu.sz;
+#if DEBUG_LOG_EN
+		LOG_D("n_pdu_pack");
+#endif //DEBUG_LOG_EN
+		if (n_pdu_pack(ih->addr_md, &ih->out.pdu, &id, ih->out.msg) != N_OK)
+		{
+			goto iso15765_process_out_cfm;
+		}
+		ih->out.cf_cnt = 1;
+
+		/* after this frame we expect a Flow Control then assign the correct flag before the
+		* transmission to avoid any issues and start the timer */
+		ih->out.sts = N_S_TX_WAIT_FC;
+		rslt = ih->clbs.send_frame(ih->fr_id_type, id, ih->out.fr_fmt, ih->out.fr_fmt == CBUS_FR_FRM_STD ? 8 : 64, ih->out.pdu.dt) == 0 ? N_OK : N_ERROR;
+		ih->out.last_upd.n_bs = ih->clbs.get_ms();
+		return (rslt == 0) ? N_OK : N_ERROR;
+
+	case N_PCI_T_CF:
+		/* if the minimun difference between transmissions is not reached then skip */
+		if ((ih->out.last_upd.n_cs + ih->config.stmin) > ih->clbs.get_ms())
+		{
+			return N_OK;
+		}
+			
+		/* Increase the sequence number of the frame and the CF counter of the stream
+		* and then pack the PDU to a CANBus frame */
+		ih->out.pdu.n_pci.sn = ih->out.cf_cnt & 0x0F;
+		ih->out.cf_cnt = ih->out.cf_cnt == 0xFF ? 0 : ih->out.cf_cnt + 1;
+		if (ih->out.fr_fmt == CBUS_FR_FRM_STD)
+		{
+			uint8_t max_payload = (addr_mode & 0x01) == 0 ? 7 : 6;
+			ih->out.pdu.sz = ih->out.msg_sz - ih->out.msg_pos;
+			ih->out.pdu.sz = ih->out.pdu.sz >= max_payload ? max_payload : ih->out.pdu.sz;
+		}
+		else
+		{
+			uint8_t max_payload = (addr_mode & 0x01) == 0 ? 63 : 62;
+			ih->out.pdu.sz = ih->out.msg_sz - ih->out.msg_pos;
+			ih->out.pdu.sz = ih->out.pdu.sz >= max_payload ? max_payload : ih->out.pdu.sz;
+		}
+#if DEBUG_LOG_EN
+		LOG_D("n_pdu_pack");
+#endif //DEBUG_LOG_EN
+		if (n_pdu_pack(ih->addr_md, &ih->out.pdu, &id, &ih->out.msg[ih->out.msg_pos]) != N_OK)
+		{
+			goto iso15765_process_out_cfm;
+		}
+			
+		/* Increase the position which indicates the remaining data in the inbound buffer */
+		ih->out.msg_pos += ih->out.pdu.sz;
+
+		/* if after this frame we expect a Flow Control then assign the correct flag before the
+		* transmission to avoid any issues and start the timer */
+		if (ih->out.pdu.n_pci.sn == ih->config.bs)
+		{
+			ih->out.sts = N_S_TX_WAIT_FC;
+			ih->out.last_upd.n_bs = ih->clbs.get_ms();
+		}
+		/* send the canbus frame! */
+		uint8_t of1 = (addr_mode & 0x01) == 0 ? 1 : 2;
+		rslt = ih->clbs.send_frame(ih->fr_id_type, id, ih->out.fr_fmt, n_get_closest_can_dl(ih->out.pdu.sz + of1, ih->out.fr_fmt), ih->out.pdu.dt) == 0 ? N_OK : N_ERROR;
+		ih->out.last_upd.n_cs = ih->clbs.get_ms();
+		if (ih->out.msg_pos >= ih->out.msg_sz)
+		{
+			goto iso15765_process_out_cfm;
+		}
+		return N_OK;
+
+	default:
+		break;
+	}
+
+	return N_ERROR;
+
+iso15765_process_out_cfm:
+	ih->out.sts = N_S_IDLE;
+	ih->out.cf_cnt = 0;
+	ih->out.wf_cnt = 0;
+	//返回给上层结果.
+	signaling(N_CONF, &ih->out, (void*)ih->clbs.cfm, 0, rslt);
+	return rslt;
+}
+
+/******************************************************************************
+* Definition  | Public Functions
+******************************************************************************/
+
+/*
+ * Initialize and check if the configuration parameters of the ISO15765 handler are
+ * correct. Not assigned callback which are not assigned will be automatically assigned
+ * to the static UNUSED functions. If no error occurs, the system can start the service.
+ */
+n_rslt iso15765_init(iso15765_t* instance)
+{
+	if (instance == NULL)
+	{
+		return N_NULL;
+	}
+
+	/* check if parameters have correct values */
+	if ((instance->fr_id_type != CBUS_ID_T_STANDARD && instance->fr_id_type != CBUS_ID_T_EXTENDED))
+	{
+		return N_WRG_VALUE;
+	}
+
+	/* check if must-have functions are assigned */
+	if (instance->clbs.send_frame == NULL || instance->clbs.get_ms == NULL)
+	{
+		return N_MISSING_CLB;
+	}
+
+	/* if optional functions are not assigned then use the defaults */
+	if (instance->clbs.indn == NULL)
+	{
+		instance->clbs.indn = indn;
+	}
+
+	if (instance->clbs.ff_indn == NULL)
+	{
+		instance->clbs.ff_indn = ff_indn;
+	}
+
+	if (instance->clbs.cfm == NULL)
+	{
+		instance->clbs.cfm = cfm;
+	}
+
+	if (instance->clbs.cfg_cfm == NULL)
+	{
+		instance->clbs.cfg_cfm = cfg_cfm;
+	}
+
+	/* clear the in/out streams */
+	memset(&instance->in, 0, sizeof(n_iostream_t));
+	memset(&instance->out, 0, sizeof(n_iostream_t));
+	memset(&instance->fl_pdu, 0, sizeof(n_pdu_t));
+	/* init the incoming canbus frame queue(buffer) */
+	iqueue_init(&instance->inqueue,
+		I15765_QUEUE_ELMS,
+		sizeof(canbus_frame_t),
+		instance->inq_buf);
+
+	ISO_15675_UNUSED(sgn_chg_cfm);
+
+	return N_OK;
+}
+
+/*
+ * Enqueues an incoming frame from the lower level (CANBus) to a buffer. The service
+ * will process the frames during the call of the 'iso15765_process' function. Usually
+ * this function should be called when a canbus frame is received.
+ */
+n_rslt iso15765_enqueue(iso15765_t* instance, canbus_frame_t* frame)
+{
+	return iqueue_enqueue(&instance->inqueue, frame) == I_OK
+		? N_OK : N_BUFFER_OVFLW;
+}
+/*
+ * Request to send a message. Depending on the message a call to 'iso15765_process'
+ * may be required. The service can send one message per time as long as the
+ * communication is syncronous
+ */
+n_rslt iso15765_send(iso15765_t* instance, n_req_t* frame)
+{
+	/* Make sure that there is no transmission in progress */
+	if (instance->out.sts != N_S_IDLE)
+	{
+		return N_TX_BUSY;
+	}
+	/* and the requested size is fitting in our outbound buffer */
+	if (frame->msg_sz > I15765_MSG_SIZE)
+	{
+		return N_BUFFER_OVFLW;
+	}
+
+	/* copy all the info and data to the outbound buffer */
+	instance->out.fr_fmt = frame->fr_fmt;
+	instance->out.msg_sz = frame->msg_sz;
+	memmove(instance->out.msg, frame->msg, frame->msg_sz);
+	memmove(&instance->out.pdu.n_ai, &frame->n_ai, sizeof(n_ai_t));
+	instance->out.sts = N_S_TX_BUSY;
+
+	return N_OK;
+}
+
+/*
+ * Process the inbound/outbound streams of the service. For optimal operation
+ * this function should be called continiously with a minimal delay. It is
+ * suggested to be used in a thread.
+ */
+n_rslt iso15765_process(iso15765_t* instance)
+{
+	/* First check if a timeout is occured. Only for the inbound stream */
+	n_rslt rslt = process_timeouts(instance);
+	canbus_frame_t frame;
+
+	/* Dequeue all the incoming frames and process them */
+	while (iqueue_dequeue(&instance->inqueue, &frame) != I_EMPTY)
+	{
+		rslt |= iso15765_process_in(instance, &frame);
+	}
+
+	/* Process the outbound stream */
+	rslt |= iso15765_process_out(instance);
+	return rslt;
+}
+
+/******************************************************************************
+* EOF - NO CODE AFTER THIS LINE
+******************************************************************************/

+ 408 - 0
BleCanBoxCode/STM32F103RCT6/Middle/iso15765-canbus-master/src/lib_iso15765.h

@@ -0,0 +1,408 @@
+/*!
+@file   iso15765_2.h
+@brief  Header file of the ISO15765-2 library
+@t.odo  -
+---------------------------------------------------------------------------
+
+MIT License
+Copyright (c) 2020 Io. D (Devcoons.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+/******************************************************************************
+* Preprocessor Definitions & Macros
+******************************************************************************/
+
+#ifndef DEVCOONS_ISO15765_2_H_
+#define DEVCOONS_ISO15765_2_H_
+
+#define I15765_MSG_SIZE     516 /* Max. size of the TP up to 4095 bytes */
+#define I15765_QUEUE_ELMS   64  /* No. of max incoming frames that the* reception buffer can hold */
+
+/* Alignment is required for Microcontrollers */
+#if defined(__clang__)
+    #define ALIGNMENT __attribute__ ((aligned (4)))
+#elif defined(__GNUC__) || defined(__GNUG__)
+    #define ALIGNMENT __attribute__ ((aligned (4)))
+#elif defined(_MSC_VER)
+    #define ALIGNMENT __declspec(align(4))
+#endif
+
+#ifndef ISO_15675_UNUSED
+    #define ISO_15675_UNUSED(x) ((void)(x))
+#endif
+
+
+/******************************************************************************
+ * Includes
+******************************************************************************/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "lib_iqueue.h"
+
+/******************************************************************************
+ * Enumerations, structures & Variables
+******************************************************************************/
+
+/* --- CANTP Mode - Frame Type (ref:                     ) ----------------- */
+
+#ifndef CBUS_FR_FORMAT
+#define CBUS_FR_FORMAT
+typedef enum
+{
+    CBUS_FR_FRM_STD = 0x01,     /* Standard CANBUS */
+    CBUS_FR_FRM_FD  = 0x02      /* FD CANBUS       */
+} cbus_fr_format;
+#endif
+
+/* --- CANBus Mode [ID Type] (ref: iso15765-2 p.8) -------==---------------- */
+
+#ifndef CBUS_ID_TYPE
+#define CBUS_ID_TYPE
+typedef enum
+{
+    CBUS_ID_T_STANDARD = 0x04U, /* 11bits CAN Identifier */
+    CBUS_ID_T_EXTENDED = 0x08U  /* 29bits CAN Identifier */
+} cbus_id_type;
+#endif
+
+/* --- CANBus Frame (ref: iso15765-2 p.) ----------------------------------- */
+
+#ifndef CANBUS_FRAME
+#define CANBUS_FRAME
+typedef struct
+{
+    uint32_t id;        /* CAN Frame Id */
+    uint32_t id_type;   /* CAN Frame Id Type `cbus_id_type` */
+    uint16_t fr_format; /* CAN Frame Format `cbus_fr_format` */
+    uint16_t dlc;       /* Size of data */
+    uint8_t dt[64];     /* Actual data of the frame */
+} canbus_frame_t;
+#endif
+
+/* --- CANTP Addressing Mode (ref: iso15765-2 p.28) ------------------------ */
+
+typedef enum
+{
+    N_ADM_UNKN      = 0x00, /* Not defined */
+    N_ADM_NORMAL    = 0x14, /* Normal Mode */
+    N_ADM_FIXED     = 0x28, /* Extended Mode */
+    N_ADM_MIXED11   = 0x35, /* Mixed 11bits ID Mode */
+    N_ADM_EXTENDED  = 0x45, /* Fixed Mode */
+    N_ADM_MIXED29   = 0x59, /* Mixed 29bits ID Mode */
+    N_ADM_BMW       = 0x60, /* BMW */
+} addr_md;
+
+/* --- Protocol Control Information Type (ref: iso15765-2 p.17) ------------ */
+
+typedef enum
+{
+    N_PCI_T_SF = 0x00U, /* Single Frame µ¥Ö¡*/
+    N_PCI_T_FF = 0x01U, /* First Frame Ê×Ö¡*/
+    N_PCI_T_CF = 0x02U, /* Consecutive Frame Á¬ÐøÖ¡*/
+    N_PCI_T_FC = 0x03U, /* Flow Control Frame Á÷¿ØÖ¡*/
+    N_PCI_T_UN = 0xFF   /* Unknown */
+} pci_type;
+
+/* --- Network Target Address Type (ref: iso15765-2 p.9,29,30) ------------- */
+
+typedef enum
+{
+    N_TA_T_PHY  = 0x01, /* Physical */
+    N_TA_T_FUNC = 0x02  /* Functional */
+} ta_type;
+
+/* --- Message Type (ref: iso15765-2 p.8) ---------------------------------- */
+
+typedef enum
+{
+    N_MT_DIAG  = 0x00,  /* Diagnostics */
+    N_MT_RDIAG = 0x01   /* Remote Diagnostics */
+} mtype;
+
+/* --- FlowControl Parameters (ref: iso15765-2 p.--------------------------- */
+
+typedef enum
+{
+    N_ST_MIN = 0x00U,   /* SeparationTimeMin: the minimum time the sender should  wait between the transmissions of two CF N_PDUs */
+    N_BS     = 0x01U,   /* BlockSize: the max. number of N_PDUs the receiver allows the sender to send, before waiting for an authorization to continue transmission of the following N_PDUs */
+} fl_param;
+
+/* --- N rslts (ref: iso15765-2 p.10-11) ----------------------------------- */
+
+typedef enum
+{
+    N_OK            = 0x0000, /* service execution has completed successfully */
+    N_TIMEOUT_A     = 0x0001, /* when the timer N_Ar/N_As has passed its time-out * value N_Asmax / N_Armax; */
+    N_TIMEOUT_Bs    = 0x0002, /* when the timer N_Bs has passed its time-out value * N_Bsmax */
+    N_TIMEOUT_Cr    = 0x0003, /* when the timer N_Cr has passed its time-out value * N_Crmax */
+    N_WRG_SN        = 0x0004, /* upon reception of an unexpected sequence number * (PCI.SN) value */
+    N_INV_FS        = 0x0005, /* when an invalid or unknown FlowStatus value has * been received in a flow control(FC) N_PDU */
+    N_UNE_PDU       = 0x0006, /* upon reception of an unexpected protocol data unit; */
+    N_WFT_OVRN      = 0x0007, /* upon reception of flow control WAIT frame that * exceeds the maximum counter N_WFTmax */
+    N_BUFFER_OVFLW  = 0x0008, /* upon reception of a flow control (FC) N_PDU with * FlowStatus = OVFLW */
+    N_ERROR         = 0x0009, /* when an error has been detected by the network layer * and no other parameter value can be used to better * describe the error. */
+    N_IDLE          = 0x0010, /* service execution has completed successfully and not TXRX */
+    N_TX_BUSY       = 0x0011, /* service execution has completed successfully and TX pending */
+    N_RX_BUSY       = 0x0012, /* service execution has completed successfully and RX pending */
+    N_WRG_PARAM     = 0x0013, /* the service did not execute due to an undefined <Parameter> */
+    N_WRG_VALUE     = 0x0014, /* the service did not execute due to an out of range <Parameter_Value>; */
+    N_INV           = 0x0015, /* the service did not execute due to an invalid requested operation */
+    N_MISSING_CLB   = 0x0016, /* the service did not execute due to missing mandatory callback functions */
+    N_NULL          = 0x0017, /* the service has a null pointer (this should never happen) */
+    N_FC_TIMEOUT    = 0x0018, /* Flow Control Timeout. @n_timeouts.n_bs */
+    N_CF_TIMEOUT    = 0x0019, /* ConsecutiveFrame Timeout. @n_timeouts.n_cr */
+    N_CAN_DT_INV    = 0x0020, /* Invalid CAN Data Error */
+    N_UNE_FC        = 0x0021, /* FlowControl was received without being expected. */
+    N_UNE_CF        = 0x0022, /* ConsecutiveFrame was received without being expected. */
+    N_RCV_INT_SF    = 0x0023, /* Frames sequence was not correct. Service received a * single frame during a Multi-frame reception. */
+    N_RCV_INT_FF    = 0x0024, /* Frames sequence was not correct. Service received a * first frame during a Multi-frame reception. */
+    N_RCV_INT_FC    = 0x0025, /* ReceptionInterruptedWithFC */
+    N_INV_SEQ_NUM   = 0x0026, /* ConsecutiveFrame sequence number was invalid. */
+    N_UNS_WF        = 0x0027, /* Unsuported WaitFrame */
+    N_MAX_WF_REAC   = 0x0028, /* Maximum Wait Frames Reached */
+    N_INV_PDU       = 0x0029, /* PDU Conversion failed */
+    N_INV_REQ_SZ    = 0x0030, /* Invalid Request Size */
+    N_UNE_FC_STS    = 0x0031, /* Flow control status was invalid and/or unexpected. */
+    N_OVFLW         = 0x0032, /* Buffer Overflow. */
+} n_rslt;
+
+/* --- N_PCI_T_FC Status (ref: iso15765-2 p.8) ---------------------------- */
+
+typedef enum
+{
+    N_CONTINUE = 0x00U, /* continue to send, the authorization to continue */
+    N_WAIT     = 0x01U, /* the request to continue to wait */
+    N_OVERFLOW = 0x02U  /* buffer overflow, the indication that the number of bytes specified in the FirstFrame of the segmented message exceeds the number of bytes that can be stored in the buffer of the receiver entity */
+} flow_sts;
+
+/* --- dt I/O Stream Status (ref: iso15765-2 p.8) ------------------------ */
+
+typedef enum
+{
+    N_S_IDLE        = 0x00, /* Has to pending action */
+    N_S_RX_BUSY     = 0x02, /* Reception is in progress */
+    N_S_TX_BUSY     = 0x04, /* Transmission is in progress */
+    N_S_TX_READY    = 0x05, /* Transmission is ready to begin */
+    N_S_TX_WAIT_FC  = 0x10, /* Transmission is in progress and waits
+                             * for a Flow control frame */
+} stream_sts;
+
+/* --- Network Layer Timing PARAMs (ref: iso15765-2 p.) -------------------- */
+
+typedef struct ALIGNMENT
+{
+    uint32_t n_bs;  /* FlowControl N_PDU not received (lost, overwritten) on the
+             * sender side or preceding FirstFrame N_PDU or ConsecutiveFrame
+             * N_PDU not received(lost, overwritten) on the receiver side.
+             * Abort message transmission and issue N_USData.confirm with
+             * <N_Result> = N_TIMEOUT_Bs. */
+    uint32_t n_cr;  /* ConsecutiveFrame N_PDU not received (lost, overwritten) on
+             * the receiver side or preceding FC N_PDU not received(lost,
+             * overwritten) on the sender side. Abort message reception and issue
+             * N_USData.indication with <N_Result> = N_TIMEOUT_Cr */
+    uint32_t n_cs;
+} n_timeouts;
+
+/* --- Address information (ref: iso15765-2 p.) ---------------------------- */
+
+typedef struct ALIGNMENT
+{
+    uint8_t n_pr;       /* Network Address Priority */
+    uint8_t n_sa;       /* Network Source Address */
+    uint8_t n_ta;       /* Network Target Address */
+    uint8_t n_ae;       /* Network Address Extension */
+    ta_type n_tt;       /* Network Target Address type */
+} n_ai_t;
+
+/* --- Protocol control information (ref: iso15765-2 p.) ------------------- */
+
+typedef struct ALIGNMENT
+{
+    uint8_t  fs;     /* FlowStatus: whether the sending network entity can proceed with the message transmission 'flow_sts' */
+    uint8_t  bs;     /* BlockSize */
+    uint8_t  sn;     /* SequenceNumber: specify the order of the consecutive frames */
+    uint8_t  st;     /* SeparationTime: Requested separation time */
+    pci_type pt;     /* Type of the received pdu 'pci_type' */
+    uint16_t dl;     /* PCI data length (if 0 frame must be ignored) */
+} n_pci_t;
+
+/* --- Protocol dt unit (ref: iso15765-2 p.) ------------------------------- */
+
+typedef struct ALIGNMENT
+{
+    mtype    n_mt;     /* Message Type */
+    uint16_t sz;       /* Actual data size */
+    n_ai_t   n_ai;     /* Address information */
+    n_pci_t  n_pci;    /* Protocol control information */
+    uint8_t  dt[128];  /* Data Field */
+} n_pdu_t;
+
+/* --- N_USdt.cfm (ref: iso15765-2 p.6) ------------------------------------ */
+
+typedef struct ALIGNMENT
+{
+    n_ai_t  n_ai;    /* Address information */
+    n_pci_t n_pci;   /* Protocol control information */
+    n_rslt  rslt;    /* Result of the request */
+} n_cfm_t;
+
+/* --- N_FF.indn (ref: iso15765-2 p.6) ------------------------------------ */
+
+typedef struct ALIGNMENT
+{
+    cbus_fr_format fr_fmt;  /* CANBus Frame format */
+    n_ai_t         n_ai;    /* Address information */
+    n_pci_t        n_pci;   /* Protocol control information */
+    uint16_t       msg_sz;  /* Size of the message that will be received */
+} n_ff_indn_t;
+
+/* --- N_USData.request (ref: iso15765-2 p6.) ------------------------------ */
+
+typedef struct ALIGNMENT
+{
+    cbus_fr_format fr_fmt;                 /* CANBus Frame format */
+    n_ai_t         n_ai;                   /* Address information */
+    n_pci_t        n_pci;                  /* Protocol control information */
+    uint16_t       msg_sz;                 /* Message actual size */
+    uint8_t        msg[I15765_MSG_SIZE];   /* Message to be transmitted */
+} n_req_t;
+
+/* --- N_USdt.indn (ref: iso15765-2 p.7) ---------------------------------- */
+
+typedef struct ALIGNMENT
+{
+    cbus_fr_format fr_fmt;                  /* CANBus Frame format */
+    n_ai_t         n_ai;                    /* Address information */
+    n_pci_t        n_pci;                   /* Protocol control information */
+    n_rslt         rslt;                    /* Result of the reception */
+    uint16_t       msg_sz;                  /* Received message actual size */
+    uint8_t        msg[I15765_MSG_SIZE];    /* Received message data */
+} n_indn_t;
+
+typedef struct ALIGNMENT
+{
+    n_ai_t n_ai;        /* Address information. Not supported:the lib handles only 1 stream */
+    n_pci_t n_pci;      /* Protocol control information. Not supported:the lib handles only 1 stream) */
+    fl_param param;     /* Parameter to change */
+    uint8_t pval;       /* Value to set */
+} n_chg_param_req_t;
+
+typedef struct ALIGNMENT
+{
+    n_ai_t n_ai;        /* Address information. Not supported:the lib handles only 1 stream */
+    n_pci_t n_pci;      /* Protocol control information. Not supported: because the lib handles only 1 stream */
+    fl_param param;     /* Requested Parameter to change */
+    uint8_t pval;       /* Requested Value to set */
+    n_rslt rslt;        /* Result of the request */
+} n_chg_param_cfm_t;
+
+
+typedef enum
+{
+    N_INDN       = 0x01,   /* N_USData.indication */
+    N_FF_INDN    = 0x02,   /* N_USData_FF.indication */
+    N_CONF       = 0x03,   /* N_USData.confirm */
+    N_CHG_P_CONF = 0x04    /* N_ChangeParameter.confirm */
+} signal_tp;
+
+/* --- Callbacks  ---------------------------------------------------------- */
+
+typedef struct ALIGNMENT
+{
+    void (*indn)(n_indn_t *);                         /* Indication Callback: Will be fired when a reception is available or an error occured during the reception. */
+    void (*ff_indn)(n_ff_indn_t *);                   /* First Frame Indication Callback: Will be fired when a FF is received, giving back some useful information */
+    void (*cfm)(n_cfm_t *);                           /* This callback confirms to the higher layers that the requested  service has been carried out */
+    void (*cfg_cfm)(n_chg_param_cfm_t *);             /* This service confirms to the upper layer that the request to  change a specific protocol has been carried out */
+    void (*pdu_custom_pack)(n_pdu_t *, uint32_t *);   /* Custom CAN ID packing for 11bits ID. If assinged the default  packing will be skipped */
+    void (*pdu_custom_unpack)(n_pdu_t *, uint32_t *); /* Custom CAN ID uppacking for 11bits ID. If assinged the default uppacking will be skipped */
+    void (*on_error)(n_rslt);                         /* Will be fired in any occured error. */
+    uint32_t(*get_ms)();                              /* Time-source for the library in ms(required) */
+    uint8_t(*send_frame)                              /* Callback to assing the Network Layer. This callback will be fired when a transmission of a canbus frame is ready.*/
+    (                   
+        cbus_id_type,                                 /* - CANBus Frame ID Type [Standard or Extended] */
+        uint32_t,                                     /* - Frame ID */
+        cbus_fr_format,                               /* - Frame Type: [CLASSIC or FD]*/
+        uint8_t,                                      /* - Frame Data Length */
+        uint8_t *                                     /* - Frame Data Array */
+    );
+} n_callbacks_t;
+
+/* --- PDU Stream  --------------------------------------------------------- */
+
+typedef struct ALIGNMENT
+{
+    cbus_fr_format fr_fmt;              /* CANBus Frame format */
+    n_pdu_t        pdu;                 /* Keep information about the in/out frame in a PDU format */
+    uint8_t     cf_cnt;                 /* Current block sequence number (ConsecutiveFrame) */
+    uint8_t     wf_cnt;                 /* Current received wait flow control frames */
+    uint8_t     cfg_wf;                 /* Max supported Wait Flow Control frames */
+    uint8_t     stmin;                  /* Frames transmission rate */
+    uint8_t     cfg_bs;                 /* Max. supported block sequence (ConsecutiveFrame) */
+    stream_sts  sts;                    /* Stream status */
+    uint16_t    msg_sz;                 /* Actual message buffer size */
+    uint16_t    msg_pos;                /* Transmit message buffer position */
+    n_timeouts  last_upd;               /* Time keeper for timouts */
+    uint8_t     msg[I15765_MSG_SIZE];   /* Received/Transmit message buffer */
+} n_iostream_t;
+
+/* --- iso15765 timing configuration (ref: iso15765-2 p.25)----------------- */
+
+typedef struct ALIGNMENT
+{
+    uint8_t  stmin;  /* Default min. frame transmission separation */
+    uint8_t  bs;     /* Max. Block size during transmission */
+    uint8_t  wf;     /* Max. accepted Wait Requests from the FlowControl */
+    uint16_t n_bs;   /* Time until reception of the next FlowControl N_PDU */
+    uint16_t n_cr;   /* Time until reception of the next ConsecutiveFrame N_PDU */
+} n_config_t;
+
+/* --- iso15765 Handler  --------------------------------------------------- */
+
+typedef struct ALIGNMENT
+{
+    addr_md addr_md;                                              /* Selected address mode of the TP */
+    cbus_id_type fr_id_type;                                      /* CANBus frame Id Type */
+    n_iostream_t in;                                              /* Incoming data stream (reception) */
+    n_iostream_t out;                                             /* Outcoming data stream (transmission) */
+    n_pdu_t fl_pdu;                                               /* Flow control pdu */
+    n_callbacks_t clbs;                                           /* Callbacks */
+    n_config_t config;                                            /* Default configuration to be used. (timing etc) */
+    n_timeouts cfg_timeout;                                       /* Timeouts configuration */
+    iqueue_t inqueue;                                             /* Queue handler for the incoming canbus frames */
+    uint8_t inq_buf[I15765_QUEUE_ELMS * sizeof(canbus_frame_t)];  /* Queue buffer */
+} iso15765_t;
+
+/******************************************************************************
+* Declaration | Public Functions
+******************************************************************************/
+
+n_rslt iso15765_init(iso15765_t *instance);
+
+n_rslt iso15765_send(iso15765_t *instance, n_req_t *frame);
+
+n_rslt iso15765_enqueue(iso15765_t *instance, canbus_frame_t *frame);
+
+n_rslt iso15765_process(iso15765_t *instance);
+
+/******************************************************************************
+* EOF - NO CODE AFTER THIS LINE
+******************************************************************************/
+#endif