├── temp.lnt ├── tests ├── __init__.py ├── requirements.txt ├── main.c ├── common.py ├── ccp_config.h ├── testCcp.py ├── teststub.c ├── Makefile ├── ffi.py └── ccp_wrapper.py ├── working.lnt ├── local_tests.cmd ├── local_tests.sh ├── README.md ├── .travis.yml ├── loptions.lnt ├── project.lnt ├── inc └── ccp.h └── src └── ccp.c /temp.lnt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /working.lnt: -------------------------------------------------------------------------------- 1 | -e952 2 | -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | enum34 2 | -------------------------------------------------------------------------------- /local_tests.cmd: -------------------------------------------------------------------------------- 1 | cd tests 2 | make 3 | python -m unittest discover -v 4 | cd .. -------------------------------------------------------------------------------- /local_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/env sh 2 | cd tests 3 | make 4 | python -m unittest discover -v 5 | cd .. -------------------------------------------------------------------------------- /tests/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | 6 | int main(void) 7 | { 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## CAN Calibration Protocol for C 3 | 4 | 5 | [![Build Status](https://travis-ci.org/pySART/pyccp.svg)](https://travis-ci.org/pySART/cccp) 6 | -------------------------------------------------------------------------------- /tests/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import unittest 5 | import sys 6 | import enum 7 | 8 | from ffi import loadLibrary 9 | 10 | 11 | class BaseTest(unittest.TestCase): 12 | 13 | CLASS = None 14 | DLL = "" 15 | 16 | def setUp(self): 17 | self.obj = self.CLASS(loadLibrary(self.DLL)) 18 | 19 | def tearDown(self): 20 | self.obj.deinit() 21 | del self.obj 22 | 23 | -------------------------------------------------------------------------------- /tests/ccp_config.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(__CCCP_CONFIG_H) 3 | #define __CCCP_CONFIG_H 4 | 5 | #define CCP_STATION_ADDRESS (1) 6 | #define CCP_STATION_ID "description_of_test_ecu.a2l" 7 | #define CCP_MASTER_CANID 0xe01 8 | 9 | #define CCP_BUILD_TYPE CCP_DEBUG_BUILD 10 | #define CCP_SIMULATOR TRUE 11 | #define CCP_SIMULATED_MEMORY_SIZE (256 * 1024) 12 | 13 | #endif /* __CCCP_CONFIG_H */ 14 | 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | sudo: required 4 | 5 | script: 6 | - uname -s && python -V 7 | # - autoreconf -iv 8 | #- ./configure 9 | #- make check 10 | #- ls python -lRA 11 | #- cd ./python 12 | # - sudo python setup.py install 13 | # - sudo pip install -v 14 | - sudo -H pip install https://github.com/pySART/pyccp/archive/master.tar.gz 15 | #- cd .. 16 | - cd ./tests 17 | - make 18 | #- sudo pip install enum 19 | #- sudo pip install -r requirements.txt 20 | #- ls -lA 21 | #- python -c "import pyccp; print(dir(pyccp))" 22 | - python -m unittest discover -v 23 | 24 | os: 25 | - linux 26 | - osx 27 | 28 | compiler: 29 | - gcc 30 | - clang 31 | 32 | notifications: 33 | email: false 34 | 35 | #matrix: 36 | # allow_failures: 37 | # - os: osx 38 | 39 | -------------------------------------------------------------------------------- /loptions.lnt: -------------------------------------------------------------------------------- 1 | // 2 | -wlib(1) // Only report errors from the libraries 3 | 4 | // Output: One line, file info always, use full path names 5 | -hF1 6 | +ffn 7 | -"format=%(\q%f\q %l %C%) %t %n: %m" 8 | 9 | // Do not break lines 10 | -width(0,0) 11 | 12 | // And make sure no foreign includes change the format 13 | // or the output option 14 | +flm 15 | 16 | // Warn when trigraphs are used 17 | -ftg 18 | 19 | // Include files within library includes without full path 20 | +fdi 21 | 22 | // Don't stop make because of warnings 23 | -zero(99) 24 | 25 | // Make sure to make two passes (for better error messages) 26 | -passes(2) 27 | 28 | // Include directory where other option files *.lnt are located 29 | -iC:/LINT/ 30 | 31 | // Don't let -e options bleed to other source files 32 | -restore_at_end 33 | 34 | // Produce a summary of all produced messages 35 | -summary() 36 | -------------------------------------------------------------------------------- /tests/testCcp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from ctypes import create_string_buffer 5 | import unittest 6 | 7 | from common import BaseTest 8 | from ccp_wrapper import Ccp, LocalTransport 9 | 10 | from pyccp import ccp 11 | from pyccp.master import Master 12 | 13 | def sender(cmo): 14 | print("CMO: {0}".format(cmo)) 15 | 16 | class TestCcp(BaseTest): 17 | 18 | CLASS = Ccp 19 | DLL = "ccp" 20 | 21 | # def setUp(self): 22 | # super(TestCcp, self).setUp() 23 | # transport = LocalTransport(self.obj) 24 | # self.master = Master(transport) 25 | 26 | def runTest(self, func, *params): 27 | getattr(self.master, func)(*params) 28 | #result = str(self.master.transport.message) 29 | #self.assertEqual(result, expectedResult) 30 | 31 | def testConnect(self): 32 | #self.obj.setSendCallout(sender) 33 | transport = LocalTransport(self.obj) 34 | self.master = Master(transport) 35 | self.obj.init() 36 | self.runTest("connect", 0x7E1, 0x39) 37 | 38 | @unittest.skip 39 | def testInitWorksAsExpected(self): 40 | self.obj.init() 41 | self.assertEqual(self.obj.getMta(), 0) 42 | self.assertEqual(self.obj.getConnectionState(), 0) 43 | 44 | def testCallout(self): 45 | #self.obj.setSendCallout(sender) 46 | pass 47 | 48 | 49 | def main(): 50 | unittest.main() 51 | 52 | if __name__ == '__main__': 53 | main() 54 | 55 | -------------------------------------------------------------------------------- /tests/teststub.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include "ccp.h" 9 | 10 | 11 | void req(uint8_t cmd, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5); 12 | 13 | void response(Ccp_MessageObjectType const * cmoOut) 14 | { 15 | printf("Res: "); 16 | Ccp_DumpMessageObject(cmoOut); 17 | } 18 | 19 | uint16_t ctr = 1; 20 | Ccp_MessageObjectType cmo; 21 | 22 | static uint8_t buffer[256]; 23 | 24 | #define CANID (0x070e) 25 | 26 | #define Ccp_Connect() req(CONNECT, 0x01, 0x00, 0, 0, 0, 0) 27 | #define Ccp_GetCcpVersion() req(GET_CCP_VERSION, 2, 1, 0, 0, 0, 0) 28 | #define Ccp_SetMta(w) req(SET_MTA, 0, 0, (((w) & 0xff000000)) >> 24, (((w) & 0xff0000) >> 16), (((w) & 0xff00) >> 8), ((w) & 0xff)) 29 | 30 | int main(void) 31 | { 32 | Ccp_Init(); 33 | 34 | Ccp_SetSendCallout(&response); 35 | Ccp_Connect(); 36 | Ccp_GetCcpVersion(); 37 | // 38 | printf("&buffer => %p\n", buffer);printf("&buffer => %p\n", buffer); 39 | Ccp_SetMta((uint32_t)&buffer); 40 | 41 | return 0; 42 | } 43 | 44 | void req(uint8_t cmd, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) 45 | { 46 | memset(&cmo, '\x00', sizeof(Ccp_MessageObjectType)); 47 | cmo.canID = CANID; 48 | cmo.dlc = 0x08; 49 | cmo.data[0] = cmd; 50 | cmo.data[1] = ctr; 51 | ctr++; 52 | cmo.data[2] = b0; 53 | cmo.data[3] = b1; 54 | cmo.data[4] = b2; 55 | cmo.data[5] = b3; 56 | cmo.data[6] = b4; 57 | cmo.data[7] = b5; 58 | Ccp_DispatchCommand(&cmo); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | vpath %.c ../src 2 | 3 | #OBJDIR=. 4 | PROGRAMS = ccp 5 | 6 | ccp_SRC = ccp.c main.c 7 | ccp_OBJS = $(ccp_SRC:%.c=%.o) 8 | 9 | 10 | ifeq ($(OS),Windows_NT) 11 | TARGET=messaging.dll 12 | ccp_TARGET=ccp.dll 13 | EXT=.dll 14 | else 15 | UNAME_S := $(shell uname -s) 16 | ifeq ($(UNAME_S),Linux) 17 | TARGET=messaging.so 18 | ccp_TARGET=ccp.so 19 | EXT=.do 20 | endif 21 | ifeq ($(UNAME_S),Darwin) 22 | TARGET=messaging.dylib 23 | ccp_TARGET=ccp.dylib 24 | EXT=.dylib 25 | endif 26 | endif 27 | 28 | # TARGET = $(addsuffix $(EXT), messaging) 29 | 30 | INCLUDE= -I . -I ../inc 31 | CPPFLAGS += $(INCLUDE) 32 | CFLAGS += -g -fPIC #TODO: conditional: -fprofile-arcs -ftest-coverage --coverage 33 | LDFLAGS= -shared -fPIC #-Wl,-Map=ccp.map 34 | 35 | 36 | all: $(PROGRAMS) 37 | 38 | %.o: %.c 39 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $(notdir $@) 40 | 41 | 42 | ccp: $(ccp_OBJS) 43 | @echo Linking $(ccp_TARGET) 44 | $(CC) $(CFLAGS) -o $(ccp_TARGET) $(notdir $(ccp_OBJS)) $(LDFLAGS) 45 | 46 | #%.dll: 47 | # @echo Linking $(ccp_TARGET) 48 | # $(CC) $(CFLAGS) -o $(ccp_TARGET) $(notdir $(ccp_OBJS)) $(LDFLAGS) 49 | 50 | define DLL_template = 51 | @echo "Und nun? Linking" 52 | $(1): $$($(1)_OBJS) 53 | # $(CC) $(CFLAGS) -o $$($(1)_target) $notdir $$($(1)_OBJS) $(LDFLAGS) 54 | ALL_OBJS += $$($(1)_OBJS) 55 | endef 56 | 57 | #$(foreach prog,$(PROGRAMS),$(eval $(call DLL_template,$(prog)))) 58 | 59 | #$(PROGRAMS): 60 | # $(LINK.o) $^ $(LDLIBS) -o $@ 61 | 62 | clean: 63 | rm -vf *o *dll *exe 64 | #rm -f $(ALL_OBJS) $(PROGRAMS 65 | 66 | .PHONY: clean all 67 | 68 | # Target-specific variables. 69 | #gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1 70 | #gui.o: gui.h 71 | # $(COMPILE.c) $(OUTPUT_OPTION) $< 72 | -------------------------------------------------------------------------------- /tests/ffi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from ctypes import CDLL 5 | import sys 6 | 7 | def defaultChecker(result, func, args): 8 | return args 9 | 10 | class FFI(object): 11 | 12 | def __init__(self, dll = None, parent = None): 13 | if dll is None and parent is None: 14 | raise TypeError("dll and parent are None.") 15 | if dll is None: 16 | dll = parent.dll 17 | self.dll = dll 18 | self.loadFunctions() 19 | 20 | def functionFactory(self, library, functionName, resultType, argTypes, errorChecker = None): 21 | if not errorChecker: 22 | errorChecker = defaultChecker 23 | func = getattr(library, functionName) 24 | # These functions do not return 'STATUS_T'. 25 | func.errcheck = errorChecker 26 | func.restype = resultType #self.returnValue 27 | func.argtypes = argTypes 28 | return func 29 | 30 | def loadFunctions(self): 31 | for fun in self._functions_: 32 | addFunction = True 33 | if len(fun) == 3: 34 | functionName, resultType, argTypes = fun 35 | if argTypes == []: 36 | argTypes = None 37 | try: 38 | function = self.functionFactory(self.dll, functionName, resultType, argTypes) 39 | except AttributeError as e: 40 | print("Error: {0}.".format(str(e))) 41 | addFunction = False 42 | elif len(fun) == 4: 43 | functionName, resultType, argTypes, checker = fun 44 | if argTypes == []: 45 | argTypes = None 46 | try: 47 | function = self.functionFactory(self.dll, functionName, resultType, argTypes, checker) 48 | except AttributeError: 49 | print("Error: {0}.".format(str(e))) 50 | addFunction = False 51 | else: 52 | raise AttributeError("wrong length of function definition '{0}'.".format(fun)) 53 | if addFunction: 54 | setattr(self, functionName, function) 55 | 56 | def nullPointerChecker(result, func, args): 57 | if result is None: 58 | errorCode = win32api.GetLastError() 59 | if errorCode: 60 | errorMsg = win32api.FormatMessage(errorCode) 61 | raise ctypes.WinError(errorCode, "{0}: {1}".format(func.__name__, errorMsg)) 62 | return args 63 | 64 | def loadLibrary(name): 65 | pf = sys.platform 66 | if pf.startswith("win"): 67 | ext = "dll" 68 | elif pf.startswith("linux"): 69 | ext = "so" 70 | elif pf.startswith("darwin"): 71 | ext = "dylib" 72 | dll = CDLL("./{0}.{1}".format(name, ext)) 73 | return dll 74 | 75 | -------------------------------------------------------------------------------- /tests/ccp_wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from collections import namedtuple 5 | import ctypes 6 | from ctypes import Structure, Union, c_uint8, c_uint16, c_int32, c_uint32, c_void_p, c_float, c_char_p 7 | from ctypes import create_string_buffer, POINTER, byref, CFUNCTYPE, pointer, ARRAY, c_bool, byref 8 | import enum 9 | 10 | from ffi import FFI 11 | 12 | from pyccp import ccp 13 | 14 | 15 | CCP_LSDU_LEN = 8 16 | 17 | class Ccp_MessageObjectType(Structure): 18 | 19 | _pack_ = 1 20 | _fields = [ 21 | ("canID", c_uint32), 22 | ("dlc", c_uint8), 23 | ("data", c_uint8 * CCP_LSDU_LEN), 24 | ] 25 | 26 | 27 | SEND_FUNC = CFUNCTYPE(None, POINTER(Ccp_MessageObjectType)) 28 | 29 | def sender(cmo): 30 | print("CMO: {0}".format(cmo)) 31 | 32 | send_func = SEND_FUNC(sender) 33 | 34 | 35 | class Ccp(FFI): 36 | 37 | _functions_ = ( 38 | ("Ccp_GetConnectionState", c_uint16, []), 39 | ("Ccp_DispatchCommand", None, [POINTER(Ccp_MessageObjectType)]), 40 | ("Ccp_Init", None, []), 41 | ("Ccp_GetMta", c_uint32, []), 42 | ("Ccp_SetSendCallout", None, [SEND_FUNC]), 43 | ) 44 | 45 | def init(self): 46 | self.Ccp_Init() 47 | 48 | def deinit(self): 49 | pass 50 | 51 | def getConnectionState(self): 52 | return self.Ccp_GetConnectionState() 53 | 54 | def getMta(self): 55 | return self.Ccp_GetMta() 56 | 57 | def setSendCallout(self, callout): 58 | self.Ccp_SetSendCallout(SEND_FUNC(callout)) 59 | 60 | def dispatchCommand(self, command): 61 | self.Ccp_DispatchCommand(byref(command)) 62 | 63 | 64 | class LocalTransport(object): 65 | 66 | def __init__(self, dll): 67 | self.parent = None 68 | self.dll = dll 69 | 70 | def send(self, canID, b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0): 71 | self.message = ccp.CANMessageObject(canID, 8, bytearray((b0, b1, b2, b3, b4, b5, b6, b7))) 72 | # print("[LocalTransport] Sending: {}".format(self.message)) 73 | cmo = Ccp_MessageObjectType() 74 | cmo.canID = canID 75 | cmo.dlc = 8 76 | cmo.data = [b0, b1, b2, b3, b4, b5, b6, b7] 77 | #print(cmo.canID, cmo.dlc, cmo.data) 78 | self.dll.dispatchCommand(cmo) 79 | 80 | def receive(self, canID, b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0): 81 | self.message = ccp.CANMessageObject(canID, 8, bytearray((b0, b1, b2, b3, b4, b5, b6, b7))) 82 | self.parent.receive(self.message) 83 | 84 | def __str__(self): 85 | return "[Current Message]: {}".format(self.message) 86 | 87 | __repr__ = __str__ 88 | 89 | 90 | ## 91 | ##from ffi import loadLibrary 92 | ## 93 | ##dll = loadLibrary("ccp") 94 | ##print(dll) 95 | ## 96 | ##ccpDll = Ccp(dll) 97 | ##print(dir(ccpDll)) 98 | ##ccpDll.init() 99 | ##print(ccpDll.getMta()) 100 | ## 101 | 102 | -------------------------------------------------------------------------------- /project.lnt: -------------------------------------------------------------------------------- 1 | 2 | //au-misra1.lnt 3 | au-misra2.lnt 4 | 5 | -ftg // warn when trigraphs are used. 6 | 7 | +fdi 8 | +fcu // char is unsigned. 9 | +fie // enums are like integers. 10 | 11 | //+pragma(asm, off) 12 | +rw(asm, _ignore_init) 13 | -dasm=_ignore_init 14 | +rw(_to_brackets) 15 | //+rw(_ignore_init) 16 | 17 | //-function(exit, ASSERT) 18 | 19 | -zero(99) 20 | -passes(2) 21 | -restore_at_end 22 | +summary() 23 | 24 | -t4 // tabsize = four spaces. 25 | 26 | -w2 // Inhibit all informational messages (Nur fuer den Anfang!!!). 27 | 28 | -e129 29 | //-esym(e129,__intrinisic) 30 | +fem // to suppress Error 140 31 | 32 | +e429 // Custodial pointer 'Symbol' has not been freed or returned. 33 | -e537 // Repeated include file. 34 | +e578 // Declaration of symbol 'Symbol' hides 'Symbol'. 35 | -e621 // 36 | +e714 // Symbol '___' (___) not referenced 37 | +e715 // Symbol '___' (___) not referenced 38 | +e716 // while(1) 39 | -e717 // do ... while(0) 40 | +e722 // Suspicious use of ; 41 | +e725 // Expected positive indentation from 42 | +e728 // Symbol '___' (___) not explicitly initialized 43 | +e734 // Loss of precision (___) (___ bits to ___ bits) 44 | +e749 // local enumeration constant '___' (___) not referenced 45 | +e762 // Redundantly declared symbol '___' previously declared at ___ 46 | +e765 // external '___' (___) could be made static 47 | +e777 // Testing floats for equality 48 | +e795 // Conceivable disvision by 0 49 | +e801 // Use of goto is deprecated 50 | +e825 // Control flows into case/default 51 | +e832 // Parameter '___' not explicitly declared, int assumed 52 | +e766 // Header file not used in module. 53 | +e936 // old-style function definition for function '___' 54 | +e944 // ___argument for operator '___' always evaluates to ___ 55 | -e950 // Non-ANSI reserved word or construct: '___' 56 | +e952 // Parameter '___' (___) could be declared const 57 | +e953 // variable should declared as consts. 58 | +e954 // Pointer variable '___' (___) could be declared as pointing to c 59 | +e957 // Function '___' defined without a prototype in scope 60 | +e960 // Violates MISRA 2004 Required Rule ___, ___ 61 | +e961 // Violates MISRA 2004 Required Rule ___, ___ 62 | -e964 // Header file '___' not directly used in module '___' 63 | -e966 // Indirectly included header file '___' not used by module '___' 64 | +e971 // ??? unqualified char ??? 65 | +e1773 // Attempt to cast away const (or volatile) information. 66 | 67 | -esym(534, printf) 68 | 69 | -A 70 | -strong(A) 71 | -b 72 | 73 | -strong(B, _Bool, boolean) 74 | //-strong(B, boolean) 75 | 76 | // Slickedit 77 | -"format=%(%f %l:%C %)error %n: (%t -- %m)" // Messages will contain 78 | // file information (%f), the line number (%l), the 79 | // message number (%n), message type (%t) and message text (%m). 80 | // Notice that all messages are labeled 'error' but are then 81 | // followed by a type (such as Warning, Info, Note, etc.) 82 | 83 | -hF2 // Make sure we ALWAYS provide file information ('F') and use 2 84 | // lines (line in error plus message). 85 | 86 | -width(0) // don't break messages at any particular width 87 | +flm // make sure nobody can change the output format. 88 | /////////////////////// 89 | 90 | // -d__STDC_VERSION__=199901L 91 | 92 | //-d__IAR_SYSTEMS_ICC__ 93 | //-d__ICCHCS12__ 94 | 95 | //-dKOS_MEMORY_MAPPING=STD_ON 96 | 97 | -d__STDC__=1 98 | 99 | //-i"C:\Programme\IAR Systems\Embedded Workbench Evaluation 4.0\HCS12\inc" 100 | //+libdir("C:\Programme\IAR Systems\Embedded Workbench Evaluation 4.0\HCS12\inc") 101 | -i"..\inc" 102 | //+libh() 103 | +libclass(ansi) 104 | lib-w32.lnt // Win32 API options 105 | lib-win.lnt // Windows option 106 | //+compiler(search_actively_including_stack) 107 | -vf 108 | 109 | -wlib(1) 110 | -------------------------------------------------------------------------------- /inc/ccp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pySART - Simplified AUTOSAR-Toolkit for Python. 3 | * 4 | * (C) 2007-2016 by Christoph Schueler 6 | * 7 | * All Rights Reserved 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along 20 | * with this program; if not, write to the Free Software Foundation, Inc., 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 | * 23 | * s. FLOSS-EXCEPTION.txt 24 | */ 25 | 26 | #if !defined(__CCCP_H) 27 | #define __CCCP_H 28 | 29 | #include 30 | #include 31 | 32 | #define CCP_VERSION_MAJOR (2) 33 | #define CCP_VERSION_RELEASE (1) 34 | 35 | #define CCP_LSDU_LEN (8) 36 | 37 | #define CCP_DEBUG_BUILD (1) 38 | #define CCP_RELEASE_BUILD (2) 39 | 40 | 41 | /* 42 | ** Global Types. 43 | */ 44 | 45 | typedef enum tagCcp_CommandType { 46 | 47 | /* Mandatory Commands. */ 48 | CONNECT = 0x01, 49 | GET_CCP_VERSION = 0x1B, 50 | EXCHANGE_ID = 0x17, 51 | SET_MTA = 0x02, 52 | DNLOAD = 0x03, 53 | UPLOAD = 0x04, 54 | GET_DAQ_SIZE = 0x14, 55 | SET_DAQ_PTR = 0x15, 56 | WRITE_DAQ = 0x16, 57 | START_STOP = 0x06, 58 | DISCONNECT = 0x07, 59 | /* Optional Commands. */ 60 | GET_SEED = 0x12, 61 | UNLOCK = 0x13, 62 | DNLOAD_6 = 0x23, 63 | SHORT_UP = 0x0F, 64 | SELECT_CAL_PAGE = 0x11, 65 | SET_S_STATUS = 0x0C, 66 | GET_S_STATUS = 0x0D, 67 | BUILD_CHKSUM = 0x0E, 68 | CLEAR_MEMORY = 0x10, 69 | PROGRAM = 0x18, 70 | PROGRAM_6 = 0x22, 71 | MOVE = 0x19, 72 | TEST = 0x05, 73 | GET_ACTIVE_CAL_PAGE = 0x09, 74 | START_STOP_ALL = 0x08, 75 | DIAG_SERVICE = 0x20, 76 | ACTION_SERVICE = 0x21 77 | } Ccp_CommandType; 78 | 79 | typedef enum tagCcp_ReturnType { 80 | ACKNOWLEDGE = 0x00, 81 | DAQ_PROCESSOR_OVERLOAD = 0x01, 82 | COMMAND_PROCESSOR_BUSY = 0x10, 83 | DAQ_PROCESSOR_BUSY = 0x11, 84 | INTERNAL_TIMEOUT = 0x12, 85 | KEY_REQUEST = 0x18, 86 | SESSION_STATUS_REQUEST = 0x19, 87 | COLD_START_REQUEST = 0x20, 88 | CAL_DATA_INIT_REQUEST = 0x21, 89 | DAQ_LIST_INIT_REQUEST = 0x22, 90 | CODE_UPDATE_REQUEST = 0x23, 91 | UNKNOWN_COMMAND = 0x30, 92 | COMMAND_SYNTAX = 0x31, 93 | PARAMETER_OUT_OF_RANGE = 0x32, 94 | ACCESS_DENIED = 0x33, 95 | OVERLOAD = 0x34, 96 | ACCESS_LOCKED = 0x35, 97 | RESOURCE_FUNCTION_NOT_AVAILABLE = 0x36 98 | } Ccp_ReturnType; 99 | 100 | typedef enum tagCcp_DTOType { 101 | EVENT_MESSAGE = 254, 102 | COMMAND_RETURN_MESSAGE = 255 103 | } Ccp_DTOType; 104 | 105 | typedef enum tagCcp_ConnectionStateType { 106 | CCP_DISCONNECTED = 0, 107 | CCP_CONNECTED = 1 108 | } Ccp_ConnectionStateType; 109 | 110 | 111 | typedef enum tagCcp_SlaveAccessType { 112 | PGM = 0x40, 113 | DAQ = 0x02, 114 | CAL = 0x01 115 | } Ccp_SlaveAccessType; 116 | 117 | typedef struct tagCcp_MessageObjectType { 118 | uint32_t canID; 119 | uint8_t dlc; 120 | uint8_t data[CCP_LSDU_LEN]; 121 | } Ccp_MessageObjectType; 122 | 123 | typedef struct tagCcp_StationIDType { 124 | uint16_t len; 125 | const uint8_t name[]; 126 | } Ccp_StationIDType; 127 | 128 | typedef struct tagCcp_ODTEntryType { 129 | uint32_t address; 130 | uint8_t addressExtension; /* optional */ 131 | uint32_t length; /* optional */ 132 | } Ccp_ODTEntryType; 133 | 134 | typedef struct tagCcp_ODTType { 135 | /* NOTE: ODT sampling needs to be consistent, ie. atomic. */ 136 | Ccp_ODTEntryType element[7]; 137 | 138 | } Ccp_ODTType; 139 | 140 | typedef struct tagCcp_DAQListType { 141 | 142 | } Ccp_DAQListype; 143 | 144 | 145 | typedef void(*Ccp_SendCalloutType)(Ccp_MessageObjectType const * cmoOut); 146 | 147 | /* 148 | ** Global Functions. 149 | */ 150 | void Ccp_Init(void); 151 | void Ccp_DispatchCommand(Ccp_MessageObjectType const * cmoIn); 152 | void Ccp_SendCmo(Ccp_MessageObjectType const * cmoOut); 153 | 154 | 155 | Ccp_ConnectionStateType Ccp_GetConnectionState(void); 156 | uint32_t Ccp_GetMta0(void); 157 | uint32_t Ccp_GetMta1(void); 158 | void Ccp_SetSendCallout(Ccp_SendCalloutType * callout); 159 | void Ccp_DumpMessageObject(Ccp_MessageObjectType const * cmo); 160 | 161 | #if !defined(TRUE) 162 | #define TRUE (1) 163 | #endif 164 | 165 | #if !defined(FALSE) 166 | #define FALSE (0) 167 | #endif 168 | 169 | #include "ccp_config.h" 170 | 171 | #endif /* __CCCP_H */ 172 | 173 | -------------------------------------------------------------------------------- /src/ccp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pySART - Simplified AUTOSAR-Toolkit for Python. 3 | * 4 | * (C) 2007-2016 by Christoph Schueler 6 | * 7 | * All Rights Reserved 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along 20 | * with this program; if not, write to the Free Software Foundation, Inc., 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 | * 23 | * s. FLOSS-EXCEPTION.txt 24 | */ 25 | 26 | #include "ccp.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static Ccp_ConnectionStateType Ccp_ConnectionState = CCP_DISCONNECTED; 34 | void Ccp_WriteMemory(void * dest, void * src, uint16_t count); 35 | void Ccp_ReadMemory(void * dest, void * src, uint16_t count); 36 | 37 | /* 38 | Memory transfer addresses: 39 | --- 40 | - MTA0 is used by the commands DNLOAD, UPLOAD, DNLOAD_6, SELECT_CAL_PAGE, CLEAR_MEMORY, PROGRAM and PROGRAM_6. 41 | - MTA1 is used by the MOVE command 42 | */ 43 | static uint32_t Ccp_Mta0, Ccp_Mta1; 44 | static uint8_t Ccp_MtaExtension; 45 | 46 | static Ccp_SendCalloutType Ccp_SendCallout = NULL; 47 | static const Ccp_StationIDType Ccp_StationID = { sizeof(CCP_STATION_ID), CCP_STATION_ID }; 48 | 49 | #if defined(CCP_SIMULATOR) 50 | static uint8_t Ccp_SimulatedMemory[CCP_SIMULATED_MEMORY_SIZE]; 51 | #endif 52 | 53 | #define CCP_COMMAND (cmoIn->data[0]) 54 | 55 | #define DATA_IN(idx) (cmoIn->data[(idx)]) 56 | #define DATA_OUT(idx) (cmoOut->data[(idx)]) 57 | 58 | #define COUNTER_IN (cmoIn->data[1]) 59 | #define COUNTER_OUT (cmoOut->data[2]) 60 | 61 | 62 | void Ccp_Init(void) 63 | { 64 | Ccp_ConnectionState = CCP_DISCONNECTED; 65 | Ccp_Mta0 = Ccp_Mta1 = 0x000000000L; 66 | Ccp_MtaExtension = 0x00; 67 | #if defined(CCP_SIMULATOR) 68 | memcpy(&Ccp_SimulatedMemory, &Ccp_StationID.name, Ccp_StationID.len); 69 | #endif 70 | } 71 | 72 | void Ccp_SetDTOValues(Ccp_MessageObjectType * cmoOut, uint8_t type, uint8_t returnCode, 73 | uint8_t counter, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) 74 | { 75 | cmoOut->canID = CCP_MASTER_CANID; 76 | cmoOut->dlc = 8; 77 | DATA_OUT(0) = type; 78 | DATA_OUT(1) = returnCode; 79 | DATA_OUT(2) = counter; 80 | DATA_OUT(3) = b0; 81 | DATA_OUT(4) = b1; 82 | DATA_OUT(5) = b2; 83 | DATA_OUT(6) = b3; 84 | DATA_OUT(7) = b4; 85 | } 86 | 87 | 88 | void Ccp_SetUploadDTO(Ccp_MessageObjectType * cmoOut, uint8_t type, uint8_t returnCode, uint8_t counter) 89 | { 90 | cmoOut->canID = CCP_MASTER_CANID; 91 | cmoOut->dlc = 8; 92 | DATA_OUT(0) = type; 93 | DATA_OUT(1) = returnCode; 94 | DATA_OUT(2) = counter; 95 | /* Payload already set. */ 96 | } 97 | 98 | #define Ccp_AcknowledgedCRM(ctr, b0, b1, b2, b3, b4) Ccp_SetDTOValues(&cmoOut, COMMAND_RETURN_MESSAGE, ACKNOWLEDGE, ctr, b0, b1, b2, b3, b4) 99 | #define Ccp_AcknowledgedUploadCRM(ctr) Ccp_SetUploadDTO(&cmoOut, COMMAND_RETURN_MESSAGE, ACKNOWLEDGE, ctr) 100 | 101 | /** 102 | * Entry point, needs to be "wired" to CAN-Rx interrupt. 103 | * 104 | * @param cmoIn 105 | */ 106 | void Ccp_DispatchCommand(Ccp_MessageObjectType const * cmoIn) 107 | { 108 | Ccp_MessageObjectType cmoOut = {0}; 109 | uint16_t stationAddress; 110 | 111 | printf("Req: "); 112 | Ccp_DumpMessageObject(cmoIn); 113 | 114 | if (Ccp_ConnectionState == CCP_CONNECTED) { 115 | switch (CCP_COMMAND) { 116 | case GET_CCP_VERSION: 117 | Ccp_AcknowledgedCRM(COUNTER_IN, CCP_VERSION_MAJOR, CCP_VERSION_RELEASE,0, 0, 0); 118 | Ccp_SendCmo(&cmoOut); 119 | break; 120 | case EXCHANGE_ID: 121 | 122 | Ccp_AcknowledgedCRM(COUNTER_IN, 123 | Ccp_StationID.len, 124 | 0 , /* data type qualifier of slave device ID (optional and implementation specific). */ 125 | PGM | DAQ | CAL, /* TODO: config. */ 126 | 0, /* No protection. */ 127 | 0 128 | ); 129 | Ccp_SendCmo(&cmoOut); 130 | Ccp_Mta0 = (uint32_t)&Ccp_StationID.name; 131 | break; 132 | case SET_MTA: 133 | printf("SetMTA\n"); 134 | if (DATA_IN(2) == 0) { 135 | Ccp_Mta0 = (DATA_IN(4) << 24) | (DATA_IN(5) << 16) | (DATA_IN(6) << 8) | DATA_IN(7); 136 | } else if (DATA_IN(2) == 1) { 137 | Ccp_Mta1 = (DATA_IN(4) << 24) | (DATA_IN(5) << 16) | (DATA_IN(6) << 8) | DATA_IN(7); 138 | } else { 139 | /* Invalid MTA number.*/ 140 | break; 141 | } 142 | Ccp_MtaExtension = DATA_IN(3); 143 | 144 | Ccp_AcknowledgedCRM(COUNTER_IN, 0, 0,0, 0, 0); 145 | Ccp_SendCmo(&cmoOut); 146 | break; 147 | case DNLOAD: 148 | printf("Download\n"); 149 | Ccp_WriteMemory(&Ccp_Mta0, &DATA_IN(3), DATA_IN(2)); 150 | Ccp_Mta0 += DATA_IN(2); 151 | Ccp_AcknowledgedCRM( 152 | COUNTER_IN, 153 | Ccp_MtaExtension, 154 | (Ccp_Mta0 & 0xff000000) >> 24, 155 | (Ccp_Mta0 & 0x00ff0000) >> 16, 156 | (Ccp_Mta0 & 0x0000ff00) >> 8, 157 | Ccp_Mta0 & 0xff 158 | ); 159 | Ccp_SendCmo(&cmoOut); 160 | case UPLOAD: 161 | printf("Upload\n"); 162 | //Ccp_ReadMemory(&Ccp_Mta0, &DATA_OUT(3), DATA_IN(2)); 163 | Ccp_Mta0 += DATA_IN(2); 164 | Ccp_AcknowledgedUploadCRM(COUNTER_IN); 165 | break; 166 | } 167 | } else { 168 | /* 169 | ** Handle unconnected commands. 170 | */ 171 | if (CCP_COMMAND == CONNECT) { 172 | stationAddress = DATA_IN(2) | (DATA_IN(3) << 8); 173 | 174 | //printf("Connect [%u] [%u]\n", CCP_STATION_ADDRESS, stationAddress); 175 | if (CCP_STATION_ADDRESS == stationAddress) { 176 | Ccp_AcknowledgedCRM(COUNTER_IN, 0, 0, 0, 0, 0); 177 | Ccp_SendCmo(&cmoOut); 178 | Ccp_ConnectionState = CCP_CONNECTED; 179 | } else { 180 | /* "A CONNECT command to another station temporary disconnects the active station " */ 181 | //printf("Disconnecting...\n"); 182 | Ccp_ConnectionState = CCP_DISCONNECTED; 183 | } 184 | } 185 | } 186 | /* 187 | // Mandatory Commands. 188 | DNLOAD = 0x03, 189 | UPLOAD = 0x04, 190 | GET_DAQ_SIZE = 0x14, 191 | SET_DAQ_PTR = 0x15, 192 | WRITE_DAQ = 0x16, 193 | START_STOP = 0x06, 194 | DISCONNECT = 0x07 195 | */ 196 | } 197 | 198 | 199 | void Ccp_SendCmo(Ccp_MessageObjectType const * cmoOut) 200 | { 201 | /* 202 | ** 203 | ** Note: A callout is only needed for unit-testing. 204 | ** TODO: Conditional compilation (testing vs. "real-world"). 205 | ** 206 | */ 207 | if (Ccp_SendCallout) { 208 | (*Ccp_SendCallout)(cmoOut); 209 | } 210 | } 211 | 212 | void Ccp_SetSendCallout(Ccp_SendCalloutType * callout) 213 | { 214 | Ccp_SendCallout = callout; 215 | } 216 | 217 | 218 | /* 219 | ** 220 | ** Global Helper Functions. 221 | ** 222 | ** Note: These functions are only useful for unit-testing and debugging. 223 | ** 224 | */ 225 | Ccp_ConnectionStateType Ccp_GetConnectionState(void) 226 | { 227 | return Ccp_ConnectionState; 228 | } 229 | 230 | uint32_t Ccp_GetMta0(void) 231 | { 232 | return Ccp_Mta0; 233 | } 234 | 235 | uint32_t Ccp_GetMta1(void) 236 | { 237 | return Ccp_Mta1; 238 | } 239 | 240 | void Ccp_DumpMessageObject(Ccp_MessageObjectType const * cmo) 241 | { 242 | printf("%08X %u [%02X %02X %02X %02X %02X %02X %02X %02X]\n", cmo->canID, cmo->dlc, 243 | cmo->data[0], cmo->data[1], cmo->data[2], cmo->data[3], cmo->data[4], cmo->data[5], cmo->data[6], cmo->data[7] 244 | ); 245 | } 246 | 247 | void Ccp_WriteMemory(void * dest, void * src, uint16_t count) 248 | { 249 | #if defined(CCP_SIMULATOR) 250 | ptrdiff_t diff; 251 | printf("Dest: %p -- SimMem: %p\n", dest, &Ccp_SimulatedMemory); 252 | #else 253 | memcpy(dest, src, count); 254 | #endif 255 | } 256 | --------------------------------------------------------------------------------