diff --git a/CPP_Demo/xcp_cfg.h b/CPP_Demo/xcp_cfg.h index 7b4a0ce..2a88a7e 100644 --- a/CPP_Demo/xcp_cfg.h +++ b/CPP_Demo/xcp_cfg.h @@ -25,18 +25,32 @@ // #define XCP_PROTOCOL_LAYER_VERSION 0x0104 // PACKED_MODE, CC_START_STOP_SYNCH prepare - - - /*----------------------------------------------------------------------------*/ -/* Driver features */ +/* Adress, address extension coding */ -#define XCP_TRANSPORT_LAYER_TYPE XCP_TRANSPORT_LAYER_ETH // Enable ethernet specific commands +// Use addr_ext XCP_ADDR_EXT_ABS to indicate absulute addr format (ApplXcpGetBaseAddr()+(uint32_t)addr) +#define XCP_ENABLE_ABS_ADDRESSING +#define XCP_ADDR_EXT_ABS 0x01 // Absolute address format +// Use addr_ext XCP_ADDR_EXT_DYN to indicate relative addr format (event<<16)|offset #if OPTION_ENABLE_XCP_CLASS - #define XCP_ENABLE_DYN_ADDRESSING // Enable addr_ext=1 indicating relative addr format (event<<16)|offset + #define XCP_ENABLE_DYN_ADDRESSING + #define XCP_ADDR_EXT_DYN 0x02 // Relative address format #endif +// Use addr_ext XCP_ADDR_EXT_APP to indicate application specific addr format and use ApplXcpReadMemory and ApplXcpWriteMemory +// #define XCP_ENABLE_APP_ADDRESSING +// #define XCP_ADDR_EXT_APP 0x00 // Address format handled by application + +// Internally used address extensions +// Use addr_ext XCP_ADDR_EXT_A2L to indicate A2L upload memory space +#define XCP_ADDR_EXT_A2L 0xFD +// Use addr_ext XCP_ADDR_EXT_PTR to indicate gXcp.MtaPtr is valid +#define XCP_ADDR_EXT_PTR 0xFE + +// Undefined address extension +#define XCP_ADDR_EXT_UNDEFINED 0xFF // Undefined address extension + /*----------------------------------------------------------------------------*/ /* Protocol features */ diff --git a/CPP_Demo/xcptl_cfg.h b/CPP_Demo/xcptl_cfg.h index c990486..93f9993 100644 --- a/CPP_Demo/xcptl_cfg.h +++ b/CPP_Demo/xcptl_cfg.h @@ -44,7 +44,9 @@ // CTO size // Maximum size of a XCP command -#define XCPTL_MAX_CTO_SIZE 252 // must be mod 4 +#define XCPTL_MAX_CTO_SIZE (248) +// CRO_SHORT_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-8 should be %8==0 +// CRO_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-2 // DAQ transmit queue // Transmit queue size in segments, should at least be able to hold all data produced until the next call to HandleTransmitQueue diff --git a/C_Demo/main.c b/C_Demo/main.c index 32a1aba..93686d1 100644 --- a/C_Demo/main.c +++ b/C_Demo/main.c @@ -52,7 +52,7 @@ static BOOL createA2L() { static BOOL checkKeyboard() { if (_kbhit()) { switch (_getch()) { - case 27: XcpSendEvent(EVC_SESSION_TERMINATED, NULL, 0); return FALSE; // Stop on ESC + case 27: XcpSendEvent(PID_EV,EVC_SESSION_TERMINATED, NULL, 0); return FALSE; // Stop on ESC #if OPTION_ENABLE_DBG_PRINTS case '+': if (gDebugLevel < 5) gDebugLevel++; printf("\nDebuglevel = %u\n", gDebugLevel); break; case '-': if (gDebugLevel > 0) gDebugLevel--; printf("\nDebuglevel = %u\n", gDebugLevel); break; @@ -91,8 +91,7 @@ int main(int argc, char* argv[]) { } // Terminate task - sleepMs(1000); - cancel_thread(t2); + // @@@@ // Stop the XCP server XcpEthServerShutdown(); diff --git a/C_Demo/main.h b/C_Demo/main.h index f8a8e4b..0d22152 100644 --- a/C_Demo/main.h +++ b/C_Demo/main.h @@ -1,5 +1,6 @@ #pragma once + /* main.h */ /* | Code released into public domain, no attribution required @@ -40,12 +41,6 @@ #include #include #include - -#ifdef _WIN -#define M_PI 3.14159265358979323846 -#endif -#define M_2PI (M_PI*2) - #include #ifndef _WIN // Linux @@ -54,23 +49,19 @@ #include #include #include - #include -#include +//#include + #include #include - -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include #include -#define MAX_PATH 256 -#define BOOL int -#define FALSE 0 -#define TRUE 1 +//#define MAX_PATH 256 #else // Windows @@ -78,11 +69,24 @@ #include #include +#endif + + +#ifdef __cplusplus +#include +#include +#include +#include +#endif + #define BOOL int #define FALSE 0 #define TRUE 1 +#ifdef _WIN +#define M_PI 3.14159265358979323846 #endif +#define M_2PI (M_PI*2) #include "main_cfg.h" diff --git a/C_Demo/xcp_cfg.h b/C_Demo/xcp_cfg.h index bf9f564..a5bb28b 100644 --- a/C_Demo/xcp_cfg.h +++ b/C_Demo/xcp_cfg.h @@ -21,9 +21,28 @@ #define XCP_PROTOCOL_LAYER_VERSION 0x0104 // PACKED_MODE, CC_START_STOP_SYNCH prepare /*----------------------------------------------------------------------------*/ -/* Driver features */ +/* Adress, address extension coding */ -// #define XCP_ENABLE_DYN_ADDRESSING // Enable addr_ext=1 indicating relative addr format (event<<16)|offset +// Use addr_ext XCP_ADDR_EXT_ABS to indicate absulute addr format (ApplXcpGetBaseAddr()+(uint32_t)addr) +#define XCP_ENABLE_ABS_ADDRESSING +#define XCP_ADDR_EXT_ABS 0x01 // Absolute address format + +// Use addr_ext XCP_ADDR_EXT_DYN to indicate relative addr format (event<<16)|offset +// #define XCP_ENABLE_DYN_ADDRESSING +// #define XCP_ADDR_EXT_DYN 0x02 // Relative address format + +// Use addr_ext XCP_ADDR_EXT_APP to indicate application specific addr format and use ApplXcpReadMemory and ApplXcpWriteMemory +// #define XCP_ENABLE_APP_ADDRESSING +// #define XCP_ADDR_EXT_APP 0x00 // Address format handled by application + +// Internally used address extensions +// Use addr_ext XCP_ADDR_EXT_A2L to indicate A2L upload memory space +#define XCP_ADDR_EXT_A2L 0xFD +// Use addr_ext XCP_ADDR_EXT_PTR to indicate gXcp.MtaPtr is valid +#define XCP_ADDR_EXT_PTR 0xFE + +// Undefined address extension +#define XCP_ADDR_EXT_UNDEFINED 0xFF // Undefined address extension /*----------------------------------------------------------------------------*/ diff --git a/C_Demo/xcptl_cfg.h b/C_Demo/xcptl_cfg.h index a22c75b..97563d6 100644 --- a/C_Demo/xcptl_cfg.h +++ b/C_Demo/xcptl_cfg.h @@ -44,7 +44,9 @@ // CTO size // Maximum size of a XCP command -#define XCPTL_MAX_CTO_SIZE 252 // must be mod 4 +#define XCPTL_MAX_CTO_SIZE (248) +// CRO_SHORT_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-8 should be %8==0 +// CRO_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-2 // DAQ transmit queue // Transmit queue size in segments, should at least be able to hold all data produced until the next call to HandleTransmitQueue diff --git a/XCPlib/xcpAppl.c b/XCPlib/xcpAppl.c index 5a42a95..283284a 100644 --- a/XCPlib/xcpAppl.c +++ b/XCPlib/xcpAppl.c @@ -133,7 +133,7 @@ uint8_t baseAddrValid = 0; static int dump_phdr(struct dl_phdr_info* pinfo, size_t size, void* data) { - // DBG_PRINTF1("name=%s (%d segments)\n", pinfo->dlpi_name, pinfo->dlpi_phnum); + // DBG_PRINTF3("name=%s (%d segments)\n", pinfo->dlpi_name, pinfo->dlpi_phnum); // Application modules has no name if (0 == strlen(pinfo->dlpi_name)) { @@ -151,7 +151,7 @@ uint8_t* ApplXcpGetBaseAddr() { dl_iterate_phdr(dump_phdr, NULL); assert(baseAddr != NULL); baseAddrValid = 1; - DBG_PRINTF1("BaseAddr = %lX\n", (uint64_t)baseAddr); + DBG_PRINTF3("BaseAddr = %lX\n", (uint64_t)baseAddr); } return baseAddr; @@ -251,7 +251,7 @@ uint8_t* loadFile(const char* filename, uint32_t* length) { uint8_t* fileBuf = NULL; // file content uint32_t fileLen = 0; // file length - DBG_PRINTF1("Load %s\n", filename); + DBG_PRINTF3("Load %s\n", filename); #if defined(_LINUX) // Linux diff --git a/XCPlib/xcptl_cfg.h b/XCPlib/xcptl_cfg.h index d6e507d..5f8b925 100644 --- a/XCPlib/xcptl_cfg.h +++ b/XCPlib/xcptl_cfg.h @@ -52,8 +52,9 @@ // CTO size // Maximum size of a XCP command -#define XCPTL_MAX_CTO_SIZE 252 // must be mod 4 - +#define XCPTL_MAX_CTO_SIZE (248) +// CRO_SHORT_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-8 should be %8==0 +// CRO_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-2 diff --git a/XCPlite/main.c b/XCPlite/main.c index e2eb60b..521c523 100644 --- a/XCPlite/main.c +++ b/XCPlite/main.c @@ -104,7 +104,7 @@ int main() { if (!XcpEthServerStatus()) { printf("\nXCP Server failed\n"); break; } // Check if the XCP server is running if (!checkKeyboard()) { - XcpSendEvent(EVC_SESSION_TERMINATED, NULL, 0); + XcpSendEvent(PID_EV,EVC_SESSION_TERMINATED, NULL, 0); break; } } diff --git a/XCPlite/main.h b/XCPlite/main.h index f8a8e4b..0d22152 100644 --- a/XCPlite/main.h +++ b/XCPlite/main.h @@ -1,5 +1,6 @@ #pragma once + /* main.h */ /* | Code released into public domain, no attribution required @@ -40,12 +41,6 @@ #include #include #include - -#ifdef _WIN -#define M_PI 3.14159265358979323846 -#endif -#define M_2PI (M_PI*2) - #include #ifndef _WIN // Linux @@ -54,23 +49,19 @@ #include #include #include - #include -#include +//#include + #include #include - -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include #include -#define MAX_PATH 256 -#define BOOL int -#define FALSE 0 -#define TRUE 1 +//#define MAX_PATH 256 #else // Windows @@ -78,11 +69,24 @@ #include #include +#endif + + +#ifdef __cplusplus +#include +#include +#include +#include +#endif + #define BOOL int #define FALSE 0 #define TRUE 1 +#ifdef _WIN +#define M_PI 3.14159265358979323846 #endif +#define M_2PI (M_PI*2) #include "main_cfg.h" diff --git a/XCPlite/xcp_cfg.h b/XCPlite/xcp_cfg.h index d556aa2..c5b0a18 100644 --- a/XCPlite/xcp_cfg.h +++ b/XCPlite/xcp_cfg.h @@ -20,11 +20,30 @@ //#define XCP_PROTOCOL_LAYER_VERSION 0x0103 // GET_DAQ_CLOCK_MULTICAST, GET_TIME_CORRELATION_PROPERTIES #define XCP_PROTOCOL_LAYER_VERSION 0x0104 // PACKED_MODE, CC_START_STOP_SYNCH prepare + /*----------------------------------------------------------------------------*/ -/* Driver features */ +/* Adress, address extension coding */ + +// Use addr_ext XCP_ADDR_EXT_ABS to indicate absulute addr format (ApplXcpGetBaseAddr()+(uint32_t)addr) +#define XCP_ENABLE_ABS_ADDRESSING +#define XCP_ADDR_EXT_ABS 0x01 // Absolute address format + +// Use addr_ext XCP_ADDR_EXT_DYN to indicate relative addr format (event<<16)|offset +// #define XCP_ENABLE_DYN_ADDRESSING +// #define XCP_ADDR_EXT_DYN 0x02 // Relative address format + +// Use addr_ext XCP_ADDR_EXT_APP to indicate application specific addr format and use ApplXcpReadMemory and ApplXcpWriteMemory +// #define XCP_ENABLE_APP_ADDRESSING +// #define XCP_ADDR_EXT_APP 0x00 // Address format handled by application -// #define XCP_ENABLE_DYN_ADDRESSING // Enable addr_ext=1 indicating relative addr format (event<<16)|offset +// Internally used address extensions +// Use addr_ext XCP_ADDR_EXT_A2L to indicate A2L upload memory space +#define XCP_ADDR_EXT_A2L 0xFD +// Use addr_ext XCP_ADDR_EXT_PTR to indicate gXcp.MtaPtr is valid +#define XCP_ADDR_EXT_PTR 0xFE +// Undefined address extension +#define XCP_ADDR_EXT_UNDEFINED 0xFF // Undefined address extension /*----------------------------------------------------------------------------*/ /* Protocol features */ diff --git a/XCPlite/xcptl_cfg.h b/XCPlite/xcptl_cfg.h index d6e507d..1d6d769 100644 --- a/XCPlite/xcptl_cfg.h +++ b/XCPlite/xcptl_cfg.h @@ -52,9 +52,9 @@ // CTO size // Maximum size of a XCP command -#define XCPTL_MAX_CTO_SIZE 252 // must be mod 4 - - +#define XCPTL_MAX_CTO_SIZE (248) +// CRO_SHORT_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-8 should be %8==0 +// CRO_DOWNLOAD_MAX_SIZE = XCPTL_MAX_CTO_SIZE-2 diff --git a/src/A2L.c b/src/A2L.c index e2f501c..5ac186a 100644 --- a/src/A2L.c +++ b/src/A2L.c @@ -17,8 +17,8 @@ #include "A2L.h" static FILE* gA2lFile = NULL; -static uint16_t gA2lFixedEvent = XCP_INVALID_EVENT; -static uint16_t gA2lDefaultEvent = XCP_INVALID_EVENT; +static uint16_t gA2lFixedEvent = XCP_UNDEFINED_EVENT; +static uint16_t gA2lDefaultEvent = XCP_UNDEFINED_EVENT; static uint32_t gA2lMeasurements; static uint32_t gA2lParameters; @@ -35,7 +35,7 @@ static uint32_t gA2lConversions; static void mem_check(const char* name, int32_t type, uint8_t ext, uint32_t addr) { (void)type; (void)name; volatile uint8_t *p = ApplXcpGetPointer(ext,addr); - if (p==NULL) { DBG_PRINTF1("ERROR: memory address 0x%04X of variable %s not accessible !\n",addr,name); assert(0); } + if (p==NULL) { DBG_PRINTF3("ERROR: memory address 0x%04X of variable %s not accessible !\n",addr,name); assert(0); } volatile uint8_t b = *p; // if this leads to a memory protection error, check if address transformation from A2L to uint_8_p* transformation is correct } #endif @@ -308,9 +308,9 @@ static const char* getPhysMax(int32_t type, double factor, double offset) { BOOL A2lOpen(const char *filename, const char* projectName ) { - DBG_PRINTF1("\nCreate A2L %s\n", filename); + DBG_PRINTF3("\nCreate A2L %s\n", filename); gA2lFile = NULL; - gA2lFixedEvent = XCP_INVALID_EVENT; + gA2lFixedEvent = XCP_UNDEFINED_EVENT; gA2lMeasurements = gA2lParameters = gA2lTypedefs = gA2lInstances = gA2lConversions = gA2lComponents = 0; gA2lFile = fopen(filename, "w"); if (gA2lFile == 0) { @@ -343,10 +343,10 @@ void A2lCreate_MOD_PAR(uint32_t startAddr, uint32_t size, char *epk) { fprintf(gA2lFile, "EPK \"%s\"\n", epk); fprintf(gA2lFile, "ADDR_EPK 0x%08X\n", ApplXcpGetAddr((uint8_t*)epk)); fprintf(gA2lFile, gA2lMemorySegment, startAddr, size); - DBG_PRINTF1(" A2L MOD_PAR MEMORY_SEGMENT 1: 0x%08X %u\n", startAddr, size); + DBG_PRINTF3(" A2L MOD_PAR MEMORY_SEGMENT 1: 0x%08X %u\n", startAddr, size); fprintf(gA2lFile, "/end MOD_PAR\n\n"); #if OPTION_ENABLE_DBG_PRINTS - if (epk) DBG_PRINTF1(" A2L MOD_PAR EPK \"%s\" 0x%08X\n", epk, ApplXcpGetAddr((uint8_t*)epk)); + if (epk) DBG_PRINTF3(" A2L MOD_PAR EPK \"%s\" 0x%08X\n", epk, ApplXcpGetAddr((uint8_t*)epk)); #endif } @@ -417,7 +417,7 @@ void A2lCreate_ETH_IF_DATA(BOOL useTCP, const uint8_t* addr, uint16_t port) { fprintf(gA2lFile, gA2lIfDataEnd); - DBG_PRINTF1(" IF_DATA XCP_ON_%s, ip=%s, port=%u\n", prot, addrs, port); + DBG_PRINTF3(" IF_DATA XCP_ON_%s, ip=%s, port=%u\n", prot, addrs, port); } void A2lCreate_CAN_IF_DATA(BOOL useCANFD, uint16_t croId, uint16_t dtoId, uint32_t bitRate) { @@ -443,17 +443,17 @@ void A2lCreate_CAN_IF_DATA(BOOL useCANFD, uint16_t croId, uint16_t dtoId, uint32 fprintf(gA2lFile, gA2lIfDataEnd); - DBG_PRINTF1(" IF_DATA XCP_ON_CAN, CRO=%u, DTO=%u, BITRATE=%u\n", croId, dtoId, bitRate); + DBG_PRINTF3(" IF_DATA XCP_ON_CAN, CRO=%u, DTO=%u, BITRATE=%u\n", croId, dtoId, bitRate); } void A2lCreateMeasurement_IF_DATA() { assert(gA2lFile != NULL); - if (gA2lFixedEvent != XCP_INVALID_EVENT) { + if (gA2lFixedEvent != XCP_UNDEFINED_EVENT) { fprintf(gA2lFile, " /begin IF_DATA XCP /begin DAQ_EVENT FIXED_EVENT_LIST EVENT 0x%X /end DAQ_EVENT /end IF_DATA", gA2lFixedEvent); } - else if (gA2lDefaultEvent != XCP_INVALID_EVENT) { + else if (gA2lDefaultEvent != XCP_UNDEFINED_EVENT) { fprintf(gA2lFile, " /begin IF_DATA XCP /begin DAQ_EVENT VARIABLE DEFAULT_EVENT_LIST EVENT 0x%X /end DAQ_EVENT /end IF_DATA", gA2lDefaultEvent); } } @@ -487,11 +487,11 @@ uint16_t A2lGetFixedEvent() { } void A2lRstDefaultEvent() { - gA2lDefaultEvent = XCP_INVALID_EVENT; + gA2lDefaultEvent = XCP_UNDEFINED_EVENT; } void A2lRstFixedEvent() { - gA2lFixedEvent = XCP_INVALID_EVENT; + gA2lFixedEvent = XCP_UNDEFINED_EVENT; } @@ -706,7 +706,7 @@ void A2lClose() { fprintf(gA2lFile, "%s", gA2lFooter); fclose(gA2lFile); gA2lFile = NULL; - DBG_PRINTF1("A2L created: %u measurements, %u params, %u typedefs, %u components, %u instances, %u conversions\n\n", + DBG_PRINTF3("A2L created: %u measurements, %u params, %u typedefs, %u components, %u instances, %u conversions\n\n", gA2lMeasurements, gA2lParameters, gA2lTypedefs, gA2lComponents, gA2lInstances, gA2lConversions); } } diff --git a/src/dbg_print.h b/src/dbg_print.h index c2ec327..177422e 100644 --- a/src/dbg_print.h +++ b/src/dbg_print.h @@ -14,37 +14,45 @@ extern unsigned int gDebugLevel; #define DBG_LEVEL gDebugLevel -#define DBG_PRINTF_ERROR(format, ...) printf(format, __VA_ARGS__) +/* +1 - Error +2 - Warn +3 - Info +4 - Trace +5 - Debug +*/ + #define DBG_PRINTF(level, format, ...) if (DBG_LEVEL>=level) printf(format, __VA_ARGS__) -#define DBG_PRINTF1(format, ...) if (DBG_LEVEL>=1) printf(format, __VA_ARGS__) -#define DBG_PRINTF2(format, ...) if (DBG_LEVEL>=2) printf(format, __VA_ARGS__) +#define DBG_PRINTF_ERROR(format, ...) if (DBG_LEVEL>=1) printf(format, __VA_ARGS__) +#define DBG_PRINTF_WARNING(format, ...) if (DBG_LEVEL>=2) printf(format, __VA_ARGS__) #define DBG_PRINTF3(format, ...) if (DBG_LEVEL>=3) printf(format, __VA_ARGS__) #define DBG_PRINTF4(format, ...) if (DBG_LEVEL>=4) printf(format, __VA_ARGS__) +#define DBG_PRINTF5(format, ...) if (DBG_LEVEL>=5) printf(format, __VA_ARGS__) -#define DBG_PRINT_ERROR(format) printf(format) #define DBG_PRINT(level, format) if (DBG_LEVEL>=level) printf(format) -#define DBG_PRINT1(format) if (DBG_LEVEL>=1) printf(format) -#define DBG_PRINT2(format) if (DBG_LEVEL>=2) printf(format) +#define DBG_PRINT_ERROR(format) if (DBG_LEVEL>=1) printf(format) +#define DBG_PRINT_WARNING(format) if (DBG_LEVEL>=2) printf(format) #define DBG_PRINT3(format) if (DBG_LEVEL>=3) printf(format) #define DBG_PRINT4(format) if (DBG_LEVEL>=4) printf(format) +#define DBG_PRINT5(format) if (DBG_LEVEL>=5) printf(format) #else #undef DBG_LEVEL -#define DBG_PRINTF_ERROR(s, ...) // printf(s,__VA_ARGS__) #define DBG_PRINTF(level, s, ...) -#define DBG_PRINTF1(s, ...) -#define DBG_PRINTF2(s, ...) +#define DBG_PRINTF_ERROR(s, ...) // printf(s,__VA_ARGS__) +#define DBG_PRINTF_WARNING(s, ...) #define DBG_PRINTF3(s, ...) #define DBG_PRINTF4(s, ...) +#define DBG_PRINTF5(s, ...) -#define DBG_PRINT_ERROR(s, ...) // printf(s,__VA_ARGS__) #define DBG_PRINT(level, s, ...) -#define DBG_PRINT1(s, ...) -#define DBG_PRINT2(s, ...) +#define DBG_PRINT_ERROR(s, ...) // printf(s,__VA_ARGS__) +#define DBG_PRINT_WARNING(s, ...) #define DBG_PRINT3(s, ...) #define DBG_PRINT4(s, ...) +#define DBG_PRINT5(s, ...) #endif diff --git a/src/main.h b/src/main.h index 7ed8265..f8d6c49 100644 --- a/src/main.h +++ b/src/main.h @@ -1,5 +1,6 @@ #pragma once + /* main.h */ /* | Code released into public domain, no attribution required @@ -40,12 +41,6 @@ #include #include #include - -#ifdef _WIN -#define M_PI 3.14159265358979323846 -#endif -#define M_2PI (M_PI*2) - #include #ifndef _WIN // Linux @@ -54,23 +49,19 @@ #include #include #include - #include -#include +//#include + #include #include - -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include #include -#define MAX_PATH 256 -#define BOOL int -#define FALSE 0 -#define TRUE 1 +//#define MAX_PATH 256 #else // Windows @@ -78,12 +69,9 @@ #include #include -#define BOOL int -#define FALSE 0 -#define TRUE 1 - #endif + #ifdef __cplusplus #include #include @@ -91,5 +79,14 @@ #include #endif +#define BOOL int +#define FALSE 0 +#define TRUE 1 + +// #ifdef _WIN +// #define M_PI 3.14159265358979323846 +// #endif +// #define M_2PI (M_PI*2) + #include "main_cfg.h" diff --git a/src/platform.c b/src/platform.c index d563afe..2438f01 100644 --- a/src/platform.c +++ b/src/platform.c @@ -18,7 +18,6 @@ #include "platform.h" #include "dbg_print.h" - #if defined(_WIN) // Windows // Windows needs to link with Ws2_32.lib #pragma comment(lib, "ws2_32.lib") @@ -32,6 +31,10 @@ #ifdef _LINUX +#ifdef PLATFORM_ENABLE_KEYBOARD + +#include + int _getch() { struct termios oldt, newt; int ch; @@ -66,7 +69,7 @@ int _kbhit() { return 0; } - +#endif #endif @@ -104,7 +107,6 @@ void sleepMs(uint32_t ms) { #elif defined(_WIN) // Windows - void sleepNs(uint32_t ns) { uint64_t t1, t2; @@ -133,7 +135,7 @@ void sleepNs(uint32_t ns) { void sleepMs(uint32_t ms) { if (ms > 0 && ms < 10) { - DBG_PRINT_ERROR("WARNING: cannot precisely sleep less than 10ms!\n"); + DBG_PRINT_WARNING("WARNING: cannot precisely sleep less than 10ms!\n"); } Sleep(ms); } @@ -149,7 +151,7 @@ void sleepMs(uint32_t ms) { #if defined(_LINUX) -void mutexInit(MUTEX* m, int recursive, uint32_t spinCount) { +void mutexInit(MUTEX* m, BOOL recursive, uint32_t spinCount) { (void)spinCount; if (recursive) { pthread_mutexattr_t ma; @@ -169,7 +171,7 @@ void mutexDestroy(MUTEX* m) { #elif defined(_WIN) -void mutexInit(MUTEX* m, int recursive, uint32_t spinCount) { +void mutexInit(MUTEX* m, BOOL recursive, uint32_t spinCount) { (void) recursive; // Window critical sections are always recursive (void)InitializeCriticalSectionAndSpinCount(m,spinCount); @@ -190,17 +192,16 @@ void mutexDestroy(MUTEX* m) { #ifdef _LINUX -int socketStartup() { - - return 1; +BOOL socketStartup() { + return TRUE; } void socketCleanup() { - } -int socketOpen(SOCKET* sp, BOOL useTCP, BOOL nonBlocking, BOOL reuseaddr, BOOL timestamps) { +BOOL socketOpen(SOCKET* sp, BOOL useTCP, BOOL nonBlocking, BOOL reuseaddr, BOOL timestamps) { (void)nonBlocking; + (void)timestamps; // Create a socket *sp = socket(AF_INET, useTCP ?SOCK_STREAM:SOCK_DGRAM , 0); if (*sp < 0) { @@ -213,10 +214,10 @@ int socketOpen(SOCKET* sp, BOOL useTCP, BOOL nonBlocking, BOOL reuseaddr, BOOL t setsockopt(*sp, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); } - return 1; + return TRUE; } -int socketBind(SOCKET sock, uint8_t* addr, uint16_t port) { +BOOL socketBind(SOCKET sock, uint8_t* addr, uint16_t port) { // Bind the socket to any address and the specified port SOCKADDR_IN a; @@ -233,26 +234,29 @@ int socketBind(SOCKET sock, uint8_t* addr, uint16_t port) { return 0; } - return 1; + return TRUE; } -int socketShutdown(SOCKET sock) { +BOOL socketShutdown(SOCKET sock) { if (sock != INVALID_SOCKET) { shutdown(sock, SHUT_RDWR); } - return 1; + return TRUE; } -int socketClose(SOCKET *sp) { +BOOL socketClose(SOCKET *sp) { if (*sp != INVALID_SOCKET) { close(*sp); *sp = INVALID_SOCKET; } - return 1; + return TRUE; } + +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR + #ifndef __APPLE__ #include #else @@ -289,32 +293,29 @@ static BOOL GetMAC(char* ifname, uint8_t* mac) { BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr) { static uint32_t addr1 = 0; static uint8_t mac1[6] = { 0,0,0,0,0,0 }; +#ifdef DBG_LEVEL + char strbuf[64]; +#endif if (addr1 == 0) { struct ifaddrs *ifaddrs, *ifa; struct ifaddrs *ifa1 = NULL; - char strbuf[100]; if (-1 != getifaddrs(&ifaddrs)) { for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if ((NULL != ifa->ifa_addr) && (AF_INET == ifa->ifa_addr->sa_family)) { // IPV4 struct sockaddr_in* sa = (struct sockaddr_in*)(ifa->ifa_addr); if (0x100007f != sa->sin_addr.s_addr) { /* not 127.0.0.1 */ -#ifdef DBG_LEVEL - if (DBG_LEVEL >= 5) { - inet_ntop(AF_INET, &sa->sin_addr.s_addr, strbuf, sizeof(strbuf)); - printf(" %s: IPV4 = %s\n", ifa->ifa_name, strbuf); - } -#endif if (addr1 == 0) { addr1 = sa->sin_addr.s_addr; ifa1 = ifa; + break; } } } } - if (addr1 != 0) { + if (addr1 != 0 && ifa1!=NULL) { GetMAC(ifa1->ifa_name, mac1); #ifdef DBG_LEVEL - if (DBG_LEVEL >= 3) { + if (DBG_LEVEL >= 4) { inet_ntop(AF_INET, &addr1, strbuf, sizeof(strbuf)); printf(" Use IPV4 adapter %s with IP=%s, MAC=%02X-%02X-%02X-%02X-%02X-%02X for A2L info and clock UUID\n", ifa1->ifa_name, strbuf, mac1[0], mac1[1], mac1[2], mac1[3], mac1[4], mac1[5]); } @@ -335,10 +336,10 @@ BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr) { +#endif // PLATFORM_ENABLE_GET_LOCAL_ADDR #endif // _LINUX - #if defined(_WIN) uint32_t socketGetTimestampMode(uint8_t *clockType) { @@ -475,6 +476,7 @@ BOOL socketClose(SOCKET* sockp) { return TRUE; } +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR #include #pragma comment(lib, "IPHLPAPI.lib") @@ -507,15 +509,15 @@ BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr) { inet_pton(AF_INET, pAdapter->IpAddressList.IpAddress.String, &a); if (a!=0) { #ifdef DBG_LEVEL - DBG_PRINTF3(" Ethernet adapter %" PRIu32 ":", (uint32_t) pAdapter->Index); - //DBG_PRINTF3(" %s", pAdapter->AdapterName); - DBG_PRINTF3(" %s", pAdapter->Description); - DBG_PRINTF3(" %02X-%02X-%02X-%02X-%02X-%02X", pAdapter->Address[0], pAdapter->Address[1], pAdapter->Address[2], pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]); - DBG_PRINTF3(" %s", pAdapter->IpAddressList.IpAddress.String); - //DBG_PRINTF3(" %s", pAdapter->IpAddressList.IpMask.String); - //DBG_PRINTF3(" Gateway: %s", pAdapter->GatewayList.IpAddress.String); - //if (pAdapter->DhcpEnabled) DBG_PRINTF3(" DHCP"); - DBG_PRINT3("\n"); + DBG_PRINTF5(" Ethernet adapter %" PRIu32 ":", (uint32_t) pAdapter->Index); + //DBG_PRINTF5(" %s", pAdapter->AdapterName); + DBG_PRINTF5(" %s", pAdapter->Description); + DBG_PRINTF5(" %02X-%02X-%02X-%02X-%02X-%02X", pAdapter->Address[0], pAdapter->Address[1], pAdapter->Address[2], pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]); + DBG_PRINTF5(" %s", pAdapter->IpAddressList.IpAddress.String); + //DBG_PRINTF5(" %s", pAdapter->IpAddressList.IpMask.String); + //DBG_PRINTF5(" Gateway: %s", pAdapter->GatewayList.IpAddress.String); + //if (pAdapter->DhcpEnabled) DBG_PRINTF5(" DHCP"); + DBG_PRINT5("\n"); #endif if (addr1[0] == 0 ) { memcpy(addr1, (uint8_t*)&a, 4); @@ -537,6 +539,9 @@ BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr) { return FALSE; } +#endif // PLATFORM_ENABLE_GET_LOCAL_ADDR + + #endif // _WIN @@ -693,25 +698,25 @@ char* clockGetString(char* s, uint32_t l, uint64_t c) { BOOL clockInit() { - DBG_PRINT2("\nInit clock\n ("); + DBG_PRINT3("\nInit clock\n ("); #ifdef CLOCK_USE_UTC_TIME_NS - DBG_PRINT2("CLOCK_USE_UTC_TIME_NS,"); + DBG_PRINT3("CLOCK_USE_UTC_TIME_NS,"); #endif #ifdef CLOCK_USE_APP_TIME_US - DBG_PRINT2("CLOCK_USE_APP_TIME_US,"); + DBG_PRINT3("CLOCK_USE_APP_TIME_US,"); #endif #if CLOCK_TYPE == CLOCK_TAI - DBG_PRINT2("CLOCK_TYPE_TAI,"); + DBG_PRINT3("CLOCK_TYPE_TAI,"); #endif #if CLOCK_TYPE == CLOCK_REALTIME - DBG_PRINT2("CLOCK_TYPE_REALTIME,"); + DBG_PRINT3("CLOCK_TYPE_REALTIME,"); #endif - DBG_PRINT2(")\n"); + DBG_PRINT3(")\n"); sClock = 0; clock_getres(CLOCK_TYPE, >r); - DBG_PRINTF2("Clock resolution is %lds,%ldns!\n", gtr.tv_sec, gtr.tv_nsec); + DBG_PRINTF4("Clock resolution is %lds,%ldns!\n", gtr.tv_sec, gtr.tv_nsec); #ifndef CLOCK_USE_UTC_TIME_NS clock_gettime(CLOCK_TYPE, >s0); @@ -727,11 +732,11 @@ BOOL clockInit() time_t now = time(NULL); gettimeofday(&ptm, NULL); clock_gettime(CLOCK_TYPE, >s); - DBG_PRINTF2(" CLOCK_REALTIME=%lus time=%lu timeofday=%lu\n", gts.tv_sec, now, ptm.tv_sec); + DBG_PRINTF4(" CLOCK_REALTIME=%lus time=%lu timeofday=%lu\n", gts.tv_sec, now, ptm.tv_sec); t1 = clockGet(); sleepNs(100000); t2 = clockGet(); - DBG_PRINTF2(" +0us: %s\n", clockGetString(s, sizeof(s), t1)); - DBG_PRINTF2(" +100us: %s (%u)\n", clockGetString(s, sizeof(s), t2), (uint32_t)(t2 - t1)); - DBG_PRINT2("\n"); + DBG_PRINTF4(" +0us: %s\n", clockGetString(s, sizeof(s), t1)); + DBG_PRINTF4(" +100us: %s (%u)\n", clockGetString(s, sizeof(s), t2), (uint32_t)(t2 - t1)); + DBG_PRINT4("\n"); } #endif @@ -797,11 +802,11 @@ char* clockGetTimeString(char* str, uint32_t l, int64_t t) { BOOL clockInit() { - DBG_PRINT2("\nInit clock\n"); + DBG_PRINT3("\nInit clock\n"); #ifdef CLOCK_USE_UTC_TIME_NS - DBG_PRINT2(" CLOCK_USE_UTC_TIME_NS\n"); + DBG_PRINT3(" CLOCK_USE_UTC_TIME_NS\n"); #else - DBG_PRINT2(" CLOCK_USE_APP_TIME_US\n"); + DBG_PRINT3(" CLOCK_USE_APP_TIME_US\n"); #endif sClock = 0; @@ -862,9 +867,9 @@ BOOL clockInit() { clockGet(); #ifdef DBG_LEVEL - if (DBG_LEVEL >= 3) { + if (DBG_LEVEL >= 5) { #ifdef CLOCK_USE_UTC_TIME_NS - if (DBG_LEVEL >= 4) { + if (DBG_LEVEL >= 6) { struct tm tm; _gmtime64_s(&tm, (const __time64_t*)&time_s); printf(" Current time = %I64uus + %ums\n", time_s, time_ms); diff --git a/src/platform.h b/src/platform.h index 35883ff..a51ce6e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -5,9 +5,13 @@ */ +#define PLATFORM_ENABLE_GET_LOCAL_ADDR +#define PLATFORM_ENABLE_KEYBOARD + //------------------------------------------------------------------------------- // Keyboard +#ifdef PLATFORM_ENABLE_KEYBOARD #ifdef _LINUX #include @@ -16,6 +20,7 @@ extern int _getch(); extern int _kbhit(); #endif +#endif // PLATFORM_ENABLE_KEYBOARD //------------------------------------------------------------------------------- @@ -71,14 +76,14 @@ void mutexDestroy(MUTEX* m); typedef HANDLE tXcpThread; #define create_thread(h,t) *h = CreateThread(0, 0, t, NULL, 0, NULL) #define join_thread(h) WaitForSingleObject(h, INFINITE); -#define cancel_thread(h) { TerminateThread(h,0); WaitForSingleObject(h,1000); CloseHandle(h); } +#define terminate_thread(h) { TerminateThread(h,0); WaitForSingleObject(h,1000); CloseHandle(h); } #elif defined(_LINUX) // Linux typedef pthread_t tXcpThread; #define create_thread(h,t) pthread_create(h, NULL, t, NULL); #define join_thread(h) pthread_join(h,NULL); -#define cancel_thread(h) { pthread_detach(h); pthread_cancel(h); } +#define detach_thread(h) { pthread_detach(h); pthread_cancel(h); } #endif @@ -144,8 +149,9 @@ extern int16_t socketSend(SOCKET sock, const uint8_t* buffer, uint16_t bufferSiz extern int16_t socketSendTo(SOCKET sock, const uint8_t* buffer, uint16_t bufferSize, const uint8_t* addr, uint16_t port, uint64_t *time); extern BOOL socketShutdown(SOCKET sock); extern BOOL socketClose(SOCKET* sp); +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR extern BOOL socketGetLocalAddr(uint8_t* mac, uint8_t* addr); - +#endif //------------------------------------------------------------------------------- // Clock diff --git a/src/xcp.cpp b/src/xcp.cpp index d8f6c7e..3cd2034 100644 --- a/src/xcp.cpp +++ b/src/xcp.cpp @@ -130,7 +130,7 @@ void Xcp::event(uint16_t event) { } void Xcp::eventExt(uint16_t event, uint8_t* base) { - XcpEventExt(event, base); + XcpEventExt(event, base, 0); } void Xcp::eventAt(uint16_t event, uint64_t clock) { diff --git a/src/xcp.h b/src/xcp.h index ff355b9..4fb3044 100644 --- a/src/xcp.h +++ b/src/xcp.h @@ -96,20 +96,25 @@ #define CC_PROGRAM_MAX 0xC9 #define CC_PROGRAM_VERIFY 0xC8 -/*-------------------------------------------------------------------------*/ -/* XCP >= V1.1 Commands */ -# define CC_WRITE_DAQ_MULTIPLE 0xC7 /* XCP V1.1 specific commands */ +#if XCP_PROTOCOL_LAYER_VERSION >= 0x0101 +#define CC_WRITE_DAQ_MULTIPLE 0xC7 /* XCP V1.1 */ +#endif -/*-------------------------------------------------------------------------*/ -/* XCP >= V1.3 Commands */ -#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 -# define CC_TIME_CORRELATION_PROPERTIES 0xC6 /* XCP V1.3 specific commands */ +#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 +#define CC_TIME_CORRELATION_PROPERTIES 0xC6 /* XCP V1.3 */ #endif -/*-------------------------------------------------------------------------*/ -/* XCP >= V1.4 Commands */ +#if XCP_PROTOCOL_LAYER_VERSION >= 0x0104 +#define DTO_CTR_PROPERTIES 0xC5 /* XCP V1.4 */ +#endif + +/* 0xC1 ... 0xC4 not used */ + +#define CC_NOP 0xC1 /* No response, used for testing */ + +// Level 1 commands #if XCP_PROTOCOL_LAYER_VERSION >= 0x0104 -#define CC_LEVEL_1_COMMAND 0xC0 /* XCP V1.4 Level 1 Commands: */ +#define CC_LEVEL_1_COMMAND 0xC0 /* XCP V1.4 with sub commands */ #define CC_GET_VERSION 0x00 #define CC_SET_DAQ_LIST_PACKED_MODE 0x01 #define CC_GET_DAQ_LIST_PACKED_MODE 0x02 @@ -127,8 +132,10 @@ /*-------------------------------------------------------------------------*/ /* Command Return Codes */ +#define CRC_CMD_OK 0x00 #define CRC_CMD_SYNCH 0x00 #define CRC_CMD_PENDING 0x01 +#define CRC_CMD_IGNORED 0x02 #define CRC_CMD_BUSY 0x10 #define CRC_DAQ_ACTIVE 0x11 #define CRC_PRM_ACTIVE 0x12 @@ -200,7 +207,7 @@ #define CMB_BYTE_ORDER (0x01u<<0) #define CMB_ADDRESS_GRANULARITY (0x03u<<1) -#define CMB_SERVER_BLOCK_MODE (0x01u<<6) +#define CMB_SERVER_BLOCK_MODE (0x01u<<6) #define CMB_OPTIONAL (0x01u<<7) #define CMB_ADDRESS_GRANULARITY_BYTE (0<<1) @@ -221,15 +228,18 @@ // XCP states (low byte) */ #define SS_STORE_CAL_REQ ((uint16_t)0x0001) +#define SS_PAG_CFG_LOST ((uint16_t)0x0002) #define SS_STORE_DAQ_REQ ((uint16_t)0x0004) #define SS_CLEAR_DAQ_REQ ((uint16_t)0x0008) +#define SS_DAQ_CFG_LOST ((uint16_t)0x0010) +#define SS_UNUSED ((uint16_t)0x0020) #define SS_DAQ ((uint16_t)0x0040) #define SS_RESUME ((uint16_t)0x0080) // Internal states (high byte) */ #define SS_BLOCK_UPLOAD ((uint16_t)0x0100) /* Block upload in progress */ #define SS_LEGACY_MODE ((uint16_t)0x0200) /* XCP 1.3 legacy mode */ -#define SS_CMD_PENDING ((uint16_t)0x0800) /* async comand pending */ +#define SS_CMD_PENDING ((uint16_t)0x0800) /* async command pending */ #define SS_INITIALIZED ((uint16_t)0x8000) /* initialized */ #define SS_STARTED ((uint16_t)0x4000) /* started*/ #define SS_CONNECTED ((uint16_t)0x2000) /* connected */ @@ -238,14 +248,17 @@ /*-------------------------------------------------------------------------*/ /* Identifier Type (GET_ID) */ -#define IDT_ASCII 0 -#define IDT_ASAM_NAME 1 -#define IDT_ASAM_PATH 2 -#define IDT_ASAM_URL 3 -#define IDT_ASAM_UPLOAD 4 -#define IDT_ASAM_EPK 5 -#define IDT_ASAM_ECU 6 -#define IDT_ASAM_SYSID 7 +#define IDT_ASCII 0 +#define IDT_ASAM_NAME 1 +#define IDT_ASAM_PATH 2 +#define IDT_ASAM_URL 3 +#define IDT_ASAM_UPLOAD 4 +#define IDT_ASAM_EPK 5 +#define IDT_ASAM_ECU 6 +#define IDT_ASAM_SYSID 7 +#define IDT_VECTOR_MAPNAMES 0xDB +#define IDT_VECTOR_GET_A2LOBJECTS_FROM_ECU 0xA2 + /*-------------------------------------------------------------------------*/ /* Checksum Types (BUILD_CHECKSUM) */ @@ -305,7 +318,17 @@ /*-------------------------------------------------------------------------*/ /* SEGMENT_MODE (GET_SEGMENT_MODE, SET_SEGMENT_MODE) */ -#define SEGMENT_FLAG_FREEZE 0x01 /* */ +#define SEGMENT_FLAG_FREEZE 0x01 + +/*-------------------------------------------------------------------------*/ +/* SET_REQUEST_MODE */ + +#define SET_REQUEST_MODE_STORE_CAL 0x01 // Request to store calibration data +#define SET_REQUEST_MODE_STORE_DAQ_NORES 0x02 // Request to store DAQ configuration, no resume +#define SET_REQUEST_MODE_STORE_DAQ_RES 0x04 // Request to store DAQ configuration, resume enabled +#define SET_REQUEST_MODE_CLEAR_DAQ 0x08 // Request to clear DAQ configuration +#define SET_REQUEST_MODE_CLEAR_CAL_PAG_LOST 0x10 // Request to clear calibration page lost flag +#define SET_REQUEST_MODE_CLEAR_DAQ_LOST 0x20 // Request to clear DAQ configuration lost flag /*-------------------------------------------------------------------------*/ @@ -466,8 +489,6 @@ #define CRM_ERR CRM_BYTE(1) #define CRM_EVENTCODE CRM_BYTE(1) - - /* CONNECT */ #define CRO_CONNECT_LEN 2 #define CRO_CONNECT_MODE CRO_BYTE(1) @@ -479,12 +500,10 @@ #define CRM_CONNECT_PROTOCOL_VERSION CRM_BYTE(6) #define CRM_CONNECT_TRANSPORT_VERSION CRM_BYTE(7) - /* DISCONNECT */ #define CRO_DISCONNECT_LEN 1 #define CRM_DISCONNECT_LEN 1 - /* GET_STATUS */ #define CRO_GET_STATUS_LEN 1 #define CRM_GET_STATUS_LEN 6 @@ -492,12 +511,17 @@ #define CRM_GET_STATUS_PROTECTION CRM_BYTE(2) #define CRM_GET_STATUS_CONFIG_ID CRM_WORD(2) +/* USER_CMD */ +#define CRO_USER_CMD_LEN 4 +#define CRO_USER_CMD_SUBCOMMAND CRO_BYTE(1) +#define CRO_USER_CMD_PAR1 CRO_BYTE(2) +#define CRO_USER_CMD_PAR2 CRO_BYTE(3) + /* SYNCH */ #define CRO_SYNCH_LEN 1 #define CRM_SYNCH_LEN 2 #define CRM_SYNCH_RESULT CRM_BYTE(1) - /* GET_COMM_MODE_INFO */ #define CRO_GET_COMM_MODE_INFO_LEN 1 #define CRM_GET_COMM_MODE_INFO_LEN 8 @@ -507,7 +531,6 @@ #define CRM_GET_COMM_MODE_INFO_QUEUE_SIZE CRM_BYTE(6) #define CRM_GET_COMM_MODE_INFO_DRIVER_VERSION CRM_BYTE(7) - /* GET_ID */ #define CRO_GET_ID_LEN 2 #define CRO_GET_ID_TYPE CRO_BYTE(1) @@ -523,7 +546,6 @@ #define CRO_SET_REQUEST_CONFIG_ID CRO_WORD(1) #define CRM_SET_REQUEST_LEN 1 - /* GET_SEED */ #define CRO_GET_SEED_LEN 3 #define CRO_GET_SEED_MODE CRO_BYTE(1) @@ -532,7 +554,6 @@ #define CRM_GET_SEED_LENGTH CRM_BYTE(1) #define CRM_GET_SEED_DATA (&CRM_BYTE(2)) - /* UNLOCK */ #define CRO_UNLOCK_LEN 8 #define CRO_UNLOCK_LENGTH CRO_BYTE(1) @@ -540,14 +561,12 @@ #define CRM_UNLOCK_LEN 2 #define CRM_UNLOCK_PROTECTION CRM_BYTE(1) - /* SET_MTA */ #define CRO_SET_MTA_LEN 8 #define CRO_SET_MTA_EXT CRO_BYTE(3) #define CRO_SET_MTA_ADDR CRO_DWORD(1) #define CRM_SET_MTA_LEN 1 - /* UPLOAD */ #define CRO_UPLOAD_LEN 2 #define CRO_UPLOAD_SIZE CRO_BYTE(1) @@ -555,7 +574,6 @@ #define CRM_UPLOAD_LEN 1 /* +CRO_UPLOAD_SIZE */ #define CRM_UPLOAD_DATA (&CRM_BYTE(1)) - /* SHORT_UPLOAD */ #define CRO_SHORT_UPLOAD_LEN 8 #define CRO_SHORT_UPLOAD_SIZE CRO_BYTE(1) @@ -565,7 +583,6 @@ #define CRM_SHORT_UPLOAD_LEN 1u /* +CRO_SHORT_UPLOAD_SIZE */ #define CRM_SHORT_UPLOAD_DATA (&CRM_BYTE(1)) - /* BUILD_CHECKSUM */ #define CRO_BUILD_CHECKSUM_LEN 8 #define CRO_BUILD_CHECKSUM_SIZE CRO_DWORD(1) @@ -573,7 +590,6 @@ #define CRM_BUILD_CHECKSUM_TYPE CRM_BYTE(1) #define CRM_BUILD_CHECKSUM_RESULT CRM_DWORD(1) - /* DOWNLOAD */ #define CRO_DOWNLOAD_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-2)) #define CRO_DOWNLOAD_LEN 2 /* + CRO_DOWNLOAD_SIZE */ @@ -581,7 +597,6 @@ #define CRO_DOWNLOAD_DATA (&CRO_BYTE(2)) #define CRM_DOWNLOAD_LEN 1 - /* DOWNLOAD_NEXT */ #define CRO_DOWNLOAD_NEXT_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-2)) #define CRO_DOWNLOAD_NEXT_LEN 2 /* + size */ @@ -589,13 +604,11 @@ #define CRO_DOWNLOAD_NEXT_DATA (&CRO_BYTE(2)) #define CRM_DOWNLOAD_NEXT_LEN 1 - /* DOWNLOAD_MAX */ #define CRO_DOWNLOAD_MAX_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-1)) #define CRO_DOWNLOAD_MAX_DATA (&CRO_BYTE(1)) #define CRM_DOWNLOAD_MAX_LEN 1 - /* SHORT_DOWNLOAD */ #define CRO_SHORT_DOWNLOAD_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-8)) #define CRO_SHORT_DOWNLOAD_LEN 8 @@ -605,7 +618,6 @@ #define CRO_SHORT_DOWNLOAD_DATA (&CRO_BYTE(8)) #define CRM_SHORT_DOWNLOAD_LEN 1 /* +CRO_SHORT_UPLOAD_SIZE */ - /* MODIFY_BITS */ #define CRO_MODIFY_BITS_LEN 6 #define CRO_MODIFY_BITS_SHIFT CRO_BYTE(1) @@ -613,7 +625,6 @@ #define CRO_MODIFY_BITS_XOR CRO_WORD(2) #define CRM_MODIFY_BITS_LEN 1 - /* SET_CAL_PAGE */ #define CRO_SET_CAL_PAGE_LEN 4 #define CRO_SET_CAL_PAGE_MODE CRO_BYTE(1) @@ -621,7 +632,6 @@ #define CRO_SET_CAL_PAGE_PAGE CRO_BYTE(3) #define CRM_SET_CAL_PAGE_LEN 1 - /* GET_CAL_PAGE */ #define CRO_GET_CAL_PAGE_LEN 3 #define CRO_GET_CAL_PAGE_MODE CRO_BYTE(1) @@ -629,14 +639,12 @@ #define CRM_GET_CAL_PAGE_LEN 4 #define CRM_GET_CAL_PAGE_PAGE CRM_BYTE(3) - /* GET_PAG_PROCESSOR_INFO */ #define CRO_GET_PAG_PROCESSOR_INFO_LEN 1 #define CRM_GET_PAG_PROCESSOR_INFO_LEN 3 #define CRM_GET_PAG_PROCESSOR_INFO_MAX_SEGMENT CRM_BYTE(1) #define CRM_GET_PAG_PROCESSOR_INFO_PROPERTIES CRM_BYTE(2) - /* GET_SEGMENT_INFO */ #define CRO_GET_SEGMENT_INFO_LEN 5 #define CRO_GET_SEGMENT_INFO_MODE CRO_BYTE(1) @@ -651,7 +659,6 @@ #define CRM_GET_SEGMENT_INFO_ENCRYPTION CRM_BYTE(5) #define CRM_GET_SEGMENT_INFO_MAPPING_INFO CRM_DWORD(1) - /* GET_PAGE_INFO */ #define CRO_GET_PAGE_INFO_LEN 4 #define CRO_GET_PAGE_INFO_SEGMENT_NUMBER CRO_BYTE(2) @@ -660,20 +667,23 @@ #define CRM_GET_PAGE_INFO_PROPERTIES CRM_BYTE(1) #define CRM_GET_PAGE_INFO_INIT_SEGMENT CRM_BYTE(2) - /* SET_SEGMENT_MODE */ #define CRO_SET_SEGMENT_MODE_LEN 3 #define CRO_SET_SEGMENT_MODE_MODE CRO_BYTE(1) #define CRO_SET_SEGMENT_MODE_SEGMENT CRO_BYTE(2) #define CRM_SET_SEGMENT_MODE_LEN 1 - /* GET_SEGMENT_MODE */ #define CRO_GET_SEGMENT_MODE_LEN 3 #define CRO_GET_SEGMENT_MODE_SEGMENT CRO_BYTE(2) #define CRM_GET_SEGMENT_MODE_LEN 3 #define CRM_GET_SEGMENT_MODE_MODE CRM_BYTE(2) +/* SET_REQUEST */ +#define CRO_SET_REQUEST_LEN 4 +#define CRO_SET_REQUEST_MODE CRO_BYTE(1) +#define CRO_SET_REQUEST_ID CRO_WORD(1) +#define CRM_SET_REQUEST_LEN 1 /* COPY_CAL_PAGE */ #define CRO_COPY_CAL_PAGE_LEN 5 @@ -683,13 +693,11 @@ #define CRO_COPY_CAL_PAGE_DEST_PAGE CRO_BYTE(4) #define CRM_COPY_CAL_PAGE_LEN 1 - /* CLEAR_DAQ_LIST */ #define CRO_CLEAR_DAQ_LIST_LEN 4 #define CRO_CLEAR_DAQ_LIST_DAQ CRO_WORD(1) #define CRM_CLEAR_DAQ_LIST_LEN 1 - /* SET_DAQ_PTR */ #define CRO_SET_DAQ_PTR_LEN 6 #define CRO_SET_DAQ_PTR_DAQ CRO_WORD(1) @@ -697,7 +705,6 @@ #define CRO_SET_DAQ_PTR_IDX CRO_BYTE(5) #define CRM_SET_DAQ_PTR_LEN 1 - /* WRITE_DAQ */ #define CRO_WRITE_DAQ_LEN 8 #define CRO_WRITE_DAQ_BITOFFSET CRO_BYTE(1) @@ -706,7 +713,6 @@ #define CRO_WRITE_DAQ_ADDR CRO_DWORD(1) #define CRM_WRITE_DAQ_LEN 1 - /* WRITE_DAQ_MULTIPLE */ #define CRO_WRITE_DAQ_MULTIPLE_LEN(n) (2+(n)*8) #define CRO_WRITE_DAQ_MULTIPLE_NODAQ CRO_BYTE(1) @@ -716,7 +722,6 @@ #define CRO_WRITE_DAQ_MULTIPLE_EXT(i) CRO_BYTE(8 + (8*(i))) #define CRM_WRITE_DAQ_MULTIPLE_LEN 1 - /* SET_DAQ_LIST_MODE */ #define CRO_SET_DAQ_LIST_MODE_LEN 8 #define CRO_SET_DAQ_LIST_MODE_MODE CRO_BYTE(1) @@ -726,7 +731,6 @@ #define CRO_SET_DAQ_LIST_MODE_PRIORITY CRO_BYTE(7) #define CRM_SET_DAQ_LIST_MODE_LEN 6 - /* GET_DAQ_LIST_MODE */ #define CRO_GET_DAQ_LIST_MODE_LEN 4 #define CRO_GET_DAQ_LIST_MODE_DAQ CRO_WORD(1) @@ -736,7 +740,6 @@ #define CRM_GET_DAQ_LIST_MODE_PRESCALER CRM_BYTE(6) #define CRM_GET_DAQ_LIST_MODE_PRIORITY CRM_BYTE(7) - /* START_STOP_DAQ_LIST */ #define CRO_START_STOP_DAQ_LIST_LEN 4 #define CRO_START_STOP_DAQ_LIST_MODE CRO_BYTE(1) @@ -744,52 +747,42 @@ #define CRM_START_STOP_DAQ_LIST_LEN 2 #define CRM_START_STOP_DAQ_LIST_FIRST_PID CRM_BYTE(1) - /* START_STOP_SYNCH */ #define CRO_START_STOP_SYNCH_LEN 2 #define CRO_START_STOP_SYNCH_MODE CRO_BYTE(1) #define CRM_START_STOP_SYNCH_LEN 1 - /* GET_DAQ_CLOCK */ #define CRO_GET_DAQ_CLOCK_LEN 1 #define CRM_GET_DAQ_CLOCK_LEN 8 - #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 #define CRM_GET_DAQ_CLOCK_RES1 CRM_BYTE(1) // 1 #define CRM_GET_DAQ_CLOCK_TRIGGER_INFO CRM_BYTE(2) // 2 #define CRM_GET_DAQ_CLOCK_PAYLOAD_FMT CRM_BYTE(3) // 3 - #define CRM_GET_DAQ_CLOCK_TIME CRM_DWORD(1) // 4 #define CRM_GET_DAQ_CLOCK_SYNCH_STATE CRM_BYTE(8) // 8 - #define CRM_GET_DAQ_CLOCK_TIME64_LOW CRM_DWORD(1) // 4 #define CRM_GET_DAQ_CLOCK_TIME64_HIGH CRM_DWORD(2) // 8 #define CRM_GET_DAQ_CLOCK_SYNCH_STATE64 CRM_BYTE(12) // 12 #else #define CRM_GET_DAQ_CLOCK_TIME CRM_DWORD(1) // 4 #endif - -#define DAQ_CLOCK_PAYLOAD_FMT_SLV_32 (1<<0) -#define DAQ_CLOCK_PAYLOAD_FMT_SLV_64 (2<<0) -#define DAQ_CLOCK_PAYLOAD_FMT_ID (1<<6) +#define DAQ_CLOCK_PAYLOAD_FMT_SLV_32 (1<<0) +#define DAQ_CLOCK_PAYLOAD_FMT_SLV_64 (2<<0) +#define DAQ_CLOCK_PAYLOAD_FMT_ID (1<<6) /* GET_DAQ_CLOCK_MULTICAST */ #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 #define CRO_GET_DAQ_CLOC_MCAST_LEN 4 #define CRM_GET_DAQ_CLOCK_MCAST_LEN 8 - #define CRO_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER CRO_WORD(1) #define CRO_GET_DAQ_CLOCK_MCAST_COUNTER CRO_BYTE(4) - #define CRM_GET_DAQ_CLOCK_MCAST_TRIGGER_INFO CRM_BYTE(2) // 2 #define CRM_GET_DAQ_CLOCK_MCAST_PAYLOAD_FMT CRM_BYTE(3) // 3 - #define CRM_GET_DAQ_CLOCK_MCAST_TIME CRM_DWORD(1) // 4 #define CRM_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER CRM_WORD(4) // 8 #define CRM_GET_DAQ_CLOCK_MCAST_COUNTER CRM_BYTE(10) // 10 #define CRM_GET_DAQ_CLOCK_MCAST_SYNCH_STATE CRM_BYTE(11) // 11 - #define CRM_GET_DAQ_CLOCK_MCAST_TIME64_LOW CRM_DWORD(1) // 4 #define CRM_GET_DAQ_CLOCK_MCAST_TIME64_HIGH CRM_DWORD(2) // 8 #define CRM_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER64 CRM_WORD(6) // 12 @@ -805,7 +798,6 @@ #define CRM_READ_DAQ_EXT CRM_BYTE(3) #define CRM_READ_DAQ_ADDR CRM_DWORD(1) - /* GET_DAQ_PROCESSOR_INFO */ #define CRO_GET_DAQ_PROCESSOR_INFO_LEN 1 #define CRM_GET_DAQ_PROCESSOR_INFO_LEN 8 @@ -815,7 +807,6 @@ #define CRM_GET_DAQ_PROCESSOR_INFO_MIN_DAQ CRM_BYTE(6) #define CRM_GET_DAQ_PROCESSOR_INFO_DAQ_KEY_BYTE CRM_BYTE(7) - /* GET_DAQ_RESOLUTION_INFO */ #define CRO_GET_DAQ_RESOLUTION_INFO_LEN 1 #define CRM_GET_DAQ_RESOLUTION_INFO_LEN 8 @@ -827,7 +818,6 @@ #define CRM_GET_DAQ_RESOLUTION_INFO_TIMESTAMP_TICKS CRM_WORD(3) #define CRM_GET_DAQ_RESOLUTION_INFO_TIMESTAMP_TICKS_WRITE(ticks) CRM_WORD_WRITE(3, ticks) - /* GET_DAQ_LIST_INFO */ #define CRO_GET_DAQ_LIST_INFO_LEN 4 #define CRO_GET_DAQ_LIST_INFO_DAQ CRO_WORD(1) @@ -837,7 +827,6 @@ #define CRM_GET_DAQ_LIST_INFO_MAX_ODT_ENTRY CRM_BYTE(3) #define CRM_GET_DAQ_LIST_INFO_FIXED_EVENT CRM_WORD(2) - /* GET_DAQ_EVENT_INFO */ #define CRO_GET_DAQ_EVENT_INFO_LEN 4 #define CRO_GET_DAQ_EVENT_INFO_EVENT CRO_WORD(1) @@ -848,25 +837,20 @@ #define CRM_GET_DAQ_EVENT_INFO_TIME_CYCLE CRM_BYTE(4) #define CRM_GET_DAQ_EVENT_INFO_TIME_UNIT CRM_BYTE(5) #define CRM_GET_DAQ_EVENT_INFO_PRIORITY CRM_BYTE(6) - - #define DAQ_EVENT_PROPERTIES_DAQ 0x04 #define DAQ_EVENT_PROPERTIES_STIM 0x08 #define DAQ_EVENT_PROPERTIES_PACKED 0x10 #define DAQ_EVENT_PROPERTIES_EVENT_CONSISTENCY 0x80 - /* FREE_DAQ */ #define CRO_FREE_DAQ_LEN 1 #define CRM_FREE_DAQ_LEN 1 - /* ALLOC_DAQ */ #define CRO_ALLOC_DAQ_LEN 4 #define CRO_ALLOC_DAQ_COUNT CRO_WORD(1) #define CRM_ALLOC_DAQ_LEN 1 - /* ALLOC_ODT */ #define _CRO_ALLOC_ODT_LEN 3 #define _CRO_ALLOC_ODT_DAQ CRO_WORD(1) @@ -876,7 +860,6 @@ #define CRO_ALLOC_ODT_COUNT CRO_BYTE(4) #define CRM_ALLOC_ODT_LEN 1 - /* ALLOC_ODT_ENTRY */ #define CRO_ALLOC_ODT_ENTRY_LEN 6 #define CRO_ALLOC_ODT_ENTRY_DAQ CRO_WORD(1) @@ -884,7 +867,6 @@ #define CRO_ALLOC_ODT_ENTRY_COUNT CRO_BYTE(5) #define CRM_ALLOC_ODT_ENTRY_LEN 1 - /* PROGRAM_START */ #define CRO_PROGRAM_START_LEN 1 #define CRM_PROGRAM_START_LEN 7 @@ -894,14 +876,12 @@ #define CRM_PROGRAM_MIN_ST_PGM CRM_BYTE(5) #define CRM_PROGRAM_QUEUE_SIZE_PGM CRM_BYTE(6) - /* PROGRAM_CLEAR */ #define CRO_PROGRAM_CLEAR_LEN 8 #define CRO_PROGRAM_CLEAR_MODE CRO_BYTE(1) #define CRO_PROGRAM_CLEAR_SIZE CRO_DWORD(1) #define CRM_PROGRAM_CLEAR_LEN 1 - /* PROGRAM */ #define CRO_PROGRAM_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-2)) #define CRO_PROGRAM_LEN 2 /* + CRO_PROGRAM_SIZE */ @@ -909,19 +889,16 @@ #define CRO_PROGRAM_DATA (&CRO_BYTE(2)) #define CRM_PROGRAM_LEN 1 - /* PROGRAM RESET */ #define CRO_PROGRAM_RESET_LEN 1 #define CRM_PROGRAM_RESET_LEN 1 - /* GET_PGM_PROCESSOR_INFO*/ #define CRO_GET_PGM_PROCESSOR_INFO_LEN 1 #define CRM_GET_PGM_PROCESSOR_INFO_LEN 3 #define CRM_GET_PGM_PROCESSOR_INFO_PROPERTIES CRM_BYTE(1) #define CRM_GET_PGM_PROCESSOR_INFO_MAX_SECTOR CRM_BYTE(2) - /* GET_SECTOR_INFO */ #define CRO_PROGRAM_GET_SECTOR_INFO_LEN 3 #define CRO_PROGRAM_GET_SECTOR_INFO_MODE CRO_BYTE(1) @@ -933,13 +910,11 @@ #define CRM_PROGRAM_GET_SECTOR_SECTOR_INFO CRM_DWORD(1) #define CRM_PROGRAM_GET_SECTOR_SECTOR_INFO_WRITE(info) CRM_DWORD_WRITE(1, info) - /* PROGRAM_PREPARE */ #define CRO_PROGRAM_PREPARE_LEN 4 #define CRO_PROGRAM_PREPARE_SIZE CRO_WORD(1) #define CRM_PROGRAM_PREPARE_LEN 1 - /* PROGRAM_FORMAT */ #define CRO_PROGRAM_FORMAT_LEN 5 #define CRO_PROGRAM_FORMAT_COMPRESSION_METHOD CRO_BYTE(1) @@ -948,7 +923,6 @@ #define CRO_PROGRAM_FORMAT_ACCESS_METHOD CRO_BYTE(4) #define CRM_PROGRAM_FORMAT_LEN 1 - /* PROGRAM_NEXT */ #define CRO_PROGRAM_NEXT_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-2)) #define CRO_PROGRAM_NEXT_LEN 2 /* + size */ @@ -958,13 +932,11 @@ #define CRM_PROGRAM_NEXT_ERR_SEQUENCE CRM_BYTE(1) #define CRM_PROGRAM_NEXT_SIZE_EXPECTED_DATA CRM_BYTE(2) - /* PROGRAM_MAX */ #define CRO_PROGRAM_MAX_MAX_SIZE ((uint8_t)(XCPTL_MAX_CTO_SIZE-1)) #define CRO_PROGRAM_MAX_DATA (&CRO_BYTE(1)) #define CRM_PROGRAM_MAX_LEN 1 - /* PROGRAM_VERIFY */ #define CRO_PROGRAM_VERIFY_LEN 8 #define CRO_PROGRAM_VERIFY_MODE CRO_BYTE(1) @@ -972,7 +944,6 @@ #define CRO_PROGRAM_VERIFY_VALUE CRO_DWORD(1) #define CRM_PROGRAM_VERIFY_LEN 1 - /* GET_SERVER_ID */ /* #define CRO_GET_SERVER_ID_LEN 6 @@ -1004,19 +975,16 @@ #define CRO_SET_DAQ_ID_ID CRO_DWORD(1) #define CRM_SET_DAQ_ID_LEN 1 - /* SET_SERVER_PORT */ #define CRO_SET_SERVER_PORT_LEN 4 #define CRO_SET_SERVER_PORT_SUB_CODE CRO_BYTE(1) #define CRO_SET_SERVER_PORT_PORT CRO_WORD(1) #define CRM_SET_SERVER_PORT 1 - /* Level 1 commands */ #define CRO_LEVEL_1_COMMAND_LEN 2 #define CRO_LEVEL_1_COMMAND_CODE CRO_BYTE(1) - /* GET_VERSION */ #define CRO_GET_VERSION_LEN 2 #define CRM_GET_VERSION_LEN 6 @@ -1026,23 +994,19 @@ #define CRM_GET_VERSION_TRANSPORT_VERSION_MAJOR CRM_BYTE(4) #define CRM_GET_VERSION_TRANSPORT_VERSION_MINOR CRM_BYTE(5) - /* GET_DAQ_LIST_PACKED_MODE */ #define CRO_GET_DAQ_LIST_PACKED_MODE_DAQ CRM_WORD(1) #define CRM_GET_DAQ_LIST_PACKED_MODE_LEN 8 #define CRM_GET_DAQ_LIST_PACKED_MODE_MODE CRM_BYTE(2) - /* SET_DAQ_LIST_PACKED_MODE */ #define CRO_SET_DAQ_LIST_PACKED_MODE_DAQ CRO_WORD(1) #define CRO_SET_DAQ_LIST_PACKED_MODE_MODE CRO_BYTE(4) #define CRO_SET_DAQ_LIST_PACKED_MODE_TIMEMODE CRO_BYTE(5) #define CRO_SET_DAQ_LIST_PACKED_MODE_SAMPLECOUNT CRO_WORD(3) - #define DPM_TIMESTAMP_MODE_LAST 0 #define DPM_TIMESTAMP_MODE_FIRST 1 - /* TIME SYNCHRONIZATION PROPERTIES*/ #define CRO_TIME_SYNCH_PROPERTIES_LEN 6 #define CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES CRO_BYTE(1) @@ -1053,15 +1017,12 @@ #define TIME_SYNCH_SET_PROPERTIES_RESPONSE_FMT (3 << 0) #define TIME_SYNCH_SET_PROPERTIES_TIME_SYNCH_BRIDGE (3 << 2) #define TIME_SYNCH_SET_PROPERTIES_CLUSTER_ID (1 << 4) - #define TIME_SYNCH_RESPONSE_FMT_LEGACY 0 #define TIME_SYNCH_RESPONSE_FMT_TRIGGER_SUBSET 1 #define TIME_SYNCH_RESPONSE_FMT_TRIGGER_ALL 2 /* CRO_TIME_SYNCH_PROPERTIES_GET_PROPERTIES_REQUEST: */ -#define TIME_SYNCH_GET_PROPERTIES_GET_CLK_INFO (1 << 0) - - +#define TIME_SYNCH_GET_PROPERTIES_GET_CLK_INFO (1 << 0) #define CRM_TIME_SYNCH_PROPERTIES_LEN 8 #define CRM_TIME_SYNCH_PROPERTIES_SERVER_CONFIG CRM_BYTE(1) #define CRM_TIME_SYNCH_PROPERTIES_OBSERVABLE_CLOCKS CRM_BYTE(2) @@ -1098,7 +1059,6 @@ #define GRANDM_CLOCK_STATE_SYNCH_IN_PROGRESS (0 << 3) #define GRANDM_CLOCK_STATE_SYNCH (1 << 3) - /* CRM_TIME_SYNCH_PROPERTIES_CLOCK_INFO: */ #define CLOCK_INFO_SERVER (1<<0) #define CLOCK_INFO_GRANDM (1<<1) @@ -1124,7 +1084,6 @@ #define TRIG_INITIATOR_ECU_RESET_RELEASE 6UL #define TRIG_INITIATOR_RESERVED 7UL - #define TIME_OF_TS_SAMPLING_PROTOCOL_PROCESSOR 0UL #define TIME_OF_TS_SAMPLING_LOW_JITTER 1UL #define TIME_OF_TS_SAMPLING_PHY_TRANSMISSION 2UL @@ -1232,4 +1191,3 @@ typedef struct { #define TL_SLV_DETECT_STATUS_SLV_ID_EXT_RADAR_DATA (1<<0) #define TL_SLV_DETECT_STATUS_SLV_ID_EXT_XCP_ON_PCIE (1<<1) - diff --git a/src/xcpAppl.c b/src/xcpAppl.c index 362f434..c90d560 100644 --- a/src/xcpAppl.c +++ b/src/xcpAppl.c @@ -57,24 +57,24 @@ void ApplXcpStopDaq() { #else BOOL ApplXcpConnect() { - DBG_PRINT1("XCP connect\n"); + DBG_PRINT3("XCP connect\n"); return TRUE; } #if XCP_PROTOCOL_LAYER_VERSION >= 0x0104 BOOL ApplXcpPrepareDaq() { - DBG_PRINT1("XCP prepare DAQ\n"); + DBG_PRINT3("XCP prepare DAQ\n"); return TRUE; } #endif BOOL ApplXcpStartDaq() { - DBG_PRINT1("XCP start DAQ\n"); + DBG_PRINT3("XCP start DAQ\n"); return TRUE; } void ApplXcpStopDaq() { - DBG_PRINT1("XCP stop DAQ\n"); + DBG_PRINT3("XCP stop DAQ\n"); } #endif @@ -194,7 +194,7 @@ uint8_t baseAddrValid = 0; static int dump_phdr(struct dl_phdr_info* pinfo, size_t size, void* data) { - // DBG_PRINTF1("name=%s (%d segments)\n", pinfo->dlpi_name, pinfo->dlpi_phnum); + // DBG_PRINTF3("name=%s (%d segments)\n", pinfo->dlpi_name, pinfo->dlpi_phnum); // Application modules has no name if (0 == strlen(pinfo->dlpi_name)) { @@ -212,7 +212,7 @@ uint8_t* ApplXcpGetBaseAddr() { dl_iterate_phdr(dump_phdr, NULL); assert(baseAddr != NULL); baseAddrValid = 1; - DBG_PRINTF1("BaseAddr = %lX\n", (uint64_t)baseAddr); + DBG_PRINTF3("BaseAddr = %lX\n", (uint64_t)baseAddr); } return baseAddr; @@ -236,7 +236,7 @@ uint8_t* ApplXcpGetBaseAddr() return ((uint8_t*)((uint64_t)(&__base_addr_val)&0xffffffff00000000)); } -uint32_t ApplXcpGetAddr(uint8_t* p) +uint32_t ApplXcpGetAddr(const uint8_t* p) { return ((uint32_t)((uint64_t) p)& 0xffffffff); } @@ -311,7 +311,7 @@ uint8_t* ApplXcpGetPointer(uint8_t addr_ext, uint32_t addr) static int dump_phdr(struct dl_phdr_info* pinfo, size_t size, void* data) { - DBG_PRINTF1("0x%zX %s 0x%X %d %d %d %d 0x%X\n", + DBG_PRINTF3("0x%zX %s 0x%X %d %d %d %d 0x%X\n", pinfo->dlpi_addr, pinfo->dlpi_name, pinfo->dlpi_phdr, pinfo->dlpi_phnum, pinfo->dlpi_adds, pinfo->dlpi_subs, pinfo->dlpi_tls_modid, pinfo->dlpi_tls_data); @@ -324,7 +324,7 @@ static int dump_phdr(struct dl_phdr_info* pinfo, size_t size, void* data) // Application else { - DBG_PRINTF1("Application base addr = 0x%zx\n", pinfo->dlpi_addr); + DBG_PRINTF3("Application base addr = 0x%zx\n", pinfo->dlpi_addr); gModuleProperties[0].baseAddr = (uint8_t*) pinfo->dlpi_addr; } @@ -335,7 +335,7 @@ static int dump_phdr(struct dl_phdr_info* pinfo, size_t size, void* data) void ApplXcpInitBaseAddressList() { - DBG_PRINTF1("Module List:\n"); + DBG_PRINTF3("Module List:\n"); dl_iterate_phdr(dump_phdr, NULL); } @@ -419,7 +419,7 @@ uint8_t* loadFile(const char* filename, uint32_t* length) { uint8_t* fileBuf = NULL; // file content uint32_t fileLen = 0; // file length - DBG_PRINTF1("Load %s\n", filename); + DBG_PRINTF3("Load %s\n", filename); #if defined(_LINUX) // Linux diff --git a/src/xcpCanTl.c b/src/xcpCanTl.c index 150ae04..c3a8ed0 100644 --- a/src/xcpCanTl.c +++ b/src/xcpCanTl.c @@ -258,8 +258,8 @@ BOOL XcpTlHandleCommands(uint32_t timeout_ms) { BOOL XcpCanTlInit(BOOL useCANFD, uint32_t croId, uint32_t dtoId, uint32_t bitRate) { - XCP_DBG_PRINTF1("\nInit XCP on %s transport layer, croId=%u, dtoId=%u\n", useCANFD?"CANFD":"CAN",croId, dtoId); - XCP_DBG_PRINTF1(" QUEUE_SIZE=%u, %uKiB memory used\n", XCPTL_QUEUE_SIZE, (unsigned int)sizeof(gXcpTl) / 1024); + XCP_DBG_PRINTF3("\nInit XCP on %s transport layer, croId=%u, dtoId=%u\n", useCANFD?"CANFD":"CAN",croId, dtoId); + XCP_DBG_PRINTF3(" QUEUE_SIZE=%u, %uKiB memory used\n", XCPTL_QUEUE_SIZE, (unsigned int)sizeof(gXcpTl) / 1024); gXcpTl.useCANFD = useCANFD; gXcpTl.CroId = croId; diff --git a/src/xcpEthServer.c b/src/xcpEthServer.c index e2dfe21..2fc2148 100644 --- a/src/xcpEthServer.c +++ b/src/xcpEthServer.c @@ -37,9 +37,9 @@ static struct { // Threads tXcpThread DAQThreadHandle; - volatile int TransmitThreadRunning; + volatile BOOL TransmitThreadRunning; tXcpThread CMDThreadHandle; - volatile int ReceiveThreadRunning; + volatile BOOL ReceiveThreadRunning; } gXcpServer; @@ -56,12 +56,15 @@ BOOL XcpEthServerInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t int r = 0; if (gXcpServer.isInit) return FALSE; - DBG_PRINT1("\nStart XCP server\n"); + DBG_PRINT3("\nStart XCP server\n"); + // Init network sockets + if (!socketStartup()) return FALSE; + gXcpServer.TransmitThreadRunning = 0; gXcpServer.ReceiveThreadRunning = 0; - // Initialize XCP protocol layer + // Initialize XCP protocol layer if not already done XcpInit(); // Initialize XCP transport layer @@ -82,13 +85,14 @@ BOOL XcpEthServerInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t BOOL XcpEthServerShutdown() { if (gXcpServer.isInit) { - XcpDisconnect(); - cancel_thread(gXcpServer.DAQThreadHandle); - cancel_thread(gXcpServer.CMDThreadHandle); - - // Shutdown XCP transport layer - XcpTlShutdown(); + gXcpServer.ReceiveThreadRunning = FALSE; + gXcpServer.TransmitThreadRunning = FALSE; + XcpEthTlShutdown(); + join_thread(gXcpServer.CMDThreadHandle); + join_thread(gXcpServer.DAQThreadHandle); + gXcpServer.isInit = FALSE; + socketCleanup(); } return TRUE; } @@ -105,16 +109,16 @@ extern void* XcpServerReceiveThread(void* par) DBG_PRINT3("Start XCP CMD thread\n"); // Receive XCP unicast commands loop - gXcpServer.ReceiveThreadRunning = 1; - for (;;) { - if (!XcpTlHandleCommands(XCPTL_TIMEOUT_INFINITE)) { // Timeout Blocking + gXcpServer.ReceiveThreadRunning = TRUE; + while (gXcpServer.ReceiveThreadRunning) { + if (!XcpEthTlHandleCommands(XCPTL_TIMEOUT_INFINITE)) { // Timeout Blocking + DBG_PRINT_ERROR("ERROR: XcpTlHandleCommands failed!\n"); break; // error -> terminate thread } } - gXcpServer.ReceiveThreadRunning = 0; + gXcpServer.ReceiveThreadRunning = FALSE; - DBG_PRINT_ERROR("ERROR: XcpTlHandleCommands failed!\n"); - DBG_PRINT_ERROR("ERROR: XcpServerReceiveThread terminated!\n"); + DBG_PRINT3("XCP receive thread terminated!\n"); return 0; } @@ -132,8 +136,8 @@ extern void* XcpServerTransmitThread(void* par) DBG_PRINT3("Start XCP DAQ thread\n"); // Transmit loop - gXcpServer.TransmitThreadRunning = 1; - for (;;) { + gXcpServer.TransmitThreadRunning = TRUE; + while (gXcpServer.TransmitThreadRunning) { // Wait for transmit data available, time out at least for required flush cycle if (!XcpTlWaitForTransmitData(XCPTL_QUEUE_FLUSH_CYCLE_MS)) XcpTlFlushTransmitBuffer(); // Flush after timerout to keep data visualization going @@ -146,9 +150,9 @@ extern void* XcpServerTransmitThread(void* par) } } // for (;;) - gXcpServer.TransmitThreadRunning = 0; + gXcpServer.TransmitThreadRunning = FALSE; - DBG_PRINT_ERROR("XCP DAQ thread terminated!\n"); + DBG_PRINT3("XCP transmit thread terminated!\n"); return 0; } diff --git a/src/xcpEthTl.c b/src/xcpEthTl.c index fa07713..5e33bbe 100644 --- a/src/xcpEthTl.c +++ b/src/xcpEthTl.c @@ -17,16 +17,12 @@ #include "dbg_print.h" #include "xcpLite.h" -#ifdef XCPTL_ENABLE_SELF_TEST -#include "A2L.h" -#endif - // Parameter checks #if XCPTL_TRANSPORT_LAYER_HEADER_SIZE != 4 #error "Transportlayer supports only 4 byte headers!" #endif -#if ((XCPTL_MAX_CTO_SIZE&0x03) != 0) -#error "XCPTL_MAX_CTO_SIZE should be aligned to 4!" +#if ((XCPTL_MAX_CTO_SIZE&0x07) != 0) +#error "XCPTL_MAX_CTO_SIZE should be aligned to 8!" #endif #if ((XCPTL_MAX_DTO_SIZE&0x03) != 0) #error "XCPTL_MAX_DTO_SIZE should be aligned to 4!" @@ -60,61 +56,48 @@ typedef struct { static struct { + // Generic transport layer + int32_t lastError; + int (*sendCallback)(uint16_t msgLen, const uint8_t* msgBuf); // Callback to send a message to the application + uint16_t SegmentSize; // Maximum size of a XCP transportlayer segment + uint16_t lastCroCtr; // Last CRO command receive object message message counter received + uint16_t ctr; // next DAQ DTO data transmit message packet counter + + // Transmit segment queue + tXcpMessageBuffer queue[XCPTL_QUEUE_SIZE]; + uint32_t queue_rp; // rp = read index + uint32_t queue_len; // rp+len = write index (the next free entry), len=0 ist empty, len=XCPTL_QUEUE_SIZE is full +#if defined(_WIN) // Windows + HANDLE queue_event; + uint64_t queue_event_time; +#endif + tXcpMessageBuffer* msg_ptr; // current incomplete or not fully commited segment + MUTEX Mutex_Queue; + + // Ethernet SOCKET Sock; #ifdef XCPTL_ENABLE_TCP SOCKET ListenSock; #endif - +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR uint8_t ServerMac[6]; +#endif uint8_t ServerAddr[4]; uint16_t ServerPort; BOOL ServerUseTCP; BOOL blockingRx; - uint8_t MasterAddr[4]; uint16_t MasterPort; BOOL MasterAddrValid; - int32_t lastError; - - // Maximum size of a XCP transportlayer segment - uint16_t SegmentSize; - - // Transmit segment queue - tXcpMessageBuffer queue[XCPTL_QUEUE_SIZE]; - uint32_t queue_rp; // rp = read index - uint32_t queue_len; // rp+len = write index (the next free entry), len=0 ist empty, len=XCPTL_QUEUE_SIZE is full -#if defined(_WIN) // Windows - HANDLE queue_event; - uint64_t queue_event_time; -#endif - tXcpMessageBuffer* msg_ptr; // current incomplete or not fully commited segment - - // CTO command transfer object counter - uint16_t lastCroCtr; // Last CRO command receive object message message counter received - - // CRM,DTO message counter - uint16_t ctr; // next DAQ DTO data transmit message packet counter - // Multicast #ifdef XCPTL_ENABLE_MULTICAST tXcpThread MulticastThreadHandle; SOCKET MulticastSock; #endif - MUTEX Mutex_Queue; - -#ifdef XCPTL_ENABLE_SELF_TEST - uint32_t last_queue_len; // DAQ data bytes writen by last handleTransmitQueue - uint32_t last_bytes_written; // DAQ data bytes writen by last handleTransmitQueue - uint64_t total_bytes_written; // Total DAQ data bytes writen -#endif - } gXcpTl; -#ifdef XCPTL_ENABLE_SELF_TEST -static uint16_t gXcpTl_test_event = XCP_INVALID_EVENT; -#endif #if defined XCPTL_ENABLE_TCP && defined XCPTL_ENABLE_UDP #define isTCP() (gXcpTl.ListenSock != INVALID_SOCKET) @@ -131,39 +114,12 @@ static uint16_t gXcpTl_test_event = XCP_INVALID_EVENT; static int handleXcpMulticastCommand(int n, tXcpCtoMessage* p, uint8_t* dstAddr, uint16_t dstPort); #endif -//------------------------------------------------------------------------------ -#ifdef XCPTL_ENABLE_SELF_TEST - -void XcpEthTlCreateXcpEvents() { - gXcpTl_test_event = XcpCreateEvent("XCP", 0, 0, 0, 0); -} - -void XcpEthTlCreateA2lDescription() { - - // Measurements - A2lSetDefaultEvent(gXcpTl_test_event); - A2lCreateMeasurement(gXcpTl.total_bytes_written, "XCP total bytes written"); - A2lCreateMeasurement(gXcpTl.last_bytes_written, "bytes written by queue handler"); - A2lCreateMeasurement(gXcpTl.last_queue_len, "queue level before queue handler"); - A2lCreateMeasurement(gXcpTl.queue_len, "XCP queue level"); - - // Create a group for the measurements (optional) - A2lMeasurementGroup("XCP", 4, - "gXcpTl.total_bytes_written","gXcpTl.last_bytes_written","gXcpTl.last_queue_len","gXcpTl.queue_len"); -} - -uint64_t XcpEthTlGetBytesWritten() { - return gXcpTl.total_bytes_written; -} - -#endif - //------------------------------------------------------------------------------ // Transmit a UDP datagramm or TCP segment (contains multiple XCP DTO messages or a single CRM message (len+ctr+packet+fill)) // Must be thread safe, because it is called from CMD and from DAQ thread // Returns -1 on would block, 1 if ok, 0 on error -static int sendDatagram(const uint8_t *data, uint16_t size, const uint8_t* addr, uint16_t port) { +static int sendEthDatagram(const uint8_t *data, uint16_t size, const uint8_t* addr, uint16_t port) { int r; @@ -262,11 +218,6 @@ static void XcpTlInitTransmitQueue() { getSegmentBuffer(); mutexUnlock(&gXcpTl.Mutex_Queue); assert(gXcpTl.msg_ptr); -#ifdef XCPTL_ENABLE_SELF_TEST - gXcpTl.last_queue_len = 0; - gXcpTl.last_bytes_written = 0; - gXcpTl.total_bytes_written = 0; -#endif } // Transmit all completed and fully commited UDP frames @@ -278,10 +229,6 @@ int32_t XcpTlHandleTransmitQueue( void ) { tXcpMessageBuffer* b = NULL; int32_t n = 0; -#ifdef XCPTL_ENABLE_SELF_TEST - gXcpTl.last_queue_len = gXcpTl.queue_len; -#endif - for (;;) { for (uint32_t i = 0; i < max_loops; i++) { @@ -299,7 +246,14 @@ int32_t XcpTlHandleTransmitQueue( void ) { assert(b->size!=0); // Send this frame - int r = sendDatagram(&b->msg[0], b->size, NULL, 0); + int r; + if (gXcpTl.sendCallback != NULL) { + r = gXcpTl.sendCallback(b->size, &b->msg[0]); + } + else { + // Send the frame (UDP or TCP) + r = sendEthDatagram(&b->msg[0], b->size, NULL, 0); + } if (r == (-1)) { // would block b = NULL; break; @@ -322,16 +276,6 @@ int32_t XcpTlHandleTransmitQueue( void ) { } // for (ever) -#ifdef XCPTL_ENABLE_SELF_TEST - if (n > 0) { - gXcpTl.last_bytes_written = n; - gXcpTl.total_bytes_written += n; - if (gXcpTl.last_bytes_written > 0 && gXcpTl_test_event != XCP_INVALID_EVENT) { - XcpEvent(gXcpTl_test_event); // Test event, trigger every time the queue is emptied - } - } -#endif - return n; // Ok, queue empty now } @@ -433,6 +377,7 @@ void XcpTlWaitForTransmitQueueEmpty() { // Transmit XCP response or event packet // No error handling in protocol layer +// Must be thread save, if XcpPrint used, XcpCommand is never called from multiple threads // If transmission fails, tool times out, retries or take appropriate action // Note: CANape cancels measurement, when answer to GET_DAQ_CLOCK times out void XcpTlSendCrm(const uint8_t* packet, uint16_t packet_size) { @@ -456,7 +401,12 @@ void XcpTlSendCrm(const uint8_t* packet, uint16_t packet_size) { msg_size = packet_size; msg.dlc = (uint16_t)msg_size; msg_size = (uint16_t)(msg_size + XCPTL_TRANSPORT_LAYER_HEADER_SIZE); - r = sendDatagram((uint8_t*)&msg.dlc, msg_size, NULL, 0); + if (gXcpTl.sendCallback != NULL) { + r = gXcpTl.sendCallback(msg_size, (uint8_t*)&msg); + } + else { + r = sendEthDatagram((uint8_t*)&msg.dlc, msg_size, NULL, 0); + } } mutexUnlock(&gXcpTl.Mutex_Queue); if (r == 1) return; // ok @@ -467,7 +417,7 @@ void XcpTlSendCrm(const uint8_t* packet, uint16_t packet_size) { XcpTlCommitTransmitBuffer(handle, TRUE /* flush */); } else { // Buffer overflow - // @@@@ Todo + // Ignore, handled by tool } #else @@ -481,7 +431,7 @@ void XcpTlSendCrm(const uint8_t* packet, uint16_t packet_size) { memcpy(p.packet, packet, packet_size); r = sendDatagram((uint8_t*)&p, (uint16_t)(packet_size + XCPTL_TRANSPORT_LAYER_HEADER_SIZE), NULL, 0); if (r==(-1)) { // Would block - // @@@@ Todo + // @@@@ ToDo: Handle this case } #endif @@ -497,9 +447,9 @@ void XcpEthTlSendMulticastCrm(const uint8_t* packet, uint16_t packet_size, const p.dlc = (uint16_t)packet_size; p.ctr = 0; memcpy(p.packet, packet, packet_size); - r = sendDatagram((uint8_t*)&p, (uint16_t)(packet_size + XCPTL_TRANSPORT_LAYER_HEADER_SIZE),addr,port); + r = sendEthDatagram((uint8_t*)&p, (uint16_t)(packet_size + XCPTL_TRANSPORT_LAYER_HEADER_SIZE),addr,port); if (r == (-1)) { // Would block - // @@@@ Todo + // @@@@ ToDo: Handle this case } } @@ -512,10 +462,10 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t connected = XcpIsConnected(); #ifdef DBG_LEVEL - if (DBG_LEVEL >= 5 || (!connected && DBG_LEVEL >= 3)) { - DBG_PRINTF1("RX: CTR %04X LEN %04X DATA = ", p->ctr,p->dlc); - for (int i = 0; i < p->dlc; i++) DBG_PRINTF1("%0X ", p->packet[i]); - DBG_PRINT1("\n"); + if (DBG_LEVEL >= 5) { + DBG_PRINTF5("RX: CTR %04X LEN %04X DATA = ", p->ctr,p->dlc); + for (int i = 0; i < p->dlc; i++) DBG_PRINTF5("%0X ", p->packet[i]); + DBG_PRINT5("\n"); } #endif @@ -527,7 +477,7 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t // Check unicast ip address, not allowed to change if (memcmp(&gXcpTl.MasterAddr, srcAddr, sizeof(gXcpTl.MasterAddr)) != 0) { // Message from different master received - DBG_PRINTF1("WARNING: message from unknown new master %u.%u.%u.%u, disconnecting!\n", srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3]); + DBG_PRINTF_WARNING("WARNING: message from unknown new master %u.%u.%u.%u, disconnecting!\n", srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3]); XcpDisconnect(); gXcpTl.MasterAddrValid = FALSE; return 1; // Disconnect @@ -535,7 +485,7 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t // Check unicast master udp port, not allowed to change if (gXcpTl.MasterPort != srcPort) { - DBG_PRINTF1("WARNING: master port changed from %u to %u, disconnecting!\n", gXcpTl.MasterPort, srcPort); + DBG_PRINTF_WARNING("WARNING: master port changed from %u to %u, disconnecting!\n", gXcpTl.MasterPort, srcPort); XcpDisconnect(); gXcpTl.MasterAddrValid = FALSE; return 1; // Disconnect @@ -561,7 +511,7 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t XcpCommand((const uint32_t*)&p->packet[0],p->dlc); // Handle CONNECT command } else { - DBG_PRINT1("WARNING: no valid CONNECT command\n"); + DBG_PRINT_WARNING("WARNING: no valid CONNECT command\n"); } } @@ -569,7 +519,7 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t #ifdef XCPTL_ENABLE_UDP if (!isTCP() && !connected) { // not connected before if (XcpIsConnected()) { - DBG_PRINTF1("XCP master connected on UDP addr=%u.%u.%u.%u, port=%u\n", gXcpTl.MasterAddr[0], gXcpTl.MasterAddr[1], gXcpTl.MasterAddr[2], gXcpTl.MasterAddr[3], gXcpTl.MasterPort); + DBG_PRINTF3("XCP master connected on UDP addr=%u.%u.%u.%u, port=%u\n", gXcpTl.MasterAddr[0], gXcpTl.MasterAddr[1], gXcpTl.MasterAddr[2], gXcpTl.MasterAddr[3], gXcpTl.MasterPort); } else { // Is not in connected state gXcpTl.MasterAddrValid = FALSE; // Any client can connect @@ -584,7 +534,7 @@ static int handleXcpCommand(int n, tXcpCtoMessage *p, uint8_t *srcAddr, uint16_t // Handle incoming XCP commands // Blocking for timeout_ms, currently XCPTL_TIMEOUT_INFINITE only (blocking) // returns FALSE on error -BOOL XcpTlHandleCommands(uint32_t timeout_ms) { +BOOL XcpEthTlHandleCommands(uint32_t timeout_ms) { tXcpCtoMessage msgBuf; int16_t n; @@ -599,14 +549,14 @@ BOOL XcpTlHandleCommands(uint32_t timeout_ms) { // Listen to incoming TCP connection if not connected if (gXcpTl.Sock == INVALID_SOCKET) { - DBG_PRINT3("CDM thread waiting for TCP connection ...\n"); + DBG_PRINT5("CDM thread waiting for TCP connection ...\n"); gXcpTl.Sock = socketAccept(gXcpTl.ListenSock, gXcpTl.MasterAddr); // Wait here for incoming connection if (gXcpTl.Sock == INVALID_SOCKET) { DBG_PRINT_ERROR("ERROR: accept failed!\n"); return TRUE; // Ignore error from accept, when in non blocking mode } else { - DBG_PRINTF1("XCP master %u.%u.%u.%u accepted!\n", gXcpTl.MasterAddr[0], gXcpTl.MasterAddr[1], gXcpTl.MasterAddr[2], gXcpTl.MasterAddr[3]); + DBG_PRINTF3("XCP master %u.%u.%u.%u accepted!\n", gXcpTl.MasterAddr[0], gXcpTl.MasterAddr[1], gXcpTl.MasterAddr[2], gXcpTl.MasterAddr[3]); DBG_PRINT3("Listening for XCP commands\n"); } } @@ -626,7 +576,7 @@ BOOL XcpTlHandleCommands(uint32_t timeout_ms) { } } if (n==0) { // Socket closed - DBG_PRINT1("XCP Master closed TCP connection! XCP disconnected.\n"); + DBG_PRINT3("XCP Master closed TCP connection! XCP disconnected.\n"); XcpDisconnect(); sleepMs(100); socketShutdown(gXcpTl.Sock); @@ -671,7 +621,7 @@ static int handleXcpMulticastCommand(int n, tXcpCtoMessage* p, uint8_t* dstAddr, (void)dstAddr; (void)dstPort; - // @@@@ todo: check addr and cluster id and port + // @@@@ ToDo: Check addr and cluster id and port //printf("MULTICAST: %u.%u.%u.%u:%u len=%u\n", dstAddr[0], dstAddr[1], dstAddr[2], dstAddr[3], dstPort, n); // Valid socket data received, at least transport layer header and 1 byte @@ -707,20 +657,19 @@ extern void* XcpTlMulticastThread(void* par) for (;;) { n = socketRecvFrom(gXcpTl.MulticastSock, buffer, (uint16_t)sizeof(buffer), srcAddr, &srcPort, NULL); if (n <= 0) break; // Terminate on error or socket close -#if XCLTL_RESTRICT_MULTICAST +#ifdef XCLTL_RESTRICT_MULTICAST // Accept multicast from active master only if (gXcpTl.MasterAddrValid && memcmp(gXcpTl.MasterAddr, srcAddr, 4) == 0) { - handleXcpMulticastCommand(n, (tXcpCtoMessage*)buffer); + handleXcpMulticastCommand(n, (tXcpCtoMessage*)buffer, srcAddr, srcPort); } else { - DBG_PRINTF1("WARNING: Ignored Multicast from %u.%u.%u.%u:%u\n", srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3], srcPort); + DBG_PRINTF_WARNING("WARNING: Ignored Multicast from %u.%u.%u.%u:%u\n", srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3], srcPort); } #else - handleXcpMulticastCommand(n, (tXcpCtoMessage*)buffer, NULL, NULL); + handleXcpMulticastCommand(n, (tXcpCtoMessage*)buffer, srcAddr, srcPort); #endif } - - DBG_PRINT1("Terminate XCP multicast thread\n"); + DBG_PRINT3("XCP multicast thread terminated\n"); socketClose(&gXcpTl.MulticastSock); return 0; } @@ -730,21 +679,38 @@ extern void* XcpTlMulticastThread(void* par) //------------------------------------------------------------------------------------------------------- -BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segmentSize, BOOL blockingRx) { +BOOL XcpTlInit(uint16_t segmentSize, int (*cb)(uint16_t msgLen, const uint8_t* msgBuf)) { if (segmentSize > XCPTL_MAX_SEGMENT_SIZE) return FALSE; gXcpTl.SegmentSize = segmentSize; - - DBG_PRINTF1("\nInit XCP on %s transport layer\n", useTCP ? "TCP" : "UDP"); - DBG_PRINTF1(" SEGMENT_SIZE=%u, MAX_CTO_SIZE=%u, QUEUE_SIZE=%u, ALIGNMENT=%u, %uKiB memory used\n", gXcpTl.SegmentSize, XCPTL_MAX_CTO_SIZE, XCPTL_QUEUE_SIZE, XCPTL_PACKET_ALIGNMENT, (unsigned int)sizeof(gXcpTl) / 1024); - DBG_PRINT1(" Options=("); // Print activated XCP transport layer options + gXcpTl.sendCallback = cb; // Callback to send a message to the application return 1 if ok, 0 on error, -1 on would block + gXcpTl.lastCroCtr = 0; + gXcpTl.ctr = 0; + mutexInit(&gXcpTl.Mutex_Queue, FALSE, 1000); + XcpTlInitTransmitQueue(); +#if defined(_WIN) // Windows + gXcpTl.queue_event = CreateEvent(NULL, TRUE, FALSE, NULL); + assert(gXcpTl.queue_event!=NULL); + gXcpTl.queue_event_time = 0; +#endif + + DBG_PRINT3("\nInit XCP transport layer\n"); + DBG_PRINTF3(" SEGMENT_SIZE=%u, MAX_CTO_SIZE=%u, QUEUE_SIZE=%u, ALIGNMENT=%u, %uKiB memory used\n", segmentSize, XCPTL_MAX_CTO_SIZE, XCPTL_QUEUE_SIZE, XCPTL_PACKET_ALIGNMENT, (unsigned int)sizeof(gXcpTl) / 1024); + DBG_PRINT3(" Options=("); // Print activated XCP transport layer options #ifdef XCPTL_ENABLE_MULTICAST - DBG_PRINT1("ENABLE_MULTICAST,"); + DBG_PRINT3("ENABLE_MULTICAST,"); #endif #ifdef XCPTL_QUEUED_CRM - DBG_PRINT1("QUEUED_CRM,"); + DBG_PRINT3("QUEUED_CRM,"); #endif - DBG_PRINT1(")\n"); + DBG_PRINT3(")\n"); + + return TRUE; +} + +BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segmentSize, BOOL blockingRx) { + + if (!XcpTlInit(segmentSize,NULL)) return FALSE; if (addr != 0) { // Bind to given addr memcpy(gXcpTl.ServerAddr, addr, 4); @@ -754,31 +720,23 @@ BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segm gXcpTl.ServerPort = port; gXcpTl.ServerUseTCP = useTCP; gXcpTl.blockingRx = blockingRx; - gXcpTl.lastCroCtr = 0; - gXcpTl.ctr = 0; gXcpTl.MasterAddrValid = FALSE; gXcpTl.Sock = INVALID_SOCKET; - - mutexInit(&gXcpTl.Mutex_Queue, 0, 1000); - XcpTlInitTransmitQueue(); -#if defined(_WIN) // Windows - gXcpTl.queue_event = CreateEvent(NULL, TRUE, FALSE, NULL); - assert(gXcpTl.queue_event!=NULL); - gXcpTl.queue_event_time = 0; -#endif - + // Unicast UDP or TCP commands #ifdef XCPTL_ENABLE_TCP gXcpTl.ListenSock = INVALID_SOCKET; - if (useTCP) { // TCP + if (useTCP) + { // TCP if (!socketOpen(&gXcpTl.ListenSock, TRUE /* useTCP */, !blockingRx, TRUE /*reuseAddr*/, FALSE /* timestamps*/)) return FALSE; if (!socketBind(gXcpTl.ListenSock, gXcpTl.ServerAddr, gXcpTl.ServerPort)) return FALSE; // Bind on ANY, when serverAddr=255.255.255.255 if (!socketListen(gXcpTl.ListenSock)) return FALSE; // Put socket in listen mode - DBG_PRINTF1(" Listening for TCP connections on %u.%u.%u.%u port %u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], gXcpTl.ServerPort); + DBG_PRINTF3(" Listening for TCP connections on %u.%u.%u.%u port %u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], gXcpTl.ServerPort); } else #else - if (useTCP) { // TCP - DBG_PRINT_ERROR("ERROR: #define XCPTL_ENABLE_TCP for support\n"); + if (useTCP) + { // TCP + DBG_PRINT_ERROR("ERROR: #define XCPTL_ENABLE_TCP for TCP support\n"); return FALSE; } else @@ -786,24 +744,26 @@ BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segm { // UDP if (!socketOpen(&gXcpTl.Sock, FALSE /* useTCP */, !blockingRx, TRUE /*reuseAddr*/, FALSE /* timestamps*/)) return FALSE; if (!socketBind(gXcpTl.Sock, gXcpTl.ServerAddr, gXcpTl.ServerPort)) return FALSE; // Bind on ANY, when serverAddr=255.255.255.255 - DBG_PRINTF1(" Listening for XCP commands on UDP %u.%u.%u.%u port %u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], gXcpTl.ServerPort); + DBG_PRINTF3(" Listening for XCP commands on UDP %u.%u.%u.%u port %u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], gXcpTl.ServerPort); } +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR socketGetLocalAddr(gXcpTl.ServerMac, NULL); // Store MAC for later use +#endif // Multicast UDP commands #ifdef XCPTL_ENABLE_MULTICAST // Open a socket for GET_DAQ_CLOCK_MULTICAST and join its multicast group if (!socketOpen(&gXcpTl.MulticastSock, FALSE /*useTCP*/, FALSE /*nonblocking*/, TRUE /*reusable*/, FALSE /* timestamps*/)) return FALSE; - DBG_PRINTF2(" Bind XCP multicast socket to %u.%u.%u.%u:%u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], XCPTL_MULTICAST_PORT); + DBG_PRINTF3(" Bind XCP multicast socket to %u.%u.%u.%u:%u\n", gXcpTl.ServerAddr[0], gXcpTl.ServerAddr[1], gXcpTl.ServerAddr[2], gXcpTl.ServerAddr[3], XCPTL_MULTICAST_PORT); if (!socketBind(gXcpTl.MulticastSock, gXcpTl.ServerAddr, XCPTL_MULTICAST_PORT)) return FALSE; // Bind to ANY, when serverAddr=255.255.255.255 uint16_t cid = XcpGetClusterId(); - uint8_t maddr[4] = XCPTL_MULTICAST_ADDR; // 0xEFFFiiii + uint8_t maddr[4] = { 239,255,0,0 }; // XCPTL_MULTICAST_ADDR = 0xEFFFiiii; maddr[2] = (uint8_t)(cid >> 8); maddr[3] = (uint8_t)(cid); if (!socketJoin(gXcpTl.MulticastSock, maddr)) return FALSE; - DBG_PRINTF2(" Listening for XCP GET_DAQ_CLOCK multicast on %u.%u.%u.%u\n", maddr[0], maddr[1], maddr[2], maddr[3]); + DBG_PRINTF3(" Listening for XCP GET_DAQ_CLOCK multicast on %u.%u.%u.%u\n", maddr[0], maddr[1], maddr[2], maddr[3]); DBG_PRINT3(" Start XCP multicast thread\n"); create_thread(&gXcpTl.MulticastThreadHandle, XcpTlMulticastThread); @@ -816,28 +776,31 @@ BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segm void XcpTlShutdown() { + mutexDestroy(&gXcpTl.Mutex_Queue); +#if defined(_WIN) // Windows + CloseHandle(gXcpTl.queue_event); +#endif +} + +void XcpEthTlShutdown() { + + // Close all sockets to enable all threads to terminate #ifdef XCPTL_ENABLE_MULTICAST socketClose(&gXcpTl.MulticastSock); - sleepMs(200); - cancel_thread(gXcpTl.MulticastThreadHandle); + join_thread(gXcpTl.MulticastThreadHandle); #endif - - mutexDestroy(&gXcpTl.Mutex_Queue); #ifdef XCPTL_ENABLE_TCP if (isTCP()) socketClose(&gXcpTl.ListenSock); #endif socketClose(&gXcpTl.Sock); -#if defined(_WIN) // Windows - CloseHandle(gXcpTl.queue_event); - -#endif + // Free other resources + XcpTlShutdown(); } //------------------------------------------------------------------------------------------------------- - // Wait for outgoing data or timeout after timeout_us // Return FALSE in case of timeout BOOL XcpTlWaitForTransmitData(uint32_t timeout_ms) { @@ -874,6 +837,7 @@ int32_t XcpTlGetLastError() { //------------------------------------------------------------------------------------------------------- +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR void XcpEthTlGetInfo(BOOL* isTcp, uint8_t* mac, uint8_t* addr, uint16_t *port) { *isTcp = gXcpTl.ServerUseTCP; @@ -881,4 +845,36 @@ void XcpEthTlGetInfo(BOOL* isTcp, uint8_t* mac, uint8_t* addr, uint16_t *port) { memcpy(mac, gXcpTl.ServerMac, 4); *port = gXcpTl.ServerPort; } +#endif + +//------------------------------------------------------------------------------------------------------- + +// Execute XCP command from procedure call +// Returns FALSE on error +uint8_t XcpTlCommand( uint16_t msgLen, const uint8_t* msgBuf) { + + BOOL connected = XcpIsConnected(); + tXcpCtoMessage* p = (tXcpCtoMessage*)msgBuf; + assert (msgLen>=p->dlc+XCPTL_TRANSPORT_LAYER_HEADER_SIZE); + + /* Connected */ + if (connected) { + return XcpCommand((const uint32_t*)&p->packet[0], p->dlc); // Handle command + } + + /* Not connected yet */ + else { + /* Check for CONNECT command ? */ + if (p->dlc == 2 && p->packet[0] == CC_CONNECT) { + XcpTlInitTransmitQueue(); + return XcpCommand((const uint32_t*)&p->packet[0],p->dlc); // Handle CONNECT command + } + else { + DBG_PRINT_WARNING("WARNING: no valid CONNECT command\n"); + return CRC_CMD_SYNTAX; + } + + } +} + diff --git a/src/xcpEthTl.h b/src/xcpEthTl.h index 04f2819..789eb88 100644 --- a/src/xcpEthTl.h +++ b/src/xcpEthTl.h @@ -6,21 +6,15 @@ /* ETH transport Layer functions called by application */ extern BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segmentSize, BOOL blockingRx); // Start transport layer - -// Test mode -#ifdef XCPTL_ENABLE_SELF_TEST -extern void XcpEthTlCreateA2lDescription(); -extern void XcpEthTlCreateXcpEvents(); -extern uint64_t XcpEthTlGetBytesWritten(); // Get the number of bytes send +extern void XcpEthTlShutdown(); +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR +extern void XcpEthTlGetInfo(BOOL* isTCP, uint8_t* mac, uint8_t* addr, uint16_t* port); #endif - /* ETH transport Layer functions called by XCPlite.c */ +extern BOOL XcpEthTlHandleCommands(uint32_t timeout_ms); // Handle all incoming XCP commands, (wait for at least timeout_ms) extern void XcpEthTlSendMulticastCrm(const uint8_t* data, uint16_t n, const uint8_t* addr, uint16_t port); // Send multicast command response #ifdef XCPTL_ENABLE_MULTICAST extern void XcpEthTlSetClusterId(uint16_t clusterId); // Set cluster id for GET_DAQ_CLOCK_MULTICAST reception #endif -extern void XcpEthTlGetInfo(BOOL* isTCP, uint8_t* mac, uint8_t* addr, uint16_t* port); - - diff --git a/src/xcpLite.c b/src/xcpLite.c index caa9439..6a91f20 100644 --- a/src/xcpLite.c +++ b/src/xcpLite.c @@ -63,7 +63,6 @@ #include "dbg_print.h" #include "xcpLite.h" // Protocol layer interface - /****************************************************************************/ /* Defaults and checks */ /****************************************************************************/ @@ -109,9 +108,12 @@ #error "Please define XCP_DAQ_MEM_SIZE" #endif -// Dynamic addressing (ext=1, addr=(event<<16)|offset requires transport layer mode XCPTL_QUEUED_CRM +// Dynamic addressing (ext = XCP_ADDR_EXT_DYN, addr=(event<<16)|offset requires transport layer mode XCPTL_QUEUED_CRM +#if defined(XCP_ENABLE_DYN_ADDRESSING) && !defined(XCP_ADDR_EXT_DYN) +#error "Please define XCP_ADDR_EXT_DYN" +#endif #if defined(XCP_ENABLE_DYN_ADDRESSING) && !defined(XCPTL_QUEUED_CRM) -#error "Dynamic address format (ext=1) requires XCPTL_QUEUED_CRM!" +#error "Dynamic address format (ext = XCP_ADDR_EXT_DYN) requires XCPTL_QUEUED_CRM" #endif @@ -140,6 +142,7 @@ typedef struct { uint8_t mode; uint8_t state; uint8_t priority; + uint8_t addrExt; } tXcpDaqList; @@ -155,9 +158,6 @@ typedef struct { } tXcpDaq; - - - /* Shortcuts */ /* j is absolute odt number */ @@ -177,6 +177,7 @@ typedef struct { #define DaqListMode(i) gXcp.Daq.u.DaqList[i].mode #define DaqListState(i) gXcp.Daq.u.DaqList[i].state #define DaqListEventChannel(i) gXcp.Daq.u.DaqList[i].eventChannel +#define DaqListAddrExt(i) gXcp.Daq.u.DaqList[i].addrExt #define DaqListPriority(i) gXcp.Daq.u.DaqList[i].priority #ifdef XCP_ENABLE_PACKED_MODE #define DaqListSampleCount(i) gXcp.Daq.u.DaqList[i].sampleCount @@ -202,30 +203,46 @@ typedef union { typedef struct { uint16_t SessionStatus; + + tXcpCto Crm; /* response message buffer */ + uint8_t CrmLen; /* RES,ERR message length */ - uint8_t CrmLen; /* RES,ERR message length */ - uint8_t CroLen; /* CMD message length */ - tXcpCto Crm; /* RES,ERR message buffer */ - tXcpCto Cro; /* CMD message buffer */ +#ifdef XCP_ENABLE_DYN_ADDRESSING + tXcpCto CmdPending; /* pending command message buffer */ + uint8_t CmdPendingLen; /* pending command message length */ + + #ifdef XCP_ENABLE_MULTITHREAD_CAL_EVENTS + MUTEX CmdPendingMutex; + #endif +#endif + +#ifdef DBG_LEVEL + const tXcpCto *CmdLast; +#endif - uint8_t* MtaPtr; /* Memory Transfer Address as pointer (ApplXcpGetPointer) */ + /* Memory Transfer Address as pointer (ApplXcpGetPointer) */ + uint8_t* MtaPtr; uint32_t MtaAddr; uint8_t MtaExt; - + /* Dynamic DAQ list structures, This structure should be stored in resume mode */ tXcpDaq Daq; tXcpOdt* pOdt; - uint32_t* pOdtEntryAddr; + int32_t* pOdtEntryAddr; uint8_t* pOdtEntrySize; uint64_t DaqStartClock64; uint32_t DaqOverflowCount; /* State info from SET_DAQ_PTR for WRITE_DAQ and WRITE_DAQ_MULTIPLE */ - uint16_t WriteDaqOdtEntry; - uint16_t WriteDaqOdt; + uint16_t WriteDaqOdtEntry; // Absolute odt index + uint16_t WriteDaqOdt; // Absolute odt index uint16_t WriteDaqDaq; +#ifdef XCP_ENABLE_FREEZE_CAL_PAGE + uint8_t SegmentMode; +#endif + /* Optional event list */ #ifdef XCP_ENABLE_DAQ_EVENT_LIST @@ -241,7 +258,7 @@ typedef struct { uint16_t ClusterId; #endif -#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH +#if XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN #pragma pack(push, 1) struct { T_CLOCK_INFO server; @@ -256,8 +273,10 @@ typedef struct { } tXcpData; - -static tXcpData gXcp = { 0,0,0 }; +static tXcpData gXcp = { 0 }; +// Some compilers complain about this initialization +// Calling XCP functions (e.g. XcpEvent()) before XcpInit() is forbidden +// Static initialization of gXcp.SessionStatus to 0 allows to check this condition #define CRM (gXcp.Crm) #define CRM_LEN (gXcp.CrmLen) @@ -265,11 +284,7 @@ static tXcpData gXcp = { 0,0,0 }; #define CRM_WORD(x) (gXcp.Crm.w[x]) #define CRM_DWORD(x) (gXcp.Crm.dw[x]) -#define CRO (gXcp.Cro) -#define CRO_LEN (gXcp.CroLen) -#define CRO_BYTE(x) (gXcp.Cro.b[x]) -#define CRO_WORD(x) (gXcp.Cro.w[x]) -#define CRO_DWORD(x) (gXcp.Cro.dw[x]) +static uint8_t XcpAsyncCommand( BOOL async, const uint32_t* cmdBuf, uint16_t cmdLen ); /****************************************************************************/ @@ -279,17 +294,10 @@ static tXcpData gXcp = { 0,0,0 }; #define error(e) { err=(e); goto negative_response; } #define check_error(e) { err=(e); if (err!=0) goto negative_response; } -#ifdef XCP_ENABLE_DYN_ADDRESSING - #define check_result(e) { err=(e); if (err!=0) { if (err==CRC_CMD_PENDING) { XcpPushCommand(); goto no_response;} else goto negative_response; } } -#else - #define check_result(e) { err=(e); if (err!=0) goto negative_response; } -#endif - #define isInitialized() (gXcp.SessionStatus & SS_INITIALIZED) #define isStarted() (gXcp.SessionStatus & SS_STARTED) #define isConnected() (gXcp.SessionStatus & SS_CONNECTED) #define isDaqRunning() (gXcp.SessionStatus & SS_DAQ) -#define isCmdPending() (gXcp.SessionStatus & SS_CMD_PENDING) #define isLegacyMode() (gXcp.SessionStatus & SS_LEGACY_MODE) @@ -298,23 +306,25 @@ static tXcpData gXcp = { 0,0,0 }; /****************************************************************************/ #ifdef XCP_ENABLE_TEST_CHECKS - #define check_len(n) if (cmdLen<(n)) { err = CRC_CMD_SYNTAX; goto negative_response; } + #define check_len(n) if (CRO_LEN<(n)) { err = CRC_CMD_SYNTAX; goto negative_response; } #else #define check_len(n) #endif - #ifdef DBG_LEVEL -static void XcpPrintCmd(); -static void XcpPrintRes(); +static void XcpPrintCmd(const tXcpCto* cro); +static void XcpPrintRes(const tXcpCto* crm); static void XcpPrintDaqList(uint16_t daq); #endif - /****************************************************************************/ /* Status */ /****************************************************************************/ +uint16_t XcpGetSessionStatus() { + return gXcp.SessionStatus; +} + BOOL XcpIsStarted() { return isStarted(); } @@ -358,57 +368,119 @@ uint32_t XcpGetDaqOverflowCount() { /* Calibration */ /****************************************************************************/ -// Write n bytes. Copying of size bytes from data to gXcp.MtaPtr +/* +XcpWriteMta is not performance critical, but critical for data consistency. +It is used to modify calibration variables. +When using memcpy, it is not guaranteed that is uses multibyte move operations specifically for alignment to provide thread safety. +Its primary responsibility is only to copy memory. Any considerations regarding thread safety must be explicitly managed. +This is also a requirement to the tool, which must ensure that the data is consistent by choosing the right granularity for DOWNLOAD and SHORT_DOWNLOAD operations. +*/ + +// Copy of size bytes from data to gXcp.MtaPtr or gXcp.MtaAddr depending on the addressing mode static uint8_t XcpWriteMta( uint8_t size, const uint8_t* data ) { - // Ext=0x01 Relativ addressing -#ifdef XCP_ENABLE_DYN_ADDRESSING - if (gXcp.MtaExt == 0x01) { - return CRC_CMD_PENDING; // Async command - } + // EXT == XCP_ADDR_EXT_APP Application specific memory access +#ifdef XCP_ENABLE_APP_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_APP) { + uint8_t res = ApplXcpWriteMemory(gXcp.MtaAddr, size, data); + gXcp.MtaAddr += size; + return res; + } #endif - // Ext=0x00 Standard memory access - if (gXcp.MtaExt == 0x00) { - if (gXcp.MtaPtr == NULL) return CRC_ACCESS_DENIED; - memcpy(gXcp.MtaPtr, data, size); - gXcp.MtaPtr += size; - return 0; // Ok - } + // Standard memory access by pointer gXcp.MtaPtr + if (gXcp.MtaExt == XCP_ADDR_EXT_PTR) { + + if (gXcp.MtaPtr == NULL) return CRC_ACCESS_DENIED; - return CRC_ACCESS_DENIED; // Access violation + // TEST + // Test data consistency: slow bytewise write to increase probability for multithreading data consistency problems + // while (size-->0) { + // *gXcp.MtaPtr++ = *data++; + // sleepNs(5); + // } + + // Fast write with atomic copies of basic types, assuming correctly aligned target memory locations + switch (size) { + case 1: *gXcp.MtaPtr = *data; break; + case 2: *(uint16_t*)gXcp.MtaPtr = *(uint16_t*)data; break; + case 4: *(uint32_t*)gXcp.MtaPtr = *(uint32_t*)data; break; + case 8: *(uint64_t*)gXcp.MtaPtr = *(uint64_t*)data; break; + default: memcpy(gXcp.MtaPtr, data, size); break; + } + gXcp.MtaPtr += size; + return 0; // Ok + } + + return CRC_ACCESS_DENIED; // Access violation, illegal address or extension } -// Read n bytes. Copying of size bytes from gXcp.MtaPtr to data +// Copying of size bytes from data to gXcp.MtaPtr or gXcp.MtaAddr, depending on the addressing mode static uint8_t XcpReadMta( uint8_t size, uint8_t* data ) { - // Ext=0x01 Relativ addressing -#ifdef XCP_ENABLE_DYN_ADDRESSING - if (gXcp.MtaExt == 0x01) { - return CRC_CMD_PENDING; // Async command - } + + // EXT == XCP_ADDR_EXT_APP Application specific memory access +#ifdef XCP_ENABLE_APP_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_APP) { + uint8_t res = ApplXcpReadMemory(gXcp.MtaAddr, size, data); + gXcp.MtaAddr += size; + return res; + } #endif - // Ext=0xFF File (A2L) upload + // Ext == XCP_ADDR_EXT_ABS Standard memory access by absolute address pointer + if (gXcp.MtaExt == XCP_ADDR_EXT_PTR) { + if (gXcp.MtaPtr == NULL) return CRC_ACCESS_DENIED; + memcpy(data, gXcp.MtaPtr, size); + gXcp.MtaPtr += size; + return 0; // Ok + } + + // Ext == XCP_ADDR_EXT_A2L A2L file upload address space #ifdef XCP_ENABLE_IDT_A2L_UPLOAD - if (gXcp.MtaExt == 0xFF) { - if (!ApplXcpReadA2L(size, gXcp.MtaAddr, data)) return CRC_ACCESS_DENIED; // Access violation - gXcp.MtaAddr += size; - return 0; // Ok - } + if (gXcp.MtaExt == XCP_ADDR_EXT_A2L) { + if (!ApplXcpReadA2L(size, gXcp.MtaAddr, data)) return CRC_ACCESS_DENIED; // Access violation + gXcp.MtaAddr += size; + return 0; // Ok + } #endif - // Ext=0x00 Standard memory access - if (gXcp.MtaExt == 0x00) { - if (gXcp.MtaPtr == NULL) return CRC_ACCESS_DENIED; - memcpy(data, gXcp.MtaPtr, size); - gXcp.MtaPtr += size; - return 0; // Ok - } - - return CRC_ACCESS_DENIED; // Access violation + return CRC_ACCESS_DENIED; // Access violation, illegal address or extension } +// Set MTA +static uint8_t XcpSetMta( uint8_t ext, uint32_t addr ) { + + gXcp.MtaExt = ext; + gXcp.MtaAddr = addr; +#ifdef XCP_ENABLE_DYN_ADDRESSING + // Relative addressing mode, MtaPtr unknown yet + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { + gXcp.MtaPtr = NULL; // MtaPtr not used + } + else +#endif +#ifdef XCP_ENABLE_APP_ADDRESSING + // Application specific addressing mode + if (gXcp.MtaExt == XCP_ADDR_EXT_APP) { + gXcp.MtaPtr = NULL; // MtaPtr not used + } + else +#endif +#ifdef XCP_ENABLE_ABS_ADDRESSING + // Absolute addressing mode + if (gXcp.MtaExt == XCP_ADDR_EXT_ABS) { + gXcp.MtaPtr = ApplXcpGetPointer(gXcp.MtaExt, gXcp.MtaAddr); + gXcp.MtaExt = XCP_ADDR_EXT_PTR; + } + else +#endif + { + return CRC_OUT_OF_RANGE; // Unsupported addressing mode + } + + return CRC_CMD_OK; +} /****************************************************************************/ @@ -416,9 +488,9 @@ static uint8_t XcpReadMta( uint8_t size, uint8_t* data ) /****************************************************************************/ // Free all dynamic DAQ lists -static void XcpFreeDaq( void ) -{ - gXcp.SessionStatus &= (uint16_t)(~SS_DAQ); +static void XcpFreeDaq( void ) { + + gXcp.SessionStatus &= ~SS_DAQ; gXcp.Daq.DaqCount = 0; gXcp.Daq.OdtCount = 0; @@ -432,8 +504,8 @@ static void XcpFreeDaq( void ) } // Allocate Memory for daq,odt,odtEntries and Queue according to DaqCount, OdtCount and OdtEntryCount -static uint8_t XcpAllocMemory( void ) -{ +static uint8_t XcpAllocMemory( void ) { + uint32_t s; /* Check memory overflow */ @@ -444,38 +516,39 @@ static uint8_t XcpAllocMemory( void ) if (s>=XCP_DAQ_MEM_SIZE) return CRC_MEMORY_OVERFLOW; gXcp.pOdt = (tXcpOdt*)&gXcp.Daq.u.DaqList[gXcp.Daq.DaqCount]; - gXcp.pOdtEntryAddr = (uint32_t*)&gXcp.pOdt[gXcp.Daq.OdtCount]; + gXcp.pOdtEntryAddr = (int32_t*)&gXcp.pOdt[gXcp.Daq.OdtCount]; gXcp.pOdtEntrySize = (uint8_t*)&gXcp.pOdtEntryAddr[gXcp.Daq.OdtEntryCount]; - DBG_PRINTF4("[XcpAllocMemory] %u of %u Bytes used\n",s,XCP_DAQ_MEM_SIZE ); + DBG_PRINTF5("[XcpAllocMemory] %u of %u Bytes used\n",s,XCP_DAQ_MEM_SIZE ); return 0; } // Allocate daqCount DAQ lists -static uint8_t XcpAllocDaq( uint16_t daqCount ) -{ - if ( (gXcp.Daq.OdtCount!=0) || (gXcp.Daq.OdtEntryCount!=0) ) { - return CRC_SEQUENCE; - } - if( daqCount == 0 || daqCount>255) { - return CRC_OUT_OF_RANGE; - } +static uint8_t XcpAllocDaq( uint16_t daqCount ) { + + uint16_t daq; + uint8_t r; + if ( gXcp.Daq.OdtCount!=0 || gXcp.Daq.OdtEntryCount!=0 ) return CRC_SEQUENCE; + if ( daqCount == 0 || daqCount>255) return CRC_OUT_OF_RANGE; + + // Initialize + if (0!=(r = XcpAllocMemory())) return r; + for (daq=0;daq 0xFFFF) return CRC_OUT_OF_RANGE; // Overall number of ODTs limited to 64K @@ -483,8 +556,6 @@ static uint8_t XcpAllocOdt( uint16_t daq, uint8_t odtCount ) gXcp.Daq.u.DaqList[daq].firstOdt = gXcp.Daq.OdtCount; gXcp.Daq.OdtCount = (uint16_t)n; gXcp.Daq.u.DaqList[daq].lastOdt = (uint16_t)(gXcp.Daq.OdtCount-1); - gXcp.Daq.u.DaqList[daq].eventChannel = 0xFFFF; // Undefined - return XcpAllocMemory(); } @@ -499,7 +570,7 @@ static BOOL XcpAdjustOdtSize(uint16_t daq, uint16_t odt, uint8_t size) { DaqListOdtSize(odt) = (uint16_t)(DaqListOdtSize(odt) + size); #endif #ifdef XCP_ENABLE_TEST_CHECKS - if (DaqListOdtSize(odt) > XCPTL_MAX_DTO_SIZE) { + if (DaqListOdtSize(odt) > (XCPTL_MAX_DTO_SIZE-2)-(odt==0?4:0)) { // -6/2 bytes for odt+daq+timestamp DBG_PRINTF_ERROR("ERROR: ODT size %u exceed XCPTL_MAX_DTO_SIZE %u!\n", DaqListOdtSize(odt), XCPTL_MAX_DTO_SIZE); return FALSE; } @@ -508,17 +579,13 @@ static BOOL XcpAdjustOdtSize(uint16_t daq, uint16_t odt, uint8_t size) { } // Allocate all ODT entries, Parameter odt is relative odt number -static uint8_t XcpAllocOdtEntry( uint16_t daq, uint8_t odt, uint8_t odtEntryCount ) -{ +static uint8_t XcpAllocOdtEntry( uint16_t daq, uint8_t odt, uint8_t odtEntryCount ) { + int xcpFirstOdt; uint32_t n; - if ( (gXcp.Daq.DaqCount==0) || (gXcp.Daq.OdtCount==0) ) { - return (uint8_t)CRC_SEQUENCE; - } - if (odtEntryCount==0) { - return (uint8_t)CRC_OUT_OF_RANGE; - } + if ( gXcp.Daq.DaqCount==0 || gXcp.Daq.OdtCount==0 ) return CRC_SEQUENCE; + if (odtEntryCount==0) return CRC_OUT_OF_RANGE; /* Absolute ODT entry count is limited to 64K */ n = (uint32_t)gXcp.Daq.OdtEntryCount + (uint32_t)odtEntryCount; @@ -546,42 +613,56 @@ static uint8_t XcpSetDaqPtr(uint16_t daq, uint8_t odt, uint8_t idx) { } // Add an ODT entry to current DAQ/ODT +// Supports XCP_ADDR_EXT_ABS and XCP_ADDR_EXT_DYN if XCP_ENABLE_DYN_ADDRESSING +// All ODT entries of a DAQ list must have the same address extension,returns CRC_DAQ_CONFIG if not +// In XCP_ADDR_EXT_DYN addressing mode, the event must be unique static uint8_t XcpAddOdtEntry(uint32_t addr, uint8_t ext, uint8_t size) { if ((size == 0) || size > XCP_MAX_ODT_ENTRY_SIZE) return CRC_OUT_OF_RANGE; if (0 == gXcp.Daq.DaqCount || 0 == gXcp.Daq.OdtCount || 0 == gXcp.Daq.OdtEntryCount) return CRC_DAQ_CONFIG; + if (gXcp.WriteDaqOdtEntry-DaqListOdtFirstEntry(gXcp.WriteDaqOdt) >= DaqListOdtEntryCount(gXcp.WriteDaqOdt)) return CRC_OUT_OF_RANGE; -#ifndef XCP_ENABLE_DYN_ADDRESSING - if (ext > 0) return CRC_ACCESS_DENIED; // Not supported -#else - if (ext > 1) return CRC_ACCESS_DENIED; // Not supported - if (ext == 1) { + uint8_t daq_ext = DaqListAddrExt(gXcp.WriteDaqDaq); + if (daq_ext != XCP_ADDR_EXT_UNDEFINED && ext != daq_ext) return CRC_DAQ_CONFIG; // Error not unique address extension + DaqListAddrExt(gXcp.WriteDaqDaq) = ext; + + int32_t base_offset = 0; +#ifdef XCP_ENABLE_DYN_ADDRESSING + // DYN addressing mode, base pointer will given to XcpEventExt() + // Max address range base-0x8000 - base+0x7FFF + if (ext == XCP_ADDR_EXT_DYN) { // relative addressing mode + uint16_t event = (uint16_t)(addr >> 16); // event + int16_t offset = (int16_t)(addr & 0xFFFF); // address offset + base_offset = (int32_t)offset; // sign extend to 32 bit, the relative address may be negative uint16_t e0 = DaqListEventChannel(gXcp.WriteDaqDaq); - uint16_t e1 = (uint16_t)(addr >> 16); - addr &= 0x0000FFFF; - if (e0 != 0xFFFF && e0 != e1) return CRC_OUT_OF_RANGE; // Error event channel redefinition - DaqListEventChannel(gXcp.WriteDaqDaq) = e1; - } - else -#endif - { + if (e0 != XCP_UNDEFINED_EVENT && e0 != event) return CRC_OUT_OF_RANGE; // Error event channel redefinition + DaqListEventChannel(gXcp.WriteDaqDaq) = event; + } else +#endif +#ifdef XCP_ENABLE_ABS_ADDRESSING + // ABS adressing mode, base pointer will ApplXcpGetBaseAddr() + // Max address range 0-0x7FFFFFFF + if (ext == XCP_ADDR_EXT_ABS) { // absolute addressing mode{ uint8_t* p; - uint64_t a; + int64_t a; p = ApplXcpGetPointer(ext, addr); if (p == NULL) return CRC_ACCESS_DENIED; // Access denied a = p - ApplXcpGetBaseAddr(); - if (a>0xFFFFFFFF) return CRC_ACCESS_DENIED; // Access out of range - addr = (uint32_t)a; - } + if (a>0x7FFFFFFF || a<0) return CRC_ACCESS_DENIED; // Access out of range + base_offset = (int32_t)a; + } else +#endif + return CRC_ACCESS_DENIED; OdtEntrySize(gXcp.WriteDaqOdtEntry) = size; - OdtEntryAddr(gXcp.WriteDaqOdtEntry) = addr; // Holds A2L/XCP address + OdtEntryAddr(gXcp.WriteDaqOdtEntry) = base_offset; // Signed 32 bit offset relative to base pointer given to XcpEvent_ if (!XcpAdjustOdtSize(gXcp.WriteDaqDaq, gXcp.WriteDaqOdt, size)) return CRC_DAQ_CONFIG; gXcp.WriteDaqOdtEntry++; // Autoincrement to next ODT entry, no autoincrementing over ODTs return 0; } // Set DAQ list mode +// All DAQ lists associaded with an event, must have the same event channel and address extension static uint8_t XcpSetDaqListMode(uint16_t daq, uint16_t event, uint8_t mode, uint8_t prio ) { #ifdef XCP_ENABLE_DAQ_EVENT_LIST @@ -589,8 +670,21 @@ static uint8_t XcpSetDaqListMode(uint16_t daq, uint16_t event, uint8_t mode, uin if (e == NULL) return CRC_OUT_OF_RANGE; #endif #ifdef XCP_ENABLE_DYN_ADDRESSING - uint16_t e0 = DaqListEventChannel(daq); - if (e0 != 0xFFFF && event != e0) return CRC_OUT_OF_RANGE; // Error event channel redefinition + + // Check if the DAQ list requires a specific event and it matches + uint16_t event0 = DaqListEventChannel(daq); + if (event0 != XCP_UNDEFINED_EVENT && event != event0) return CRC_DAQ_CONFIG; // Error event not unique + + // Check all DAQ lists with same event have the same address extension + uint8_t ext = DaqListAddrExt(daq); + for (uint16_t daq0=0;daq0= 3) { + if (DBG_LEVEL >= 4) { XcpPrintDaqList(daq); } #endif } } #ifdef DBG_LEVEL - if (DBG_LEVEL >= 2) { + if (DBG_LEVEL >= 4) { char ts[64]; clockGetString(ts, sizeof(ts), gXcp.DaqStartClock64); printf("DAQ start at t=%s\n", ts); @@ -648,8 +742,8 @@ static void XcpStartAllSelectedDaq() // Stop DAQ list // Returns TRUE if all DAQ lists are stopped and event procession has stopped -static uint8_t XcpStopDaq( uint16_t daq ) -{ +static uint8_t XcpStopDaq( uint16_t daq ) { + DaqListState(daq) &= (uint8_t)(~(DAQ_STATE_OVERRUN|DAQ_STATE_RUNNING)); /* Check if all DAQ lists are stopped */ @@ -658,14 +752,14 @@ static uint8_t XcpStopDaq( uint16_t daq ) return 0; } } - gXcp.SessionStatus &= (uint16_t)(~SS_DAQ); // Stop processing DAQ events + gXcp.SessionStatus &= ~SS_DAQ; // Stop processing DAQ events return 1; } // Stop all selected DAQs // Does not stop event processing -static void XcpStopAllSelectedDaq() -{ +static void XcpStopAllSelectedDaq() { + uint16_t daq; for (daq=0;daqmutex); #endif // Get clock, if not given as parameter @@ -738,21 +833,21 @@ static void XcpEvent_(uint16_t event, uint8_t* base, uint64_t clock) // Get DTO buffer d0 = XcpTlGetTransmitBuffer(&handle, (uint16_t)(DaqListOdtSize(odt) + hs)); -#ifdef XCP_ENABLE_MULTITHREAD_EVENTS +#if defined(XCP_ENABLE_MULTITHREAD_DAQ_EVENTS) && defined(XCP_ENABLE_DAQ_EVENT_LIST) mutexUnlock(&ev->mutex); #endif // Check declining time stamps // Disable for maximal measurement performance #ifdef XCP_ENABLE_DAQ_EVENT_LIST -#ifdef XCP_ENABLE_TEST_CHECKS + #if defined(XCP_ENABLE_SELF_TEST) if (ev->time > clock) { // declining time stamps DBG_PRINTF_ERROR("ERROR: Declining timestamp! event=%u, diff=%" PRIu64 "\n", event, ev->time-clock); } if (ev->time == clock) { // duplicate time stamps - DBG_PRINTF3("WARNING: Duplicate timestamp! event=%u\n", event); + DBG_PRINTF_WARNING("WARNING: Duplicate timestamp! event=%u\n", event); } -#endif + #endif #endif // Buffer overrun @@ -802,47 +897,80 @@ static void XcpEvent_(uint16_t event, uint8_t* base, uint64_t clock) } /* daq */ #ifdef XCP_ENABLE_DAQ_EVENT_LIST -#ifdef XCP_ENABLE_TEST_CHECKS + #if defined(XCP_ENABLE_SELF_TEST) ev->time = clock; -#endif + #endif #endif } +// ABS adressing mode event with clock +// Base is ApplXcpGetBaseAddr() +#ifdef XCP_ENABLE_ABS_ADDRESSING void XcpEventAt(uint16_t event, uint64_t clock) { if (!isDaqRunning()) return; // DAQ not running XcpEvent_(event, ApplXcpGetBaseAddr(), clock); } +#endif -void XcpEventExt(uint16_t event, uint8_t* base) { +// ABS addressing mode event +// Base is ApplXcpGetBaseAddr() +#ifdef XCP_ENABLE_ABS_ADDRESSING +void XcpEvent(uint16_t event) { + if (!isDaqRunning()) return; // DAQ not running + XcpEvent_(event, ApplXcpGetBaseAddr(), 0); +} +#endif +// Dyn addressing mode event +// Base is given as parameter +uint8_t XcpEventExt(uint16_t event, const uint8_t* base, uint32_t len) { + + // @@@@ ToDo: use len to check memory boundaries + (void)len; + + // Cal #ifdef XCP_ENABLE_DYN_ADDRESSING - if (!isStarted()) return; - if (isCmdPending()) { // Pending command, check if it can be executed in this context - if (gXcp.MtaExt == 1 && (uint16_t)(gXcp.MtaAddr >> 16) == event) { - // Convert MtaPtr to context - gXcp.MtaPtr = base + (gXcp.MtaAddr & 0xFFFF); - gXcp.MtaExt = 0; - XcpCommand((const uint32_t*)&gXcp.Cro, gXcp.CroLen); - gXcp.SessionStatus &= (uint16_t)~SS_CMD_PENDING; + if (!isStarted()) return CRC_CMD_OK; + + // Check if a pending command can be executed in this context + // @@@@ ToDo: Optimize with atomics, this is performance critical as cal events may come from different threads +#if defined(XCP_ENABLE_MULTITHREAD_CAL_EVENTS) + mutexLock(&gXcp.CmdPendingMutex); +#endif + BOOL cmdPending = FALSE; + if (gXcp.SessionStatus & SS_CMD_PENDING) { + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN && (uint16_t)(gXcp.MtaAddr >> 16) == event) { + gXcp.SessionStatus &= ~SS_CMD_PENDING; + cmdPending = TRUE; } } -#endif +#if defined(XCP_ENABLE_MULTITHREAD_CAL_EVENTS) + mutexUnlock(&gXcp.CmdPendingMutex); +#endif + if (cmdPending) { + // Convert relative signed 16 bit addr in MtaAddr to pointer MtaPtr + gXcp.MtaPtr = (uint8_t*)(base + (int16_t)(gXcp.MtaAddr & 0xFFFF)); + gXcp.MtaExt = XCP_ADDR_EXT_PTR; + if (CRC_CMD_OK==XcpAsyncCommand(TRUE,(const uint32_t*)&gXcp.CmdPending, gXcp.CmdPendingLen)) { + uint8_t cmd = gXcp.CmdPending.b[0]; + if (cmd==CC_SHORT_DOWNLOAD||cmd==CC_DOWNLOAD) return CRC_CMD_PENDING; // Write operation done + } + return CRC_CMD_OK; // Another pending operation done + } +#endif // XCP_ENABLE_DYN_ADDRESSING - if (!isDaqRunning()) return; // DAQ not running + // Daq + if (!isDaqRunning()) return CRC_CMD_OK; // DAQ not running XcpEvent_(event, base, 0); + return CRC_CMD_OK; } -void XcpEvent(uint16_t event) { - if (!isDaqRunning()) return; // DAQ not running - XcpEvent_(event, ApplXcpGetBaseAddr(), 0); -} /****************************************************************************/ /* Command Processor */ /****************************************************************************/ - // Stops DAQ and goes to disconnected state void XcpDisconnect( void ) { @@ -854,75 +982,105 @@ void XcpDisconnect( void ) XcpTlWaitForTransmitQueueEmpty(); // Wait until transmit queue empty } - gXcp.SessionStatus &= (uint16_t)(~SS_CONNECTED); + gXcp.SessionStatus &= ~SS_CONNECTED; } // Transmit command response -static void XcpSendResponse() { +static void XcpSendResponse(const tXcpCto* crm, uint8_t crmLen) { - XcpTlSendCrm((const uint8_t*)&gXcp.Crm, gXcp.CrmLen); + XcpTlSendCrm((const uint8_t*)crm, crmLen); #ifdef DBG_LEVEL - if (DBG_LEVEL >= 2) XcpPrintRes(); + if (DBG_LEVEL >= 4) XcpPrintRes(crm); #endif } // Transmit multicast command response #if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH -static void XcpSendMulticastResponse( uint8_t *addr, uint16_t port) { +#ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR +static void XcpSendMulticastResponse( const tXcpCto* crm, uint8_t crmLen, uint8_t *addr, uint16_t port) { - XcpEthTlSendMulticastCrm((const uint8_t*)&gXcp.Crm, gXcp.CrmLen, addr, port); + XcpEthTlSendMulticastCrm((const uint8_t*)crm, crmLen, addr, port); #ifdef DBG_LEVEL - if (DBG_LEVEL >= 2) XcpPrintRes(); + if (DBG_LEVEL >= 4) XcpPrintRes(crm); #endif } #endif +#endif // Push XCP command which can not be executes in this context for later async execution #ifdef XCP_ENABLE_DYN_ADDRESSING -static void XcpPushCommand() { - gXcp.SessionStatus |= (uint16_t)SS_CMD_PENDING; -} + +static uint8_t XcpPushCommand( const tXcpCto* cmdBuf, uint16_t cmdLen) { + +#if defined(XCP_ENABLE_MULTITHREAD_CAL_EVENTS) + mutexLock(&gXcp.CmdPendingMutex); #endif + // Set pending command flag + if (gXcp.SessionStatus & SS_CMD_PENDING) { +#if defined(XCP_ENABLE_MULTITHREAD_CAL_EVENTS) + mutexUnlock(&gXcp.CmdPendingMutex); +#endif + return CRC_CMD_BUSY; + } + gXcp.SessionStatus |= SS_CMD_PENDING; + + gXcp.CmdPendingLen = cmdLen; + memcpy(&gXcp.CmdPending, cmdBuf, cmdLen); + +#if defined(XCP_ENABLE_MULTITHREAD_CAL_EVENTS) + mutexUnlock(&gXcp.CmdPendingMutex); +#endif + + return CRC_CMD_OK; +} +#endif // XCP_ENABLE_DYN_ADDRESSING + // Handles incoming XCP commands -void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) +uint8_t XcpCommand( const uint32_t* cmdBuf, uint16_t cmdLen ) { + return XcpAsyncCommand(FALSE, cmdBuf, cmdLen); +} +// Handles incoming or asyncronous XCP commands +static uint8_t XcpAsyncCommand( BOOL async, const uint32_t* cmdBuf, uint16_t cmdLen ) { - + #define CRO ((tXcpCto*)cmdBuf) + #define CRO_LEN (cmdLen) + #define CRO_BYTE(x) (CRO->b[x]) + #define CRO_WORD(x) (CRO->w[x]) + #define CRO_DWORD(x) (CRO->dw[x]) + uint8_t err = 0; - if (!isStarted()) return; - if (cmdLen > sizeof(gXcp.Cro)) return; - - gXcp.CroLen = (uint8_t)cmdLen; - memcpy(&gXcp.Cro, cmdData, cmdLen); + if (!isStarted()) return CRC_GENERIC; + if (CRO_LEN > sizeof(tXcpCto)) return CRC_CMD_SYNTAX; // Prepare the default response CRM_CMD = PID_RES; /* Response, no error */ - gXcp.CrmLen = 1; /* Length = 1 */ + CRM_LEN = 1; /* Length = 1 */ // CONNECT ? -#if XCP_TRANSPORT_LAYER_TYPE == XCP_TRANSPORT_LAYER_ETH - if (cmdLen==CRO_CONNECT_LEN && CRO_CMD==CC_CONNECT) +#if XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN + if (CRO_LEN==CRO_CONNECT_LEN && CRO_CMD==CC_CONNECT) #else - if (cmdLen>=CRO_CONNECT_LEN && CRO_CMD==CC_CONNECT) + if (CRO_LEN>=CRO_CONNECT_LEN && CRO_CMD==CC_CONNECT) #endif { #ifdef DBG_LEVEL - DBG_PRINTF2("CONNECT mode=%u\n", CRO_CONNECT_MODE); - if (gXcp.SessionStatus & SS_CONNECTED) DBG_PRINT1(" Already connected! DAQ setup cleared! Legacy mode activated!\n"); + DBG_PRINTF3("CONNECT mode=%u\n", CRO_CONNECT_MODE); + if (gXcp.SessionStatus & SS_CONNECTED) DBG_PRINT_WARNING("WARNING: Already connected! DAQ setup cleared! Legacy mode activated!\n"); #endif // Check application is ready for XCP connect if (!ApplXcpConnect()) error(CRC_ACCESS_DENIED); // Initialize Session Status - gXcp.SessionStatus = (uint16_t)(SS_INITIALIZED | SS_STARTED | SS_CONNECTED | SS_LEGACY_MODE); + gXcp.SessionStatus = (SS_INITIALIZED | SS_STARTED | SS_CONNECTED | SS_LEGACY_MODE); /* Reset DAQ */ XcpFreeDaq(); // Response - gXcp.CrmLen = CRM_CONNECT_LEN; + CRM_LEN = CRM_CONNECT_LEN; CRM_CONNECT_TRANSPORT_VERSION = (uint8_t)( (uint16_t)XCP_TRANSPORT_LAYER_VERSION >> 8 ); /* Major versions of the XCP Protocol Layer and Transport Layer Specifications. */ CRM_CONNECT_PROTOCOL_VERSION = (uint8_t)( (uint16_t)XCP_PROTOCOL_LAYER_VERSION >> 8 ); CRM_CONNECT_MAX_CTO_SIZE = XCPTL_MAX_CTO_SIZE; @@ -938,28 +1096,43 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) else { #ifdef DBG_LEVEL - if (DBG_LEVEL >= 2) XcpPrintCmd(); + if (DBG_LEVEL >= 4 && !async) XcpPrintCmd(CRO); #endif if (!isConnected() && CRO_CMD!= CC_TRANSPORT_LAYER_CMD) { // Must be connected, exception are the transport layer commands - DBG_PRINT1("Command ignored because not in connected state, no response sent!\n"); - return; + DBG_PRINT_WARNING("WARNING: Command ignored because not in connected state, no response sent!\n"); + return CRC_CMD_IGNORED; } - if (cmdLen<1 || cmdLen>XCPTL_MAX_CTO_SIZE) error(CRC_CMD_SYNTAX); + if (CRO_LEN<1 || CRO_LEN>XCPTL_MAX_CTO_SIZE) error(CRC_CMD_SYNTAX); switch (CRO_CMD) { + + // User defined commands +#ifdef XCP_ENABLE_USER_COMMAND + case CC_USER_CMD: + { + check_len(CRO_USER_CMD_LEN); + check_error(ApplXcpUserCommand(CRO_USER_CMD_SUBCOMMAND)); + } + break; +#endif + + // Always return a negative response with the error code ERR_CMD_SYNCH case CC_SYNCH: { - /* Always return a negative response with the error code ERR_CMD_SYNCH. */ - gXcp.CrmLen = CRM_SYNCH_LEN; + CRM_LEN = CRM_SYNCH_LEN; CRM_CMD = PID_ERR; CRM_ERR = CRC_CMD_SYNCH; } break; + // Don_t respond, just ignore, no error unkwown command, used for testing + case CC_NOP: + goto no_response; + case CC_GET_COMM_MODE_INFO: { - gXcp.CrmLen = CRM_GET_COMM_MODE_INFO_LEN; + CRM_LEN = CRM_GET_COMM_MODE_INFO_LEN; CRM_GET_COMM_MODE_INFO_DRIVER_VERSION = XCP_DRIVER_VERSION; #ifdef XCP_ENABLE_INTERLEAVED CRM_GET_COMM_MODE_INFO_COMM_OPTIONAL = 0; // CMO_INTERLEAVED_MODE; @@ -998,7 +1171,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) #ifdef XCP_ENABLE_IDT_A2L_UPLOAD case IDT_ASAM_UPLOAD: gXcp.MtaAddr = 0; - gXcp.MtaExt = 0xFF; + gXcp.MtaExt = XCP_ADDR_EXT_A2L; CRM_GET_ID_LENGTH = ApplXcpGetId(CRO_GET_ID_TYPE, NULL, 0); CRM_GET_ID_MODE = 0x00; // Uncompressed data upload break; @@ -1009,9 +1182,40 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) } break; +/* Not implemented, no gXcp.ProtectionStatus checks */ +#if 0 +#ifdef XCP_ENABLE_SEED_KEY + case CC_GET_SEED: + { + if (CRO_GET_SEED_MODE != 0x00) error(CRC_OUT_OF_RANGE) + if ((gXcp.ProtectionStatus & CRO_GET_SEED_RESOURCE) != 0) { // locked + CRM_GET_SEED_LENGTH = ApplXcpGetSeed(CRO_GET_SEED_RESOURCE, CRM_GET_SEED_DATA);; + } else { // unlocked + CRM_GET_SEED_LENGTH = 0; // return 0 if the resource is unprotected + } + CRM_LEN = CRM_GET_SEED_LEN; + } + break; + + case CC_UNLOCK: + { + uint8_t resource = ApplXcpUnlock(CRO_UNLOCK_KEY, CRO_UNLOCK_LENGTH); + if (0x00 == resource) { // Key wrong !, send ERR_ACCESS_LOCKED and go to disconnected state + XcpDisconnect(); + error(CRC_ACCESS_LOCKED) + } else { + gXcp.ProtectionStatus &= ~resource; // unlock (reset) the appropriate resource protection mask bit + } + CRM_UNLOCK_PROTECTION = gXcp.ProtectionStatus; // return the current resource protection status + CRM_LEN = CRM_UNLOCK_LEN; + } + break; +#endif /* XCP_ENABLE_SEED_KEY */ +#endif + case CC_GET_STATUS: { - gXcp.CrmLen = CRM_GET_STATUS_LEN; + CRM_LEN = CRM_GET_STATUS_LEN; CRM_GET_STATUS_STATUS = (uint8_t)(gXcp.SessionStatus&0xFF); CRM_GET_STATUS_PROTECTION = 0; CRM_GET_STATUS_CONFIG_ID = 0; /* Session configuration ID not available. */ @@ -1021,36 +1225,40 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) case CC_SET_MTA: { check_len(CRO_SET_MTA_LEN); - gXcp.MtaExt = CRO_SET_MTA_EXT; - gXcp.MtaAddr = CRO_SET_MTA_ADDR; - gXcp.MtaPtr = NULL; - if (gXcp.MtaExt > 1) error(CRC_OUT_OF_RANGE); - if (gXcp.MtaExt == 0) { - gXcp.MtaPtr = ApplXcpGetPointer(gXcp.MtaExt, gXcp.MtaAddr); - } + check_error(XcpSetMta(CRO_SET_MTA_EXT, CRO_SET_MTA_ADDR)); } break; case CC_DOWNLOAD: { check_len(CRO_DOWNLOAD_LEN); - uint8_t size = CRO_DOWNLOAD_SIZE; // Variable cmdLen - if (size > CRO_DOWNLOAD_MAX_SIZE || size > cmdLen-CRO_DOWNLOAD_LEN) error(CRC_CMD_SYNTAX) - check_result(XcpWriteMta(size, CRO_DOWNLOAD_DATA)); + uint8_t size = CRO_DOWNLOAD_SIZE; // Variable CRO_LEN + if (size > CRO_DOWNLOAD_MAX_SIZE || size > CRO_LEN-CRO_DOWNLOAD_LEN) error(CRC_CMD_SYNTAX) +#ifdef XCP_ENABLE_DYN_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { + if (XcpPushCommand(CRO,CRO_LEN)==CRC_CMD_BUSY) goto busy_response; + goto no_response; + } +#endif + check_error(XcpWriteMta(size, CRO_DOWNLOAD_DATA)); } break; case CC_SHORT_DOWNLOAD: { check_len(CRO_SHORT_DOWNLOAD_LEN); - uint8_t size = CRO_SHORT_DOWNLOAD_SIZE; // Variable cmdLen - if (size > CRO_SHORT_DOWNLOAD_MAX_SIZE || size > cmdLen - CRO_SHORT_DOWNLOAD_LEN) error(CRC_CMD_SYNTAX) - if (!isCmdPending()) { - gXcp.MtaExt = CRO_SHORT_DOWNLOAD_EXT; - gXcp.MtaAddr = CRO_SHORT_DOWNLOAD_ADDR; - gXcp.MtaPtr = ApplXcpGetPointer(gXcp.MtaExt, gXcp.MtaAddr); + uint8_t size = CRO_SHORT_DOWNLOAD_SIZE; // Variable CRO_LEN + if (size > CRO_SHORT_DOWNLOAD_MAX_SIZE || size > CRO_LEN - CRO_SHORT_DOWNLOAD_LEN) error(CRC_CMD_SYNTAX); + if (!async) { // When SHORT_DOWNLOAD is executed async, MtaXxx was already set + check_error(XcpSetMta(CRO_SHORT_DOWNLOAD_EXT, CRO_SHORT_DOWNLOAD_ADDR)); } - check_result(XcpWriteMta(size, CRO_SHORT_DOWNLOAD_DATA)); +#ifdef XCP_ENABLE_DYN_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { + if (XcpPushCommand(CRO,CRO_LEN)==CRC_CMD_BUSY) goto busy_response; + goto no_response; + } +#endif + check_error(XcpWriteMta(size, CRO_SHORT_DOWNLOAD_DATA)); } break; @@ -1059,8 +1267,14 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) check_len(CRO_UPLOAD_LEN); uint8_t size = CRO_UPLOAD_SIZE; if (size > CRM_UPLOAD_MAX_SIZE) error(CRC_OUT_OF_RANGE); - check_result(XcpReadMta(size,CRM_UPLOAD_DATA)); - gXcp.CrmLen = (uint8_t)(CRM_UPLOAD_LEN+size); +#ifdef XCP_ENABLE_DYN_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { + if (XcpPushCommand(CRO,CRO_LEN)==CRC_CMD_BUSY) goto busy_response; + goto no_response; + } +#endif + check_error(XcpReadMta(size,CRM_UPLOAD_DATA)); + CRM_LEN = (uint8_t)(CRM_UPLOAD_LEN+size); } break; @@ -1069,13 +1283,17 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) check_len(CRO_SHORT_UPLOAD_LEN); uint8_t size = CRO_SHORT_UPLOAD_SIZE; if (size > CRM_SHORT_UPLOAD_MAX_SIZE) error(CRC_OUT_OF_RANGE); - if (!isCmdPending()) { - gXcp.MtaExt = CRO_SHORT_UPLOAD_EXT; - gXcp.MtaAddr = CRO_SHORT_UPLOAD_ADDR; - gXcp.MtaPtr = ApplXcpGetPointer(gXcp.MtaExt, gXcp.MtaAddr); + if (!async) { // When SHORT_UPLOAD is executed async, MtaXxx was already set + check_error(XcpSetMta(CRO_SHORT_UPLOAD_EXT,CRO_SHORT_UPLOAD_ADDR)); } - check_result(XcpReadMta(size,CRM_SHORT_UPLOAD_DATA)); - gXcp.CrmLen = (uint8_t)(CRM_SHORT_UPLOAD_LEN+size); +#ifdef XCP_ENABLE_DYN_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { + if (XcpPushCommand(CRO,CRO_LEN)==CRC_CMD_BUSY) goto busy_response; + goto no_response; + } +#endif + check_error(XcpReadMta(size,CRM_SHORT_UPLOAD_DATA)); + CRM_LEN = (uint8_t)(CRM_SHORT_UPLOAD_LEN+size); } break; @@ -1090,36 +1308,98 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) case CC_GET_CAL_PAGE: { check_len(CRO_GET_CAL_PAGE_LEN); - gXcp.CrmLen = CRM_GET_CAL_PAGE_LEN; - CRM_GET_CAL_PAGE_PAGE = ApplXcpGetCalPage(CRO_GET_CAL_PAGE_SEGMENT, CRO_GET_CAL_PAGE_MODE); + CRM_LEN = CRM_GET_CAL_PAGE_LEN; + uint8_t page = ApplXcpGetCalPage(CRO_GET_CAL_PAGE_SEGMENT, CRO_GET_CAL_PAGE_MODE); + if (page == 0xFF) error(CRC_PAGE_MODE_NOT_VALID); + CRM_GET_CAL_PAGE_PAGE = page; } break; + + #ifdef XCP_ENABLE_COPY_CAL_PAGE + case CC_COPY_CAL_PAGE: + { + CRM_LEN = CRM_COPY_CAL_PAGE_LEN; + check_error( ApplXcpCopyCalPage(CRO_COPY_CAL_PAGE_SRC_SEGMENT,CRO_COPY_CAL_PAGE_SRC_PAGE,CRO_COPY_CAL_PAGE_DEST_SEGMENT,CRO_COPY_CAL_PAGE_DEST_PAGE) ) + } + break; + #endif // XCP_ENABLE_COPY_CAL_PAGE + + #ifdef XCP_ENABLE_FREEZE_CAL_PAGE // @@@@ ToDo: Only 1 segment supported yet + case CC_GET_PAG_PROCESSOR_INFO: + { + check_len(CRO_GET_PAG_PROCESSOR_INFO_LEN); + CRM_LEN = CRM_GET_PAG_PROCESSOR_INFO_LEN; + CRM_GET_PAG_PROCESSOR_INFO_MAX_SEGMENT = 1; + CRM_GET_PAG_PROCESSOR_INFO_PROPERTIES = PAG_PROPERTY_FREEZE; + } + break; + + /* case CC_GET_SEGMENT_INFO: break; not implemented */ + /* case CC_GET_PAGE_INFO: not implemented */ + + case CC_SET_SEGMENT_MODE: + { + check_len(CRO_SET_SEGMENT_MODE_LEN); + if (CRO_SET_SEGMENT_MODE_SEGMENT>0) error(CRC_OUT_OF_RANGE) + CRM_LEN = CRM_SET_SEGMENT_MODE_LEN; + gXcp.SegmentMode = CRO_SET_SEGMENT_MODE_MODE; + } + break; + + case CC_GET_SEGMENT_MODE: + { + check_len(CRO_GET_SEGMENT_MODE_LEN); + if (CRO_GET_SEGMENT_MODE_SEGMENT>0) error(CRC_OUT_OF_RANGE) + CRM_LEN = CRM_GET_SEGMENT_MODE_LEN; + CRM_GET_SEGMENT_MODE_MODE = gXcp.SegmentMode; + } + break; + + case CC_SET_REQUEST: + { + check_len(CRO_SET_REQUEST_LEN); + CRM_LEN = CRM_SET_REQUEST_LEN; + if (CRO_SET_REQUEST_MODE & SET_REQUEST_MODE_STORE_CAL) check_error(ApplXcpFreezeCalPage(0)); + } + break; + #endif // XCP_ENABLE_FREEZE_CAL_PAGE #endif // XCP_ENABLE_CAL_PAGE #ifdef XCP_ENABLE_CHECKSUM case CC_BUILD_CHECKSUM: { check_len(CRO_BUILD_CHECKSUM_LEN); + #ifdef XCP_ENABLE_DYN_ADDRESSING + if (gXcp.MtaExt == XCP_ADDR_EXT_DYN) { XcpPushCommand(CRO,CRO_LEN); goto no_response;} // Execute in async mode + #endif uint32_t n = CRO_BUILD_CHECKSUM_SIZE; uint32_t s = 0; uint32_t d,i; - //if (n % 4 != 0) error(CRC_OUT_OF_RANGE) - //n = n / 4; - n = (n + 3) / 4; - for (i = 0; i < n; i++) { - check_error(XcpReadMta(4, (uint8_t*)&d)); - s += d; + // Switch to XCP_CHECKSUM_TYPE_ADD41 if n is not a multiple of 4 + if (n % 4 != 0) { + for (i = 0; i < n; i++) { + check_error(XcpReadMta(1, (uint8_t*)&d)); + s += d; + } + CRM_BUILD_CHECKSUM_RESULT = s; + CRM_BUILD_CHECKSUM_TYPE = XCP_CHECKSUM_TYPE_ADD11; + } else { + n = n / 4; + for (i = 0; i < n; i++) { + check_error(XcpReadMta(4, (uint8_t*)&d)); + s += d; + } + CRM_BUILD_CHECKSUM_RESULT = s; + CRM_BUILD_CHECKSUM_TYPE = XCP_CHECKSUM_TYPE_ADD44; } - CRM_BUILD_CHECKSUM_RESULT = s; - CRM_BUILD_CHECKSUM_TYPE = XCP_CHECKSUM_TYPE_ADD44; - gXcp.CrmLen = CRM_BUILD_CHECKSUM_LEN; + CRM_LEN = CRM_BUILD_CHECKSUM_LEN; } break; #endif // XCP_ENABLE_CHECKSUM case CC_GET_DAQ_PROCESSOR_INFO: { - gXcp.CrmLen = CRM_GET_DAQ_PROCESSOR_INFO_LEN; + CRM_LEN = CRM_GET_DAQ_PROCESSOR_INFO_LEN; CRM_GET_DAQ_PROCESSOR_INFO_MIN_DAQ = 0; CRM_GET_DAQ_PROCESSOR_INFO_MAX_DAQ = (gXcp.Daq.DaqCount); /* dynamic */ #if defined ( XCP_ENABLE_DAQ_EVENT_INFO ) @@ -1134,7 +1414,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) case CC_GET_DAQ_RESOLUTION_INFO: { - gXcp.CrmLen = CRM_GET_DAQ_RESOLUTION_INFO_LEN; + CRM_LEN = CRM_GET_DAQ_RESOLUTION_INFO_LEN; CRM_GET_DAQ_RESOLUTION_INFO_GRANULARITY_DAQ = 1; CRM_GET_DAQ_RESOLUTION_INFO_GRANULARITY_STIM = 1; CRM_GET_DAQ_RESOLUTION_INFO_MAX_SIZE_DAQ = (uint8_t)XCP_MAX_ODT_ENTRY_SIZE; @@ -1151,19 +1431,18 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) uint16_t eventNumber = CRO_GET_DAQ_EVENT_INFO_EVENT; tXcpEvent* event = XcpGetEvent(eventNumber); if (event==NULL) error(CRC_OUT_OF_RANGE); - gXcp.CrmLen = CRM_GET_DAQ_EVENT_INFO_LEN; + CRM_LEN = CRM_GET_DAQ_EVENT_INFO_LEN; CRM_GET_DAQ_EVENT_INFO_PROPERTIES = DAQ_EVENT_PROPERTIES_DAQ | DAQ_EVENT_PROPERTIES_EVENT_CONSISTENCY; -#ifdef XCP_ENABLE_PACKED_MODE + #ifdef XCP_ENABLE_PACKED_MODE if (ApplXcpEventList[event].sampleCount) CRM_GET_DAQ_EVENT_INFO_PROPERTIES |= DAQ_EVENT_PROPERTIES_PACKED; -#endif - // if (event->size) CRM_GET_DAQ_EVENT_INFO_PROPERTIES |= DAQ_EVENT_PROPERTIES_EXT; @@@@ V1.6 + #endif CRM_GET_DAQ_EVENT_INFO_MAX_DAQ_LIST = 0xFF; CRM_GET_DAQ_EVENT_INFO_NAME_LENGTH = (uint8_t)strlen(event->name); CRM_GET_DAQ_EVENT_INFO_TIME_CYCLE = event->timeCycle; CRM_GET_DAQ_EVENT_INFO_TIME_UNIT = event->timeUnit; CRM_GET_DAQ_EVENT_INFO_PRIORITY = event->priority; gXcp.MtaPtr = (uint8_t*)event->name; - gXcp.MtaExt = 0; + gXcp.MtaExt = XCP_ADDR_EXT_PTR; } break; #endif // XCP_ENABLE_DAQ_EVENT_INFO @@ -1208,7 +1487,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) check_len(CRO_GET_DAQ_LIST_MODE_LEN); uint16_t daq = CRO_GET_DAQ_LIST_MODE_DAQ; if (daq >= gXcp.Daq.DaqCount) error(CRC_OUT_OF_RANGE); - gXcp.CrmLen = CRM_GET_DAQ_LIST_MODE_LEN; + CRM_LEN = CRM_GET_DAQ_LIST_MODE_LEN; CRM_GET_DAQ_LIST_MODE_MODE = DaqListMode(daq); CRM_GET_DAQ_LIST_MODE_PRESCALER = 1; CRM_GET_DAQ_LIST_MODE_EVENTCHANNEL = DaqListEventChannel(daq); @@ -1231,7 +1510,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) break; } - case CC_SET_DAQ_PTR: + case CC_SET_DAQ_PTR: { check_len(CRO_SET_DAQ_PTR_LEN); uint16_t daq = CRO_SET_DAQ_PTR_DAQ; @@ -1269,7 +1548,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) if (CRO_START_STOP_DAQ_LIST_MODE == 1) { // start individual daq list XcpStartDaq(daq); } - gXcp.CrmLen = CRM_START_STOP_DAQ_LIST_LEN; + CRM_LEN = CRM_START_STOP_DAQ_LIST_LEN; CRM_START_STOP_DAQ_LIST_FIRST_PID = 0; // Absolute DAQ, Relative ODT - DaqListFirstPid(daq); } else { @@ -1296,9 +1575,9 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) break; case 1: /* start selected */ if (!ApplXcpStartDaq()) error(CRC_RESOURCE_TEMPORARY_NOT_ACCESSIBLE); - XcpSendResponse(); // Transmit response and then start DAQ + XcpSendResponse(&CRM, CRM_LEN); // Transmit response first and then start DAQ XcpStartAllSelectedDaq(); - return; + goto no_response; // Do not send response again case 0: /* stop all */ ApplXcpStopDaq(); XcpStopAllDaq(); @@ -1311,42 +1590,42 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) } break; -#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 && XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH +#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 && XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN case CC_TIME_CORRELATION_PROPERTIES: { check_len(CRO_TIME_SYNCH_PROPERTIES_LEN); - gXcp.CrmLen = CRM_TIME_SYNCH_PROPERTIES_LEN; + CRM_LEN = CRM_TIME_SYNCH_PROPERTIES_LEN; if ((CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_RESPONSE_FMT) >= 1) { // set extended format - DBG_PRINTF2(" Timesync extended mode activated (RESPONSE_FMT=%u)\n", CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_RESPONSE_FMT); - gXcp.SessionStatus &= (uint16_t)~SS_LEGACY_MODE; + DBG_PRINTF4(" Timesync extended mode activated (RESPONSE_FMT=%u)\n", CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_RESPONSE_FMT); + gXcp.SessionStatus &= ~SS_LEGACY_MODE; } -#ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST + #ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST if (CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_CLUSTER_ID) { // set cluster id - DBG_PRINTF2(" Cluster id set to %u\n", CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID); + DBG_PRINTF4(" Cluster id set to %u\n", CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID); gXcp.ClusterId = CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID; // Set cluster id XcpEthTlSetClusterId(gXcp.ClusterId); } CRM_TIME_SYNCH_PROPERTIES_CLUSTER_ID = gXcp.ClusterId; -#else + #else if (CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_CLUSTER_ID) { // set cluster id //error(CRC_OUT_OF_RANGE); // CANape insists on setting a cluster id, even if Multicast is not enabled - DBG_PRINTF2(" Cluster id = %u setting ignored\n", CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID); + DBG_PRINTF4(" Cluster id = %u setting ignored\n", CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID); } CRM_TIME_SYNCH_PROPERTIES_CLUSTER_ID = 0; -#endif + #endif if (CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES & TIME_SYNCH_SET_PROPERTIES_TIME_SYNCH_BRIDGE) error(CRC_OUT_OF_RANGE); // set time sync bride is not supported -> error CRM_TIME_SYNCH_PROPERTIES_SERVER_CONFIG = SERVER_CONFIG_RESPONSE_FMT_ADVANCED | SERVER_CONFIG_DAQ_TS_SERVER | SERVER_CONFIG_TIME_SYNCH_BRIDGE_NONE; // SERVER_CONFIG_RESPONSE_FMT_LEGACY CRM_TIME_SYNCH_PROPERTIES_RESERVED = 0x0; -#ifndef XCP_ENABLE_PTP + #ifndef XCP_ENABLE_PTP CRM_TIME_SYNCH_PROPERTIES_OBSERVABLE_CLOCKS = LOCAL_CLOCK_FREE_RUNNING | GRANDM_CLOCK_NONE | ECU_CLOCK_NONE; CRM_TIME_SYNCH_PROPERTIES_SYNCH_STATE = LOCAL_CLOCK_STATE_FREE_RUNNING; CRM_TIME_SYNCH_PROPERTIES_CLOCK_INFO = CLOCK_INFO_SERVER; -#else // XCP_ENABLE_PTP + #else // XCP_ENABLE_PTP if (ApplXcpGetClockInfoGrandmaster(gXcp.ClockInfo.grandmaster.UUID, &gXcp.ClockInfo.grandmaster.epochOfGrandmaster, &gXcp.ClockInfo.grandmaster.stratumLevel)) { // Update UUID and clock details CRM_TIME_SYNCH_PROPERTIES_OBSERVABLE_CLOCKS = LOCAL_CLOCK_SYNCHED | GRANDM_CLOCK_READABLE | ECU_CLOCK_NONE; - DBG_PRINTF1(" GrandmasterClock: UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X stratumLevel=%u, epoch=%u\n", gXcp.ClockInfo.grandmaster.UUID[0], gXcp.ClockInfo.grandmaster.UUID[1], gXcp.ClockInfo.grandmaster.UUID[2], gXcp.ClockInfo.grandmaster.UUID[3], gXcp.ClockInfo.grandmaster.UUID[4], gXcp.ClockInfo.grandmaster.UUID[5], gXcp.ClockInfo.grandmaster.UUID[6], gXcp.ClockInfo.grandmaster.UUID[7], gXcp.ClockInfo.grandmaster.stratumLevel, gXcp.ClockInfo.grandmaster.epochOfGrandmaster); + DBG_PRINTF4(" GrandmasterClock: UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X stratumLevel=%u, epoch=%u\n", gXcp.ClockInfo.grandmaster.UUID[0], gXcp.ClockInfo.grandmaster.UUID[1], gXcp.ClockInfo.grandmaster.UUID[2], gXcp.ClockInfo.grandmaster.UUID[3], gXcp.ClockInfo.grandmaster.UUID[4], gXcp.ClockInfo.grandmaster.UUID[5], gXcp.ClockInfo.grandmaster.UUID[6], gXcp.ClockInfo.grandmaster.UUID[7], gXcp.ClockInfo.grandmaster.stratumLevel, gXcp.ClockInfo.grandmaster.epochOfGrandmaster); CRM_TIME_SYNCH_PROPERTIES_SYNCH_STATE = ApplXcpGetClockState(); - DBG_PRINTF1(" SyncState: %u\n", CRM_TIME_SYNCH_PROPERTIES_SYNCH_STATE); + DBG_PRINTF4(" SyncState: %u\n", CRM_TIME_SYNCH_PROPERTIES_SYNCH_STATE); CRM_TIME_SYNCH_PROPERTIES_CLOCK_INFO = CLOCK_INFO_SERVER | CLOCK_INFO_GRANDM | CLOCK_INFO_RELATION; } else { @@ -1354,16 +1633,17 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) CRM_TIME_SYNCH_PROPERTIES_SYNCH_STATE = LOCAL_CLOCK_STATE_FREE_RUNNING; CRM_TIME_SYNCH_PROPERTIES_CLOCK_INFO = CLOCK_INFO_SERVER; } -#endif // XCP_ENABLE_PTP + #endif // XCP_ENABLE_PTP if (CRO_TIME_SYNCH_PROPERTIES_GET_PROPERTIES_REQUEST & TIME_SYNCH_GET_PROPERTIES_GET_CLK_INFO) { // check whether MTA based upload is requested gXcp.MtaPtr = (uint8_t*)&gXcp.ClockInfo.server; - gXcp.MtaExt = 0; + gXcp.MtaExt = XCP_ADDR_EXT_PTR; } } break; #endif // >= 0x0103 -#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 +#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 && XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH + case CC_TRANSPORT_LAYER_CMD: switch (CRO_TL_SUBCOMMAND) { @@ -1378,7 +1658,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) CRM_GET_DAQ_CLOCK_MCAST_TRIGGER_INFO = 0x18 + 0x02; // TIME_OF_SAMPLING (Bitmask 0x18, 3 - Sampled on reception) + TRIGGER_INITIATOR ( Bitmask 0x07, 2 - GET_DAQ_CLOCK_MULTICAST) if (!isLegacyMode()) { // Extended format #ifdef XCP_DAQ_CLOCK_64BIT - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_MCAST_LEN + 8; + CRM_LEN = CRM_GET_DAQ_CLOCK_MCAST_LEN + 8; CRM_GET_DAQ_CLOCK_MCAST_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_ID| DAQ_CLOCK_PAYLOAD_FMT_SLV_64; // size of timestamp is DLONG + CLUSTER_ID CRM_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER64 = CRO_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER; CRM_GET_DAQ_CLOCK_MCAST_COUNTER64 = CRO_GET_DAQ_CLOCK_MCAST_COUNTER; @@ -1387,18 +1667,18 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) CRM_GET_DAQ_CLOCK_MCAST_TIME64_HIGH = (uint32_t)(clock >> 32); CRM_GET_DAQ_CLOCK_MCAST_SYNCH_STATE64 = ApplXcpGetClockState(); #else - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_MCAST_LEN + 4; + CRM_LEN = CRM_GET_DAQ_CLOCK_MCAST_LEN + 4; CRM_GET_DAQ_CLOCK_MCAST_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_ID | DAQ_CLOCK_PAYLOAD_FMT_SLV_32; // size of timestamp is DWORD + CLUSTER_ID CRM_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER = CRO_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER; CRM_GET_DAQ_CLOCK_MCAST_COUNTER = CRO_GET_DAQ_CLOCK_MCAST_COUNTER; CRM_GET_DAQ_CLOCK_MCAST_TIME = (uint32_t)ApplXcpGetClock64(); CRM_GET_DAQ_CLOCK_MCAST_SYNCH_STATE = ApplXcpGetClockState(); #endif - if (gXcp.CrmLen> XCPTL_MAX_CTO_SIZE) error(CRC_CMD_UNKNOWN); // Extended mode needs enough CTO size + if (CRM_LEN> XCPTL_MAX_CTO_SIZE) error(CRC_CMD_UNKNOWN); // Extended mode needs enough CTO size } else { // Legacy format - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_MCAST_LEN; + CRM_LEN = CRM_GET_DAQ_CLOCK_MCAST_LEN; CRM_GET_DAQ_CLOCK_MCAST_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_SLV_32; // size of timestamp is DWORD CRM_GET_DAQ_CLOCK_MCAST_TIME = (uint32_t)ApplXcpGetClock64(); } @@ -1406,40 +1686,42 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) break; #endif // XCP_ENABLE_DAQ_CLOCK_MULTICAST - #if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH - case CC_TL_GET_SERVER_ID: + #if XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN + case CC_TL_GET_SERVER_ID: goto no_response; // Not supported, no response, response has atypical layout - case CC_TL_GET_SERVER_ID_EXTENDED: - check_len(CRO_TL_GET_SERVER_ID_LEN); - BOOL server_isTCP; - uint16_t server_port; - uint8_t server_addr[4]; - uint8_t server_mac[6]; - uint16_t client_port; - uint8_t client_addr[4]; - client_port = CRO_TL_GET_SERVER_ID_PORT; - memcpy(client_addr, &CRO_TL_GET_SERVER_ID_ADDR(0), 4); - XcpEthTlGetInfo(&server_isTCP, server_mac, server_addr, &server_port); - memcpy(&CRM_TL_GET_SERVER_ID_ADDR(0),server_addr,4); - CRM_TL_GET_SERVER_ID_PORT = server_port; - CRM_TL_GET_SERVER_ID_STATUS = - (server_isTCP ? GET_SERVER_ID_STATUS_PROTOCOL_TCP : GET_SERVER_ID_STATUS_PROTOCOL_UDP) | // protocol type - (isConnected() ? GET_SERVER_ID_STATUS_SLV_AVAILABILITY_BUSY : 0) | // In use - 0; // TL_SLV_DETECT_STATUS_SLV_ID_EXT_SUPPORTED; // GET_SERVER_ID_EXTENDET supported - CRM_TL_GET_SERVER_ID_RESOURCE = RM_DAQ; - CRM_TL_GET_SERVER_ID_ID_LEN = (uint8_t)ApplXcpGetId(IDT_ASCII, &CRM_TL_GET_SERVER_ID_ID, CRM_TL_GET_SERVER_ID_MAX_LEN); - memcpy((uint8_t*)&CRM_TL_GET_SERVER_ID_MAC(CRM_TL_GET_SERVER_ID_ID_LEN), server_mac, 6); - gXcp.CrmLen = (uint8_t)CRM_TL_GET_SERVER_ID_LEN(CRM_TL_GET_SERVER_ID_ID_LEN); - XcpSendMulticastResponse(client_addr,client_port); // Transmit multicast command response + case CC_TL_GET_SERVER_ID_EXTENDED: + #ifdef PLATFORM_ENABLE_GET_LOCAL_ADDR + check_len(CRO_TL_GET_SERVER_ID_LEN); + BOOL server_isTCP; + uint16_t server_port; + uint8_t server_addr[4]; + uint8_t server_mac[6]; + uint16_t client_port; + uint8_t client_addr[4]; + client_port = CRO_TL_GET_SERVER_ID_PORT; + memcpy(client_addr, &CRO_TL_GET_SERVER_ID_ADDR(0), 4); + XcpEthTlGetInfo(&server_isTCP, server_mac, server_addr, &server_port); + memcpy(&CRM_TL_GET_SERVER_ID_ADDR(0),server_addr,4); + CRM_TL_GET_SERVER_ID_PORT = server_port; + CRM_TL_GET_SERVER_ID_STATUS = + (server_isTCP ? GET_SERVER_ID_STATUS_PROTOCOL_TCP : GET_SERVER_ID_STATUS_PROTOCOL_UDP) | // protocol type + (isConnected() ? GET_SERVER_ID_STATUS_SLV_AVAILABILITY_BUSY : 0) | // In use + 0; // TL_SLV_DETECT_STATUS_SLV_ID_EXT_SUPPORTED; // GET_SERVER_ID_EXTENDED supported + CRM_TL_GET_SERVER_ID_RESOURCE = RM_DAQ; + CRM_TL_GET_SERVER_ID_ID_LEN = (uint8_t)ApplXcpGetId(IDT_ASCII, &CRM_TL_GET_SERVER_ID_ID, CRM_TL_GET_SERVER_ID_MAX_LEN); + memcpy((uint8_t*)&CRM_TL_GET_SERVER_ID_MAC(CRM_TL_GET_SERVER_ID_ID_LEN), server_mac, 6); + CRM_LEN = (uint8_t)CRM_TL_GET_SERVER_ID_LEN(CRM_TL_GET_SERVER_ID_ID_LEN); + XcpSendMulticastResponse(&CRM, CRM_LEN,client_addr,client_port); // Transmit multicast command response + #endif // PLATFORM_ENABLE_GET_LOCAL_ADDR goto no_response; - #endif + #endif // !XCP_TRANSPORT_LAYER_CAN - case 0: - default: /* unknown transport layer command */ + case 0: + default: /* unknown transport layer command */ error(CRC_CMD_UNKNOWN); - } + } break; #endif // >= 0x0103 @@ -1450,25 +1732,25 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) CRM_GET_DAQ_CLOCK_TRIGGER_INFO = 0x18; // TIME_OF_SAMPLING (Bitmask 0x18, 3 - Sampled on reception) if (!isLegacyMode()) { // Extended format #ifdef XCP_DAQ_CLOCK_64BIT - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_LEN + 5; + CRM_LEN = CRM_GET_DAQ_CLOCK_LEN + 5; CRM_GET_DAQ_CLOCK_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_SLV_64;// FMT_XCP_SLV = size of timestamp is DLONG uint64_t clock = ApplXcpGetClock64(); CRM_GET_DAQ_CLOCK_TIME64_LOW = (uint32_t)(clock); CRM_GET_DAQ_CLOCK_TIME64_HIGH = (uint32_t)(clock >> 32); CRM_GET_DAQ_CLOCK_SYNCH_STATE64 = ApplXcpGetClockState(); #else - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_LEN + 1; + CRM_LEN = CRM_GET_DAQ_CLOCK_LEN + 1; CRM_GET_DAQ_CLOCK_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_SLV_32; // FMT_XCP_SLV = size of timestamp is DWORD CRM_GET_DAQ_CLOCK_TIME = (uint32_t)ApplXcpGetClock64(); CRM_GET_DAQ_CLOCK_SYNCH_STATE = ApplXcpGetClockState(); #endif - if (gXcp.CrmLen > XCPTL_MAX_CTO_SIZE) error(CRC_CMD_UNKNOWN); // Extended mode needs enough CTO size + if (CRM_LEN > XCPTL_MAX_CTO_SIZE) error(CRC_CMD_UNKNOWN); // Extended mode needs enough CTO size } else #endif // >= 0x0103 { // Legacy format CRM_GET_DAQ_CLOCK_PAYLOAD_FMT = DAQ_CLOCK_PAYLOAD_FMT_SLV_32; // FMT_XCP_SLV = size of timestamp is DWORD - gXcp.CrmLen = CRM_GET_DAQ_CLOCK_LEN; + CRM_LEN = CRM_GET_DAQ_CLOCK_LEN; CRM_GET_DAQ_CLOCK_TIME = (uint32_t)ApplXcpGetClock64(); } } @@ -1480,7 +1762,7 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) /* Major and minor versions */ case CC_GET_VERSION: - gXcp.CrmLen = CRM_GET_VERSION_LEN; + CRM_LEN = CRM_GET_VERSION_LEN; CRM_GET_VERSION_RESERVED = 0; CRM_GET_VERSION_PROTOCOL_VERSION_MAJOR = (uint8_t)((uint16_t)XCP_PROTOCOL_LAYER_VERSION >> 8); CRM_GET_VERSION_PROTOCOL_VERSION_MINOR = (uint8_t)(XCP_PROTOCOL_LAYER_VERSION & 0xFF); @@ -1514,58 +1796,98 @@ void XcpCommand( const uint32_t* cmdData, uint16_t cmdLen ) } // switch() } - // Transmit command response - XcpSendResponse(); - return; + // Transmit normal command response + XcpSendResponse(&CRM, CRM_LEN); + return CRC_CMD_OK; // Transmit error response - negative_response: - gXcp.CrmLen = 2; +negative_response: + CRM_LEN = 2; CRM_CMD = PID_ERR; CRM_ERR = err; - XcpSendResponse(); - return; + XcpSendResponse(&CRM, CRM_LEN); + return err; - // Return with no responce in case of async commands -#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH - no_response: - return; + // Transmit busy response, if another command is already pending + // Interleaved mode is not supported +#ifdef XCP_ENABLE_DYN_ADDRESSING +busy_response: + CRM_LEN = 2; + CRM_CMD = PID_ERR; + CRM_ERR = CRC_CMD_BUSY; + XcpSendResponse(&CRM, CRM_LEN); + return CRC_CMD_BUSY; #endif + + // No responce in these cases: + // - Transmit multicast command response + // - Command will be executed delayed, during execution of the associated synchronisation event +no_response: + return CRC_CMD_OK; } /***************************************************************************** | Event ******************************************************************************/ -void XcpSendEvent(uint8_t evc, const uint8_t* d, uint8_t l) +void XcpSendEvent(uint8_t ev, uint8_t evc, const uint8_t* d, uint8_t l) { - if (!isConnected()) return; - - uint8_t i; - if (isConnected()) { - CRM_BYTE(0) = PID_EV; /* Event*/ - CRM_BYTE(1) = evc; /* Event Code*/ - gXcp.CrmLen = 2; - for (i = 0; i < l; i++) CRM_BYTE(gXcp.CrmLen++) = d[i++]; - XcpSendResponse(); - } + if (isConnected()) return; + + tXcpCto crm; + crm.b[0] = ev; /* Event*/ + crm.b[1] = evc; /* Eventcode */ + uint8_t i; + for (i = 0; i < l && i < XCPTL_MAX_CTO_SIZE-4; i++) crm.b[i+2] = d[i]; + XcpTlSendCrm((const uint8_t*)&crm, l+2); } +/****************************************************************************/ +/* Print via SERV/SERV_TEXT */ +/****************************************************************************/ + +#if defined ( XCP_ENABLE_SERV_TEXT ) + +#ifndef XCPTL_QUEUED_CRM +#error "XcpPrint is not thread safe, when used without XCPTL_QUEUED_CRM" +#endif + +void XcpPrint( const char *str ) { + + if (!isConnected()) return; + + tXcpCto crm; + crm.b[0] = PID_SERV; /* Event*/ + crm.b[1] = 0x01; /* Eventcode SERV_TEXT */ + uint8_t i; + uint16_t l = strlen(str); + for (i = 0; i < l && i < XCPTL_MAX_CTO_SIZE-4; i++) crm.b[i+2] = str[i]; + crm.b[i+3] = '\n'; + crm.b[i+4] = 0; + XcpTlSendCrm((const uint8_t*)&crm, l+4); + //XcpTlFlushTransmitBuffer(); // Don't do this, as it will decrease performance of the transmit process +} + +#endif // XCP_ENABLE_SERV_TEXT + + /***************************************************************************** | Initialization of the XCP Protocol Layer ******************************************************************************/ void XcpInit( void ) { - if (gXcp.SessionStatus != SS_INITIALIZED) { - - assert(gXcp.SessionStatus == 0); + if (gXcp.SessionStatus == 0) { - /* Initialize all XCP variables to zero */ + // Initialize gXcp to zero memset((uint8_t*)&gXcp, 0, sizeof(gXcp)); + + #ifdef XCP_ENABLE_MULTITHREAD_CAL_EVENTS + mutexInit(&gXcp.CmdPendingMutex, FALSE, 1000); + #endif -#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH +#if XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 #ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST gXcp.ClusterId = XCP_MULTICAST_CLUSTER_ID; // XCP default cluster id (multicast addr 239,255,0,1, group 127,0,1 (mac 01-00-5E-7F-00-01) @@ -1574,81 +1896,82 @@ void XcpInit( void ) #endif #endif - /* Initialize the session status */ - gXcp.SessionStatus = 0; + // Initialize high resolution clock + clockInit(); + + gXcp.SessionStatus = SS_INITIALIZED; + } +} + +void XcpStart(void) +{ + if (!isInitialized()) return; + #ifdef DBG_LEVEL - DBG_PRINT1("\nInit XCP protocol layer\n"); + DBG_PRINT3("\nInit XCP protocol layer\n"); #ifndef XCP_MAX_EVENT #define XCP_MAX_EVENT 0 #endif - DBG_PRINTF1(" Version=%u.%u, MAXEV=%u, MAXCTO=%u, MAXDTO=%u, DAQMEM=%u, MAXDAQ=%u, MAXENTRY=%u, MAXENTRYSIZE=%u\n", XCP_PROTOCOL_LAYER_VERSION >> 8, XCP_PROTOCOL_LAYER_VERSION & 0xFF, XCP_MAX_EVENT, XCPTL_MAX_CTO_SIZE, XCPTL_MAX_DTO_SIZE, XCP_DAQ_MEM_SIZE, (1 << sizeof(uint16_t) * 8) - 1, (1 << sizeof(uint16_t) * 8) - 1, (1 << (sizeof(uint8_t) * 8)) - 1); - DBG_PRINTF1(" %u KiB memory used\n", (unsigned int)sizeof(gXcp) / 1024); - DBG_PRINT1(" Options=("); + DBG_PRINTF3(" Version=%u.%u, MAXEV=%u, MAXCTO=%u, MAXDTO=%u, DAQMEM=%u, MAXDAQ=%u, MAXENTRY=%u, MAXENTRYSIZE=%u\n", XCP_PROTOCOL_LAYER_VERSION >> 8, XCP_PROTOCOL_LAYER_VERSION & 0xFF, XCP_MAX_EVENT, XCPTL_MAX_CTO_SIZE, XCPTL_MAX_DTO_SIZE, XCP_DAQ_MEM_SIZE, (1 << sizeof(uint16_t) * 8) - 1, (1 << sizeof(uint16_t) * 8) - 1, (1 << (sizeof(uint8_t) * 8)) - 1); + DBG_PRINTF3(" %u KiB memory used\n", (unsigned int)sizeof(gXcp) / 1024); + DBG_PRINT3(" Options=("); // Print activated XCP protocol options -#ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST // Enable GET_DAQ_CLOCK_MULTICAST - DBG_PRINT1("DAQ_CLK_MULTICAST,"); -#endif -#ifdef XCP_DAQ_CLOCK_64BIT // Use 64 Bit time stamps - DBG_PRINT1("DAQ_CLK_64BIT,"); -#endif -#ifdef XCP_ENABLE_PTP // Enable server clock synchronized to PTP grandmaster clock - DBG_PRINT1("GM_CLK_INFO,"); -#endif -#ifdef XCP_ENABLE_PACKED_MODE // Enable packed DAQ events - DBG_PRINT1("PACKED_MODE,"); -#endif -#ifdef XCP_ENABLE_IDT_A2L_UPLOAD // Enable A2L upload to host - DBG_PRINT1("A2L_UPLOAD,"); -#endif -#ifdef XCP_ENABLE_IDT_A2L_HTTP_GET // Enable A2L upload to host - DBG_PRINT1("A2L_URL,"); -#endif -#ifdef XCP_ENABLE_DAQ_EVENT_LIST // Enable XCP event info by protocol or by A2L - DBG_PRINT1("DAQ_EVT_LIST,"); -#endif -#ifdef XCP_ENABLE_DAQ_EVENT_INFO // Enable XCP event info by protocol instead of A2L - DBG_PRINT1("DAQ_EVT_INFO,"); -#endif -#ifdef XCP_ENABLE_CHECKSUM // Enable BUILD_CHECKSUM command - DBG_PRINT1("CHECKSUM,"); -#endif -#ifdef XCP_ENABLE_INTERLEAVED // Enable interleaved command execution - DBG_PRINT1("INTERLEAVED,"); -#endif - DBG_PRINT1(")\n\n"); + #ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST // Enable GET_DAQ_CLOCK_MULTICAST + DBG_PRINT3("DAQ_CLK_MULTICAST,"); + #endif + #ifdef XCP_DAQ_CLOCK_64BIT // Use 64 Bit time stamps + DBG_PRINT3("DAQ_CLK_64BIT,"); + #endif + #ifdef XCP_ENABLE_PTP // Enable server clock synchronized to PTP grandmaster clock + DBG_PRINT3("GM_CLK_INFO,"); + #endif + #ifdef XCP_ENABLE_PACKED_MODE // Enable packed DAQ events + DBG_PRINT3("PACKED_MODE,"); + #endif + #ifdef XCP_ENABLE_IDT_A2L_UPLOAD // Enable A2L upload to host + DBG_PRINT3("A2L_UPLOAD,"); + #endif + #ifdef XCP_ENABLE_IDT_A2L_HTTP_GET // Enable A2L upload to host + DBG_PRINT3("A2L_URL,"); + #endif + #ifdef XCP_ENABLE_DAQ_EVENT_LIST // Enable XCP event info by protocol or by A2L + DBG_PRINT3("DAQ_EVT_LIST,"); + #endif + #ifdef XCP_ENABLE_DAQ_EVENT_INFO // Enable XCP event info by protocol instead of A2L + DBG_PRINT3("DAQ_EVT_INFO,"); + #endif + #ifdef XCP_ENABLE_CHECKSUM // Enable BUILD_CHECKSUM command + DBG_PRINT3("CHECKSUM,"); + #endif + #ifdef XCP_ENABLE_INTERLEAVED // Enable interleaved command execution + DBG_PRINT3("INTERLEAVED,"); + #endif + DBG_PRINT3(")\n\n"); #endif - gXcp.SessionStatus |= SS_INITIALIZED; - } -} - -void XcpStart(void) -{ - if (!isInitialized()) return; - -#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH -#if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 +#if XCP_TRANSPORT_LAYER_TYPE!=XCP_TRANSPORT_LAYER_CAN + #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 // XCP server clock default description gXcp.ClockInfo.server.timestampTicks = XCP_TIMESTAMP_TICKS; gXcp.ClockInfo.server.timestampUnit = XCP_TIMESTAMP_UNIT; gXcp.ClockInfo.server.stratumLevel = XCP_STRATUM_LEVEL_UNKNOWN; -#ifdef XCP_DAQ_CLOCK_64BIT + #ifdef XCP_DAQ_CLOCK_64BIT gXcp.ClockInfo.server.nativeTimestampSize = 8; // NATIVE_TIMESTAMP_SIZE_DLONG; gXcp.ClockInfo.server.valueBeforeWrapAround = 0xFFFFFFFFFFFFFFFFULL; -#else + #else gXcp.ClockInfo.server.nativeTimestampSize = 4; // NATIVE_TIMESTAMP_SIZE_LONG; gXcp.ClockInfo.server.valueBeforeWrapAround = 0xFFFFFFFFULL; -#endif -#endif // XCP_PROTOCOL_LAYER_VERSION >= 0x0103 -#ifdef XCP_ENABLE_PTP + #endif + #endif // XCP_PROTOCOL_LAYER_VERSION >= 0x0103 + #ifdef XCP_ENABLE_PTP uint8_t uuid[8] = XCP_DAQ_CLOCK_UIID; memcpy(gXcp.ClockInfo.server.UUID, uuid, 8); - DBG_PRINTF3(" ServerClock: ticks=%u, unit=%s, size=%u, UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\n", gXcp.ClockInfo.server.timestampTicks, (gXcp.ClockInfo.server.timestampUnit == DAQ_TIMESTAMP_UNIT_1NS) ? "ns" : "us", gXcp.ClockInfo.server.nativeTimestampSize, gXcp.ClockInfo.server.UUID[0], gXcp.ClockInfo.server.UUID[1], gXcp.ClockInfo.server.UUID[2], gXcp.ClockInfo.server.UUID[3], gXcp.ClockInfo.server.UUID[4], gXcp.ClockInfo.server.UUID[5], gXcp.ClockInfo.server.UUID[6], gXcp.ClockInfo.server.UUID[7]); + DBG_PRINTF4(" ServerClock: ticks=%u, unit=%s, size=%u, UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\n", gXcp.ClockInfo.server.timestampTicks, (gXcp.ClockInfo.server.timestampUnit == DAQ_TIMESTAMP_UNIT_1NS) ? "ns" : "us", gXcp.ClockInfo.server.nativeTimestampSize, gXcp.ClockInfo.server.UUID[0], gXcp.ClockInfo.server.UUID[1], gXcp.ClockInfo.server.UUID[2], gXcp.ClockInfo.server.UUID[3], gXcp.ClockInfo.server.UUID[4], gXcp.ClockInfo.server.UUID[5], gXcp.ClockInfo.server.UUID[6], gXcp.ClockInfo.server.UUID[7]); // If the server clock is PTP synchronized, both origin and local timestamps are considered to be the same. gXcp.ClockInfo.relation.timestampLocal = 0; @@ -1662,11 +1985,11 @@ void XcpStart(void) gXcp.ClockInfo.grandmaster.stratumLevel = XCP_STRATUM_LEVEL_UNKNOWN; gXcp.ClockInfo.grandmaster.epochOfGrandmaster = XCP_EPOCH_ARB; if (ApplXcpGetClockInfoGrandmaster(gXcp.ClockInfo.grandmaster.UUID, &gXcp.ClockInfo.grandmaster.epochOfGrandmaster, &gXcp.ClockInfo.grandmaster.stratumLevel)) { - DBG_PRINTF1(" GrandmasterClock: UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X stratumLevel=%u, epoch=%u\n", gXcp.ClockInfo.grandmaster.UUID[0], gXcp.ClockInfo.grandmaster.UUID[1], gXcp.ClockInfo.grandmaster.UUID[2], gXcp.ClockInfo.grandmaster.UUID[3], gXcp.ClockInfo.grandmaster.UUID[4], gXcp.ClockInfo.grandmaster.UUID[5], gXcp.ClockInfo.grandmaster.UUID[6], gXcp.ClockInfo.grandmaster.UUID[7], gXcp.ClockInfo.grandmaster.stratumLevel, gXcp.ClockInfo.grandmaster.epochOfGrandmaster); - DBG_PRINT1(" ClockRelation: local=0, origin=0\n"); + DBG_PRINTF5(" GrandmasterClock: UUID=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X stratumLevel=%u, epoch=%u\n", gXcp.ClockInfo.grandmaster.UUID[0], gXcp.ClockInfo.grandmaster.UUID[1], gXcp.ClockInfo.grandmaster.UUID[2], gXcp.ClockInfo.grandmaster.UUID[3], gXcp.ClockInfo.grandmaster.UUID[4], gXcp.ClockInfo.grandmaster.UUID[5], gXcp.ClockInfo.grandmaster.UUID[6], gXcp.ClockInfo.grandmaster.UUID[7], gXcp.ClockInfo.grandmaster.stratumLevel, gXcp.ClockInfo.grandmaster.epochOfGrandmaster); + DBG_PRINT5(" ClockRelation: local=0, origin=0\n"); } -#endif // PTP -#endif // XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH + #endif // PTP +#endif // XCP_TRANSPORT_LAYER_TYPE DBG_PRINT3("Start XCP protocol layer\n"); @@ -1697,20 +2020,20 @@ tXcpEvent* XcpGetEvent(uint16_t event) { } -// Create an XCP event, in ns, 0 = sporadic, 0-normal, >=1 realtime, only for packed mode events only, only for extended events -// Returns the XCP event number for XcpEventXxx() or 0xFFFF when out of memory +// Create an XCP event, in us, 0 = sporadic, 0-normal, >=1 realtime, only for packed mode events only, only for extended events +// Returns the XCP event number for XcpEventXxx() or XCP_UNDEFINED_EVENT when out of memory uint16_t XcpCreateEvent(const char* name, uint32_t cycleTimeNs, uint8_t priority, uint16_t sampleCount, uint32_t size) { uint16_t e; uint32_t c; if (!isInitialized()) { - DBG_PRINT1("ERROR: XCP driver not initialized\n"); - return (uint16_t)0xFFFF; // Uninitialized or out of memory + DBG_PRINT_ERROR("ERROR: XCP driver not initialized\n"); + return XCP_UNDEFINED_EVENT; // Uninitialized or out of memory } if (gXcp.EventCount >= XCP_MAX_EVENT) { - DBG_PRINT1("ERROR: XCP too many events\n"); - return (uint16_t)0xFFFF; // Uninitialized or out of memory + DBG_PRINT_ERROR("ERROR: XCP too many events\n"); + return XCP_UNDEFINED_EVENT; // timeUninitialized or out of memory } // Convert cycle time to ASAM coding time cycle and time unit @@ -1729,22 +2052,22 @@ uint16_t XcpCreateEvent(const char* name, uint32_t cycleTimeNs, uint8_t priority gXcp.EventList[e].priority = priority; gXcp.EventList[e].sampleCount = sampleCount; gXcp.EventList[e].size = size; -#ifdef XCP_ENABLE_TEST_CHECKS +#ifdef XCP_ENABLE_SELF_TEST gXcp.EventList[e].time = 0; #endif -#ifdef XCP_ENABLE_MULTITHREAD_EVENTS - mutexInit(&gXcp.EventList[e].mutex, 0, 1000); +#ifdef XCP_ENABLE_MULTITHREAD_DAQ_EVENTS + mutexInit(&gXcp.EventList[e].mutex, FALSE, 1000); #endif #ifdef DBG_LEVEL uint64_t ns = (uint64_t)(gXcp.EventList[e].timeCycle * pow(10, gXcp.EventList[e].timeUnit)); - DBG_PRINTF1(" Event %u: %s cycle=%" PRIu64 "ns, prio=%u, sc=%u, size=%u\n", e, gXcp.EventList[e].shortName, ns, gXcp.EventList[e].priority, gXcp.EventList[e].sampleCount, gXcp.EventList[e].size); - if (cycleTimeNs != ns) DBG_PRINTF1("Warning: cycle time %uns, loss of significant digits!\n", cycleTimeNs); + DBG_PRINTF3(" Event %u: %s cycle=%" PRIu64 "ns, prio=%u, sc=%u, size=%u\n", e, gXcp.EventList[e].shortName, ns, gXcp.EventList[e].priority, gXcp.EventList[e].sampleCount, gXcp.EventList[e].size); + if (cycleTimeNs != ns) DBG_PRINTF_WARNING("WARNING: cycle time %uns, loss of significant digits!\n", cycleTimeNs); #endif return gXcp.EventCount++; } -#endif +#endif // XCP_ENABLE_DAQ_EVENT_LIST /****************************************************************************/ @@ -1753,13 +2076,51 @@ uint16_t XcpCreateEvent(const char* name, uint32_t cycleTimeNs, uint8_t priority #ifdef DBG_LEVEL -static void XcpPrintCmd() { - - switch (CRO_CMD) { - - case CC_SET_MTA: - printf("SET_MTA addr=%08Xh, addrext=%02Xh\n", CRO_SET_MTA_ADDR, CRO_SET_MTA_EXT); - break; +static void XcpPrintCmd(const tXcpCto* cmdBuf) { + +#undef CRO_LEN +#undef CRO +#undef CRO_BYTE +#undef CRO_WORD +#undef CRO_DWORD +#define CRO_BYTE(x) (gXcp.CmdLast->b[x]) +#define CRO_WORD(x) (gXcp.CmdLast->w[x]) +#define CRO_DWORD(x) (gXcp.CmdLast->dw[x]) + + gXcp.CmdLast = cmdBuf; + switch (CRO_CMD) { + + case CC_SET_CAL_PAGE: printf("SET_CAL_PAGE segment=%u,page=%u,mode=%02Xh\n", CRO_SET_CAL_PAGE_SEGMENT, CRO_SET_CAL_PAGE_PAGE, CRO_SET_CAL_PAGE_MODE); break; + case CC_GET_CAL_PAGE: printf("GET_CAL_PAGE segment=%u, mode=%u\n", CRO_GET_CAL_PAGE_SEGMENT, CRO_GET_CAL_PAGE_MODE); break; + case CC_COPY_CAL_PAGE: printf("COPY_CAL_PAGE srcSegment=%u, srcPage=%u, dstSegment=%u, dstPage=%u\n", CRO_COPY_CAL_PAGE_SRC_SEGMENT,CRO_COPY_CAL_PAGE_SRC_PAGE,CRO_COPY_CAL_PAGE_DEST_SEGMENT,CRO_COPY_CAL_PAGE_DEST_PAGE); break; + case CC_GET_PAG_PROCESSOR_INFO: printf("GET_PAG_PROCESSOR_INFO\n"); break; + case CC_SET_SEGMENT_MODE: printf("SET_SEGMENT_MODE\n"); break; + case CC_GET_SEGMENT_MODE: printf("GET_SEGMENT_MODE\n"); break; + case CC_BUILD_CHECKSUM: printf("BUILD_CHECKSUM size=%u\n", CRO_BUILD_CHECKSUM_SIZE); break; + case CC_SET_MTA: printf("SET_MTA addr=%08Xh, addrext=%02Xh\n", CRO_SET_MTA_ADDR, CRO_SET_MTA_EXT); break; + case CC_SYNCH: printf("SYNCH\n"); break; + case CC_GET_COMM_MODE_INFO: printf("GET_COMM_MODE_INFO\n"); break; + case CC_DISCONNECT: printf("DISCONNECT\n"); break; + case CC_GET_ID: printf("GET_ID type=%u\n", CRO_GET_ID_TYPE); break; + case CC_GET_STATUS: printf("GET_STATUS\n"); break; + case CC_GET_DAQ_PROCESSOR_INFO: printf("GET_DAQ_PROCESSOR_INFO\n"); break; + case CC_GET_DAQ_RESOLUTION_INFO: printf("GET_DAQ_RESOLUTION_INFO\n"); break; + case CC_GET_DAQ_EVENT_INFO: printf("GET_DAQ_EVENT_INFO event=%u\n", CRO_GET_DAQ_EVENT_INFO_EVENT); break; + case CC_FREE_DAQ: printf("FREE_DAQ\n"); break; + case CC_ALLOC_DAQ: printf("ALLOC_DAQ count=%u\n", CRO_ALLOC_DAQ_COUNT); break; + case CC_ALLOC_ODT: printf("ALLOC_ODT daq=%u, count=%u\n", CRO_ALLOC_ODT_DAQ, CRO_ALLOC_ODT_COUNT); break; + case CC_ALLOC_ODT_ENTRY: printf("ALLOC_ODT_ENTRY daq=%u, odt=%u, count=%u\n", CRO_ALLOC_ODT_ENTRY_DAQ, CRO_ALLOC_ODT_ENTRY_ODT, CRO_ALLOC_ODT_ENTRY_COUNT); break; + case CC_GET_DAQ_LIST_MODE: printf("GET_DAQ_LIST_MODE daq=%u\n",CRO_GET_DAQ_LIST_MODE_DAQ ); break; + case CC_SET_DAQ_LIST_MODE: printf("SET_DAQ_LIST_MODE daq=%u, mode=%02Xh, eventchannel=%u\n",CRO_SET_DAQ_LIST_MODE_DAQ, CRO_SET_DAQ_LIST_MODE_MODE, CRO_SET_DAQ_LIST_MODE_EVENTCHANNEL); break; + case CC_SET_DAQ_PTR: printf("SET_DAQ_PTR daq=%u,odt=%u,idx=%u\n", CRO_SET_DAQ_PTR_DAQ, CRO_SET_DAQ_PTR_ODT, CRO_SET_DAQ_PTR_IDX); break; + case CC_WRITE_DAQ: printf("WRITE_DAQ size=%u,addr=%08Xh,%02Xh\n", CRO_WRITE_DAQ_SIZE, CRO_WRITE_DAQ_ADDR, CRO_WRITE_DAQ_EXT); break; + case CC_START_STOP_DAQ_LIST: printf("START_STOP mode=%s, daq=%u\n", (CRO_START_STOP_DAQ_LIST_MODE == 2)?"select": (CRO_START_STOP_DAQ_LIST_MODE == 1)?"start":"stop", CRO_START_STOP_DAQ_LIST_DAQ); break; + case CC_START_STOP_SYNCH: printf("CC_START_STOP_SYNCH mode=%s\n", (CRO_START_STOP_SYNCH_MODE == 3) ? "prepare" : (CRO_START_STOP_SYNCH_MODE == 2) ? "stop_selected" : (CRO_START_STOP_SYNCH_MODE == 1) ? "start_selected" : "stop_all"); break; + case CC_GET_DAQ_CLOCK: printf("GET_DAQ_CLOCK\n"); break; + + case CC_USER_CMD: + printf("USER_CMD SUB_COMMAND=%02X\n",CRO_USER_CMD_SUBCOMMAND); + break; case CC_DOWNLOAD: { @@ -1773,142 +2134,43 @@ static void XcpPrintCmd() { break; case CC_SHORT_DOWNLOAD: - if (DBG_LEVEL >= 3) { - uint16_t i; - printf("SHORT_DOWNLOAD addr=%08Xh, addrext=%02Xh, size=%u, data=", CRO_SHORT_DOWNLOAD_ADDR, CRO_SHORT_DOWNLOAD_EXT, CRO_SHORT_DOWNLOAD_SIZE); - for (i = 0; (i < CRO_SHORT_DOWNLOAD_SIZE) && (i < CRO_SHORT_DOWNLOAD_MAX_SIZE); i++) { - printf("%02X ", CRO_SHORT_DOWNLOAD_DATA[i]); - } - printf("\n"); + { + uint16_t i; + printf("SHORT_DOWNLOAD addr=%08Xh, addrext=%02Xh, size=%u, data=", CRO_SHORT_DOWNLOAD_ADDR, CRO_SHORT_DOWNLOAD_EXT, CRO_SHORT_DOWNLOAD_SIZE); + for (i = 0; (i < CRO_SHORT_DOWNLOAD_SIZE) && (i < CRO_SHORT_DOWNLOAD_MAX_SIZE); i++) { + printf("%02X ", CRO_SHORT_DOWNLOAD_DATA[i]); + } + printf("\n"); } break; case CC_UPLOAD: - if (DBG_LEVEL >= 3) { + { printf("UPLOAD size=%u\n", CRO_UPLOAD_SIZE); } break; case CC_SHORT_UPLOAD: - if (DBG_LEVEL >= 3 || !isDaqRunning()) { // Polling DAQ + { printf("SHORT_UPLOAD addr=%08Xh, addrext=%02Xh, size=%u\n", CRO_SHORT_UPLOAD_ADDR, CRO_SHORT_UPLOAD_EXT, CRO_SHORT_UPLOAD_SIZE); } break; -#ifdef XCP_ENABLE_CAL_PAGE - case CC_SET_CAL_PAGE: - printf("SET_CAL_PAGE segment=%u,page =%u,mode=%02Xh\n", CRO_SET_CAL_PAGE_SEGMENT, CRO_SET_CAL_PAGE_PAGE, CRO_SET_CAL_PAGE_MODE); - break; - - case CC_GET_CAL_PAGE: - printf("GET_CAL_PAGE segment=%u, mode=%u\n", CRO_GET_CAL_PAGE_SEGMENT, CRO_GET_CAL_PAGE_MODE); - break; -#endif - -#ifdef XCP_ENABLE_CHECKSUM - case CC_BUILD_CHECKSUM: /* Build Checksum */ - printf("BUILD_CHECKSUM size=%u\n", CRO_BUILD_CHECKSUM_SIZE); - break; -#endif - - case CC_SYNCH: - printf("SYNCH\n"); - break; - - case CC_GET_COMM_MODE_INFO: - printf("GET_COMM_MODE_INFO\n"); - break; - - case CC_DISCONNECT: - printf("DISCONNECT\n"); - break; - - case CC_GET_ID: - printf("GET_ID type=%u\n", CRO_GET_ID_TYPE); - break; - - case CC_GET_STATUS: - printf("GET_STATUS\n"); - break; - - case CC_GET_DAQ_PROCESSOR_INFO: - printf("GET_DAQ_PROCESSOR_INFO\n"); - break; - - case CC_GET_DAQ_RESOLUTION_INFO: - printf("GET_DAQ_RESOLUTION_INFO\n"); - break; - - case CC_GET_DAQ_EVENT_INFO: - printf("GET_DAQ_EVENT_INFO event=%u\n", CRO_GET_DAQ_EVENT_INFO_EVENT); - break; - - case CC_FREE_DAQ: - printf("FREE_DAQ\n"); - break; - - case CC_ALLOC_DAQ: - printf("ALLOC_DAQ count=%u\n", CRO_ALLOC_DAQ_COUNT); - break; - - case CC_ALLOC_ODT: - printf("ALLOC_ODT daq=%u, count=%u\n", CRO_ALLOC_ODT_DAQ, CRO_ALLOC_ODT_COUNT); - break; - - case CC_ALLOC_ODT_ENTRY: - if (DBG_LEVEL >= 3) { - printf("ALLOC_ODT_ENTRY daq=%u, odt=%u, count=%u\n", CRO_ALLOC_ODT_ENTRY_DAQ, CRO_ALLOC_ODT_ENTRY_ODT, CRO_ALLOC_ODT_ENTRY_COUNT); - } - break; - - case CC_GET_DAQ_LIST_MODE: - printf("GET_DAQ_LIST_MODE daq=%u\n",CRO_GET_DAQ_LIST_MODE_DAQ ); - break; - - case CC_SET_DAQ_LIST_MODE: - printf("SET_DAQ_LIST_MODE daq=%u, mode=%02Xh, eventchannel=%u\n",CRO_SET_DAQ_LIST_MODE_DAQ, CRO_SET_DAQ_LIST_MODE_MODE, CRO_SET_DAQ_LIST_MODE_EVENTCHANNEL); - break; - - case CC_SET_DAQ_PTR: - if (DBG_LEVEL >= 3) { - printf("SET_DAQ_PTR daq=%u,odt=%u,idx=%u\n", CRO_SET_DAQ_PTR_DAQ, CRO_SET_DAQ_PTR_ODT, CRO_SET_DAQ_PTR_IDX); - } - break; - - case CC_WRITE_DAQ: - printf("WRITE_DAQ size=%u,addr=%08Xh,%02Xh\n", CRO_WRITE_DAQ_SIZE, CRO_WRITE_DAQ_ADDR, CRO_WRITE_DAQ_EXT); - break; - - case CC_WRITE_DAQ_MULTIPLE: - if (DBG_LEVEL >= 3) { - printf("WRITE_DAQ_MULTIPLE count=%u\n", CRO_WRITE_DAQ_MULTIPLE_NODAQ); - for (int i = 0; i < CRO_WRITE_DAQ_MULTIPLE_NODAQ; i++) { - printf(" %u: size=%u,addr=%08Xh,%02Xh\n", i, CRO_WRITE_DAQ_MULTIPLE_SIZE(i), CRO_WRITE_DAQ_MULTIPLE_ADDR(i), CRO_WRITE_DAQ_MULTIPLE_EXT(i)); - } - } - break; - - case CC_START_STOP_DAQ_LIST: - printf("START_STOP mode=%s, daq=%u\n", (CRO_START_STOP_DAQ_LIST_MODE == 2)?"select": (CRO_START_STOP_DAQ_LIST_MODE == 1)?"start":"stop", CRO_START_STOP_DAQ_LIST_DAQ); - break; - - case CC_START_STOP_SYNCH: - printf("CC_START_STOP_SYNCH mode=%s\n", (CRO_START_STOP_SYNCH_MODE == 3) ? "prepare" : (CRO_START_STOP_SYNCH_MODE == 2) ? "stop_selected" : (CRO_START_STOP_SYNCH_MODE == 1) ? "start_selected" : "stop_all"); - break; - - case CC_GET_DAQ_CLOCK: - if (DBG_LEVEL >= 3 || !isDaqRunning()) { - printf("GET_DAQ_CLOCK\n"); + case CC_WRITE_DAQ_MULTIPLE: + { + printf("WRITE_DAQ_MULTIPLE count=%u\n", CRO_WRITE_DAQ_MULTIPLE_NODAQ); + for (int i = 0; i < CRO_WRITE_DAQ_MULTIPLE_NODAQ; i++) { + printf(" %u: size=%u,addr=%08Xh,%02Xh\n", i, CRO_WRITE_DAQ_MULTIPLE_SIZE(i), CRO_WRITE_DAQ_MULTIPLE_ADDR(i), CRO_WRITE_DAQ_MULTIPLE_EXT(i)); } - break; + } + break; #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 - case CC_TIME_CORRELATION_PROPERTIES: - printf("GET_TIME_CORRELATION_PROPERTIES set=%02Xh, request=%u, clusterId=%u\n", CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES, CRO_TIME_SYNCH_PROPERTIES_GET_PROPERTIES_REQUEST, CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID ); - break; + case CC_TIME_CORRELATION_PROPERTIES: printf("GET_TIME_CORRELATION_PROPERTIES set=%02Xh, request=%u, clusterId=%u\n", CRO_TIME_SYNCH_PROPERTIES_SET_PROPERTIES, CRO_TIME_SYNCH_PROPERTIES_GET_PROPERTIES_REQUEST, CRO_TIME_SYNCH_PROPERTIES_CLUSTER_ID ); break; #endif #if XCP_PROTOCOL_LAYER_VERSION >= 0x0104 + case CC_LEVEL_1_COMMAND: switch (CRO_LEVEL_1_COMMAND_CODE) { case CC_GET_VERSION: @@ -1922,40 +2184,45 @@ static void XcpPrintCmd() { printf("SET_DAQ_LIST_PACKED_MODE daq=%u, sampleCount=%u\n", CRO_SET_DAQ_LIST_PACKED_MODE_DAQ,CRO_SET_DAQ_LIST_PACKED_MODE_SAMPLECOUNT); break; #endif - default: - printf("UNKNOWN LEVEL 1 COMMAND %02X\n", CRO_LEVEL_1_COMMAND_CODE); - break; - } + default: printf("UNKNOWN LEVEL 1 COMMAND %02X\n", CRO_LEVEL_1_COMMAND_CODE); break; + } // switch (CRO_LEVEL_1_COMMAND_CODE) break; -#endif + +#endif // >= 0x0104 case CC_TRANSPORT_LAYER_CMD: - switch (CRO_TL_SUBCOMMAND) { + switch (CRO_TL_SUBCOMMAND) { #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 - case CC_TL_GET_DAQ_CLOCK_MULTICAST: - if (DBG_LEVEL >= 3 || !isDaqRunning()) { - printf("GET_DAQ_CLOCK_MULTICAST counter=%u, cluster=%u\n", CRO_GET_DAQ_CLOCK_MCAST_COUNTER, CRO_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER); - } - break; - case CC_TL_GET_SERVER_ID_EXTENDED: - case CC_TL_GET_SERVER_ID: - printf("GET_SERVER_ID %u:%u:%u:%u:%u\n", CRO_TL_GET_SERVER_ID_ADDR(0), CRO_TL_GET_SERVER_ID_ADDR(1), CRO_TL_GET_SERVER_ID_ADDR(2), CRO_TL_GET_SERVER_ID_ADDR(3), CRO_TL_GET_SERVER_ID_PORT ); - break; -#endif - } - break; + case CC_TL_GET_DAQ_CLOCK_MULTICAST: + { + printf("GET_DAQ_CLOCK_MULTICAST counter=%u, cluster=%u\n", CRO_GET_DAQ_CLOCK_MCAST_COUNTER, CRO_GET_DAQ_CLOCK_MCAST_CLUSTER_IDENTIFIER); + } + break; + case CC_TL_GET_SERVER_ID_EXTENDED: + case CC_TL_GET_SERVER_ID: + printf("GET_SERVER_ID %u:%u:%u:%u:%u\n", CRO_TL_GET_SERVER_ID_ADDR(0), CRO_TL_GET_SERVER_ID_ADDR(1), CRO_TL_GET_SERVER_ID_ADDR(2), CRO_TL_GET_SERVER_ID_ADDR(3), CRO_TL_GET_SERVER_ID_PORT ); + break; +#endif // >= 0x0103 + default: printf("UNKNOWN TRANSPORT LAYER COMMAND %02X\n", CRO_TL_SUBCOMMAND); break; + } // switch (CRO_TL_SUBCOMMAND) - } /* switch */ + } // switch (CRO_CMD) } -static void XcpPrintRes() { - - if (CRM_CMD == PID_EV && CRM_EVENTCODE != EVC_TIME_SYNCH) { - printf("<- EVENT: %02Xh\n", CRM_BYTE(1)); - } - else if (CRM_CMD == PID_ERR) { - const char* e; +static void XcpPrintRes(const tXcpCto* crm) { + +#undef CRM_LEN +#undef CRM_BYTE +#undef CRM_WORD +#undef CRM_DWORD +#define CRM_LEN (crmLen) +#define CRM_BYTE(x) (crm->b[x]) +#define CRM_WORD(x) (crm->w[x]) +#define CRM_DWORD(x) (crm->dw[x]) + + if (CRM_CMD == PID_ERR) { + const char* e; switch (CRM_ERR) { case CRC_CMD_SYNCH: e = "CRC_CMD_SYNCH"; break; case CRC_CMD_BUSY: e = "CRC_CMD_BUSY"; break; @@ -1983,7 +2250,7 @@ static void XcpPrintRes() { printf("<- ERROR: %02Xh - %s\n", CRM_ERR, e ); } else { - switch (CRO_CMD) { + switch (0) { case CC_CONNECT: printf("<- version=%02Xh/%02Xh, maxcro=%u, maxdto=%u, resource=%02X, mode=%u\n", @@ -2049,7 +2316,7 @@ static void XcpPrintRes() { #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 case CC_GET_DAQ_CLOCK: - if (DBG_LEVEL >= 3 || !isDaqRunning()) { + { if (isLegacyMode()) { printf("<- L t=0x%" PRIx32 "\n", CRM_GET_DAQ_CLOCK_TIME); } @@ -2098,7 +2365,7 @@ static void XcpPrintRes() { switch (CRO_TL_SUBCOMMAND) { #if XCP_PROTOCOL_LAYER_VERSION >= 0x0103 case CC_TL_GET_DAQ_CLOCK_MULTICAST: - if (DBG_LEVEL >= 3 || !isDaqRunning()) { + { if (isLegacyMode()) { printf("<- L t=0x%" PRIx32 "\n", CRM_GET_DAQ_CLOCK_MCAST_TIME); } @@ -2128,7 +2395,7 @@ static void XcpPrintRes() { break; default: - if (DBG_LEVEL >= 3) { + if (DBG_LEVEL >= 4) { printf("<- OK\n"); } break; @@ -2146,6 +2413,7 @@ static void XcpPrintDaqList( uint16_t daq ) printf("DAQ %u:\n",daq); printf(" eventchannel=%04Xh,",DaqListEventChannel(daq)); + printf(" ext=%02Xh,",DaqListAddrExt(daq)); printf(" firstOdt=%u,",DaqListFirstOdt(daq)); printf(" lastOdt=%u,",DaqListLastOdt(daq)); printf(" mode=%02Xh,", DaqListMode(daq)); @@ -2162,6 +2430,4 @@ static void XcpPrintDaqList( uint16_t daq ) } /* j */ } - -#endif /* DBG_PRINTS_ENABLED */ - +#endif diff --git a/src/xcpLite.h b/src/xcpLite.h index a5be6d3..b421051 100644 --- a/src/xcpLite.h +++ b/src/xcpLite.h @@ -4,7 +4,6 @@ /* Copyright(c) Vector Informatik GmbH.All rights reserved. Licensed under the MIT license.See LICENSE file in the project root for details. */ - #ifdef __XCPTL_CFG_H__ #error "Include dependency error!" #endif @@ -22,14 +21,13 @@ #include "xcptl_cfg.h" // Transport layer configuration // Transport layer definitions and configuration -#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH #include "xcpTl.h" +#if XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_ETH #include "xcpEthTl.h" // Ethernet transport layer specific functions #elif XCP_TRANSPORT_LAYER_TYPE==XCP_TRANSPORT_LAYER_CAN -#include "xcptl.h" #include "xcpcantl.h" #else -#error "Define XCP_TRANSPORT_LAYER_ETH or XCP_TRANSPORT_LAYER_CAN" +#error "Define XCP_TRANSPORT_LAYER_ETH or _CAN" #endif // Protocol layer definitions and configuration @@ -42,6 +40,8 @@ /* DAQ event information */ /****************************************************************************/ +#define XCP_UNDEFINED_EVENT 0xFFFF + #ifdef XCP_ENABLE_DAQ_EVENT_LIST #define XCP_MAX_EVENT_NAME 8 @@ -54,10 +54,10 @@ typedef struct { uint16_t sampleCount; // packed event sample count uint16_t daqList; // associated DAQ list uint8_t priority; // priority 0 = queued, 1 = pushing, 2 = realtime -#ifdef XCP_ENABLE_MULTITHREAD_EVENTS +#ifdef XCP_ENABLE_MULTITHREAD_DAQ_EVENTS MUTEX mutex; #endif -#ifdef XCP_ENABLE_TEST_CHECKS +#ifdef XCP_ENABLE_SELF_TEST uint64_t time; // last event time stamp #endif } tXcpEvent; @@ -76,22 +76,33 @@ extern void XcpDisconnect(); /* Trigger a XCP data acquisition or stimulation event */ extern void XcpEvent(uint16_t event); -extern void XcpEventExt(uint16_t event, uint8_t* base); +extern uint8_t XcpEventExt(uint16_t event, const uint8_t* base, uint32_t len); extern void XcpEventAt(uint16_t event, uint64_t clock); /* XCP command processor */ -extern void XcpCommand( const uint32_t* pCommand, uint16_t len ); +extern uint8_t XcpCommand( const uint32_t* pCommand, uint16_t len ); /* Send an XCP event message */ -extern void XcpSendEvent(uint8_t evc, const uint8_t* d, uint8_t l); +extern void XcpSendEvent(uint8_t ev, uint8_t evc, const uint8_t* d, uint8_t l); + +/* Print log message via XCP */ +#ifdef XCP_ENABLE_SERV_TEXT +extern void XcpPrint( const char *str); +#endif /* Check status */ extern BOOL XcpIsStarted(); extern BOOL XcpIsConnected(); +extern uint16_t XcpGetSessionStatus(); extern BOOL XcpIsDaqRunning(); extern BOOL XcpIsDaqEventRunning(uint16_t event); extern uint64_t XcpGetDaqStartTime(); extern uint32_t XcpGetDaqOverflowCount(); +#ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST +extern uint16_t XcpGetClusterId(); +#endif + + /* Time synchronisation */ #ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST @@ -101,8 +112,6 @@ extern uint16_t XcpGetClusterId(); // Event list #ifdef XCP_ENABLE_DAQ_EVENT_LIST -#define XCP_INVALID_EVENT 0xFFFF - // Clear event list extern void XcpClearEventList(); // Add a measurement event to event list, return event number (0..MAX_EVENT-1) @@ -130,34 +139,52 @@ extern BOOL ApplXcpPrepareDaq(); extern BOOL ApplXcpStartDaq(); extern void ApplXcpStopDaq(); -/* Address conversions from A2L address to pointer and vice versa */ -/* Note that xcpAddrExt 0x01 and 0xFF are reserved for special use cases (0x01 if XCP_ENABLE_DYN_ADDRESSING, 0xFF if XCP_ENABLE_IDT_A2L_UPLOAD) */ +/* Address conversions from A2L address to pointer and vice versa in absolute addressing mode */ +#ifdef XCP_ENABLE_ABS_ADDRESSING extern uint8_t* ApplXcpGetPointer(uint8_t xcpAddrExt, uint32_t xcpAddr); /* Create a pointer (uint8_t*) from xcpAddrExt and xcpAddr, returns NULL if no access */ -extern uint32_t ApplXcpGetAddr(uint8_t* p); // Calculate the xcpAddr address from a pointer +extern uint32_t ApplXcpGetAddr(const uint8_t* p); // Calculate the xcpAddr address from a pointer extern uint8_t *ApplXcpGetBaseAddr(); // Get the base address for DAQ data access */ +#endif + +/* Read and write memory */ +#ifdef XCP_ENABLE_APP_ADDRESSING +extern uint8_t ApplXcpReadMemory(uint32_t src, uint8_t size, uint8_t* dst); +extern uint8_t ApplXcpWriteMemory(uint32_t dst, uint8_t size, const uint8_t* src); +#endif + +/* User command */ +#ifdef XCP_ENABLE_USER_COMMAND +extern uint8_t ApplXcpUserCommand(uint8_t cmd); +#endif + /* Note 1: For DAQ performance and memory optimization: XCPlite DAQ tables do not store address extensions and do not use ApplXcpGetPointer(), addr is stored as 32 Bit value and access is hardcoded by *(baseAddr+xcpAddr) All accesible DAQ data is within a 4GByte range starting at ApplXcpGetBaseAddr() - Address extensions to increase the addressable range are not supported yet - Attempting to setup an ODT entry with address extension != 0 gives a CRC_ACCESS_DENIED error message + Attempting to setup an ODT entry with address extension != XCP_ADDR_EXT_ABS or XCP_ADDR_EXT_DYN gives a CRC_ACCESS_DENIED error message Note 2: ApplXcpGetPointer may do address transformations according to active calibration page - When measuring calibration variables inswitch */ /* Switch calibration pages */ #ifdef XCP_ENABLE_CAL_PAGE +extern uint8_t ApplXcpSetCalPage(uint8_t segment, uint8_t page, uint8_t mode); extern uint8_t ApplXcpGetCalPage(uint8_t segment, uint8_t mode); extern uint8_t ApplXcpSetCalPage(uint8_t segment, uint8_t page, uint8_t mode); +#ifdef XCP_ENABLE_COPY_CAL_PAGE +extern uint8_t ApplXcpCopyCalPage(uint8_t srcSeg, uint8_t srcPage, uint8_t destSeg, uint8_t destPage); #endif - +#ifdef XCP_ENABLE_FREEZE_CAL_PAGE +extern uint8_t ApplXcpFreezeCalPage(uint8_t segment); +#endif +#endif + + /* DAQ clock */ extern uint64_t ApplXcpGetClock64(); - #define CLOCK_STATE_SYNCH_IN_PROGRESS (0) #define CLOCK_STATE_SYNCH (1) #define CLOCK_STATE_FREE_RUNNING (7) diff --git a/src/xcpTl.h b/src/xcpTl.h index 058083d..4f3efcd 100644 --- a/src/xcpTl.h +++ b/src/xcpTl.h @@ -6,20 +6,23 @@ #define XCPTL_TIMEOUT_INFINITE 0xFFFFFFFF // Infinite timeout (blocking mode) for XcpTlHandleCommands, XcpTlWaitForTransmitData - /* Transport Layer functions called by XCPlite.c */ -extern BOOL XcpTlHandleCommands(uint32_t timeout_ms); // Handle all incoming XCP commands, (wait for at least timeout_ms) extern void XcpTlSendCrm(const uint8_t* data, uint16_t n); // Send or queue (depending on XCPTL_QUEUED_CRM) a command response -extern uint8_t* XcpTlGetTransmitBuffer(void** par, uint16_t size); // Get a buffer for a message with size -extern void XcpTlCommitTransmitBuffer(void* par, BOOL flush); // Commit a buffer (by handle returned from XcpTlGetTransmitBuffer) +extern uint8_t* XcpTlGetTransmitBuffer(void** handle, uint16_t size); // Get a buffer for a message with size +extern void XcpTlCommitTransmitBuffer(void* handle, BOOL flush); // Commit a buffer (by handle returned from XcpTlGetTransmitBuffer) extern void XcpTlFlushTransmitBuffer(); // Finalize the current transmit packet (ETH only) extern void XcpTlWaitForTransmitQueueEmpty(); // Wait (sleep) until transmit queue is empty -/* Generic transport Layer functions called by application */ -/* All other application functions functions declared in xcpCanTl.h or xcpEthTl.h */ +/* Transport Layer functions called by application */ +/* All other network specific application functions functions declared in xcpCanTl.h or xcpEthTl.h */ extern int32_t XcpTlHandleTransmitQueue(); // Send all outgoing packets in the transmit queue extern BOOL XcpTlWaitForTransmitData(uint32_t timeout_ms); // Wait for at least timeout_ms, until packets are pending in the transmit queue -extern void XcpTlShutdown(); + +// Generic transport layer functions +// For testing +extern BOOL XcpTlInit(uint16_t segmentSize, int (*cb)(uint16_t msgLen, const uint8_t* msgBuf)); // Start generic transport layer, tx message callback +extern void XcpTlShutdown(); // Stop transport layer +extern uint8_t XcpTlCommand(uint16_t msgLen, const uint8_t* msgBuf); // rx message // Get last error code #define XCPTL_OK 0