diff --git a/src/main.rs b/src/main.rs index ecf9d57..60053a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -491,9 +491,18 @@ fn main() { // Without this, the A2L file will be automatically written on XCP connect, to be available for download by CANape if !args.no_a2l && mainloop_counter1 == 1 { thread::sleep(Duration::from_secs(2)); - xcp.write_a2l(); // Test A2L write - // xcp.set_init_request(); // Test init request - // xcp.set_freeze_request(); // Test freeze request + + // Test A2L write + xcp.write_a2l(); + + // Test init request + // xcp.set_init_request(); + + // Test freeze request + // xcp.set_freeze_request(); + + // Test shutdown + // break; } } info!("Main task finished"); diff --git a/xcp_lite.a2l b/xcp_lite.a2l index f0f4962..bc0100a 100644 --- a/xcp_lite.a2l +++ b/xcp_lite.a2l @@ -152,7 +152,7 @@ /end DAQ -/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "192.168.179.2" /end XCP_ON_UDP_IP +/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "127.0.0.1" /end XCP_ON_UDP_IP /end IF_DATA diff --git a/xcplib/src/platform.h b/xcplib/src/platform.h index 586a655..b312253 100644 --- a/xcplib/src/platform.h +++ b/xcplib/src/platform.h @@ -76,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 diff --git a/xcplib/src/xcpEthServer.c b/xcplib/src/xcpEthServer.c index 795ee22..d675096 100644 --- a/xcplib/src/xcpEthServer.c +++ b/xcplib/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; @@ -95,9 +95,11 @@ BOOL XcpEthServerShutdown() { if (gXcpServer.isInit) { XcpDisconnect(); - cancel_thread(gXcpServer.DAQThreadHandle); - cancel_thread(gXcpServer.CMDThreadHandle); + gXcpServer.ReceiveThreadRunning = FALSE; + gXcpServer.TransmitThreadRunning = FALSE; XcpEthTlShutdown(); + join_thread(gXcpServer.CMDThreadHandle); + join_thread(gXcpServer.DAQThreadHandle); gXcpServer.isInit = FALSE; socketCleanup(); } @@ -116,16 +118,16 @@ extern void* XcpServerReceiveThread(void* par) DBG_PRINT3("Start XCP CMD thread\n"); // Receive XCP unicast commands loop - gXcpServer.ReceiveThreadRunning = 1; - for (;;) { + 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; } @@ -143,8 +145,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 @@ -157,9 +159,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/xcplib/src/xcpEthTl.c b/xcplib/src/xcpEthTl.c index 2ce6ce0..5e33bbe 100644 --- a/xcplib/src/xcpEthTl.c +++ b/xcplib/src/xcpEthTl.c @@ -657,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_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_PRINT3("Terminate XCP multicast thread\n"); + DBG_PRINT3("XCP multicast thread terminated\n"); socketClose(&gXcpTl.MulticastSock); return 0; } @@ -760,7 +759,7 @@ BOOL XcpEthTlInit(const uint8_t* addr, uint16_t port, BOOL useTCP, uint16_t segm 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; @@ -785,17 +784,18 @@ void XcpTlShutdown() { void XcpEthTlShutdown() { - XcpTlShutdown(); - + // 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 #ifdef XCPTL_ENABLE_TCP if (isTCP()) socketClose(&gXcpTl.ListenSock); #endif socketClose(&gXcpTl.Sock); + + // Free other resources + XcpTlShutdown(); } diff --git a/xcplib/src/xcpLite.c b/xcplib/src/xcpLite.c index 35ea09e..bc2ee2e 100644 --- a/xcplib/src/xcpLite.c +++ b/xcplib/src/xcpLite.c @@ -949,7 +949,7 @@ uint8_t XcpEventExt(uint16_t event, const uint8_t* base, uint32_t len) { #endif if (cmdPending) { // Convert relative signed 16 bit addr in MtaAddr to pointer MtaPtr - gXcp.MtaPtr = base + (int16_t)(gXcp.MtaAddr & 0xFFFF); + 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]; diff --git a/xcplib/xcp_cfg.h b/xcplib/xcp_cfg.h index a3ea0cf..0b6f441 100644 --- a/xcplib/xcp_cfg.h +++ b/xcplib/xcp_cfg.h @@ -114,6 +114,13 @@ #endif +#define XCP_ENABLE_DAQ_CLOCK_MULTICAST // Enable GET_DAQ_CLOCK_MULTICAST +#ifdef XCP_ENABLE_DAQ_CLOCK_MULTICAST + // XCP default cluster id (multicast addr 239,255,0,1, group 127,0,1 (mac 01-00-5E-7F-00-01) +#define XCP_MULTICAST_CLUSTER_ID 1 +#endif + + //------------------------------------------------------------------------------- // Debug diff --git a/xcplib/xcptl_cfg.h b/xcplib/xcptl_cfg.h index 520f8ff..da047a8 100644 --- a/xcplib/xcptl_cfg.h +++ b/xcplib/xcptl_cfg.h @@ -19,6 +19,18 @@ #define XCPTL_ENABLE_TCP #define XCPTL_ENABLE_UDP + +// Multicast (GET_DAQ_CLOCK_MULTICAST) +// Use multicast time synchronisation to improve synchronisation of multiple XCP slaves +// This is standard in XCP V1.3, but it needs to create an additional thread and socket for multicast reception +// Has no benefit with PTP time synchronized slave and is just unnesserary effort +// CANape expects this by default -> adjust setting in device/protocol/event/TIME_CORRELATION_GETDAQCLOCK from "multicast" to "extended response" to switch it of +#define XCPTL_ENABLE_MULTICAST +#ifdef XCPTL_ENABLE_MULTICAST + #define XCLTL_RESTRICT_MULTICAST + #define XCPTL_MULTICAST_PORT 5557 +#endif + // Transmit mode #define XCPTL_QUEUED_CRM // Use transmit queue for command responces /*