diff --git a/Modbus-CAPL/MakeConfig.cfg b/Modbus-CAPL/MakeConfig.cfg index 975572b..f898448 100644 --- a/Modbus-CAPL/MakeConfig.cfg +++ b/Modbus-CAPL/MakeConfig.cfg @@ -1,4 +1,4 @@ -;CANoe Version |4|7|1|52132 MakeConfig +;CANoe Version |4|7|1|52133 MakeConfig Version: 8.2.40 Build 40 32 PRO 5 @@ -1261,9 +1261,37 @@ Grafik-Fenster 237 0 0 +1 0 0 0 +-11 +0 +0 +0 +0 +0 +0 +0 +400 +0 +Tahoma +0 +1 +0 +0 +0 +-11 +0 +0 +0 +34 +0 +0 +0 +400 +0 +Tahoma 0 1 1 @@ -2933,7 +2961,7 @@ End_Of_Object VGrMnBox 3 VDOLocalInfoStruct 3 Begin_Of_Object 3 1 -98 +101 VDAOBus 4 Begin_Of_Object 1 1 @@ -3063,7 +3091,7 @@ VSimulinkModelViewerConfiguration 7 Begin_Of_Object End_Of_Object VSimulinkModelViewerConfiguration 7 1 0 -4212996857 +1115474418 0 NodeSignalPanelBustypeCount 0 End_Of_Object VSimulationNode 6 @@ -3101,7 +3129,7 @@ NULL End_Of_Object VDOLocalInfoStruct 3 0.000000 0 0 -1 1 0 59420 1 233 1 2882400001 98 331 371 619 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 373 373 2882400002 0 0 0 335238400 0 336542644 3 +1 1 0 59420 1 233 1 2882400001 98 331 371 619 2882400002 0 0 0 0 0 0 1 2882400001 1270 1270 373 373 2882400002 0 0 0 355173376 0 423022796 3 SS_BEGIN_COMMON_INFO 1 0 @@ -3113,7 +3141,7 @@ Ethernet 11 1 1 -335879144 1 0 1 0 0 1 0 0 0 2000 1 +422945832 1 0 1 0 0 1 0 0 0 2000 1 SS_BEGIN_COMMON_INFO 1 3 @@ -3224,7 +3252,7 @@ End_Of_Serialized_Data 2 End_Of_Object VWriteBox 2 VWinStore 2 Begin_Of_Object 1 -22 2 3 -1 -1 -1 -1 -10088 -10000 -9070 -9233 +22 2 3 -32088 -32000 -1 -1 -10088 -10000 -9070 -9233 End_Of_Child_List End_Of_Object VWinStore 2 VWinStore 2 Begin_Of_Object @@ -3537,6 +3565,7 @@ End FiltersEnd 0 0 + END_OF_WORKSPACE_MEMBER_DATA END_OF_WORKSPACE_MEMBER 1 diff --git a/Modbus-CAPL/include/CAPL/MakeConfig.can b/Modbus-CAPL/include/CAPL/MakeConfig.can index 679209c..85b4a9b 100644 --- a/Modbus-CAPL/include/CAPL/MakeConfig.can +++ b/Modbus-CAPL/include/CAPL/MakeConfig.can @@ -25,6 +25,8 @@ variables word ADi, ADn, ADl; // Some variables for "AnalyzeDevices" byte ggMaxTransmissionCount; + byte useThirdIpByteForNames; // Whether the third byte of the IP address shall be used in the node name + byte skip255; // Whether the IP address .255 (broadcast in /24) shall be skipped } on preStart @@ -39,7 +41,12 @@ on preStart // Scan a range of IPs for devices (if nothing was set above). Start and Stop go here // Please note: Currently .255 will be skipped! Don't use this address for devices strncpy(gScanFirstIp, "192.168.1.2", elCount(gScanFirstIp)); - strncpy(gScanLastIp, "192.168.1.20", elCount(gScanLastIp)); + strncpy(gScanLastIp, "192.168.2.20", elCount(gScanLastIp)); + + // Whether the third byte of the IP address shall be used in the node name + useThirdIpByteForNames = 0; + // Whether the IP address .255 (broadcast in /24) shall be skipped + skip255 = 1; // Name of the project strncpy(name, "Modbus", elCount(name)); @@ -48,7 +55,7 @@ on preStart strncpy(fnSysvar, "include/SysVars/generated.vsysvar", elCount(fnSysvar)); strncpy(fnDbc, "include/DBC/generated.dbc", elCount(fnDbc)); - OutputDebugLevel = Debug;//Error; + OutputDebugLevel = Error; } on start @@ -87,7 +94,7 @@ void PutString(byte d) /// void DetectDevices() { - write("Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout); + writeLineEx(0, 1, "Scanning from %s to %s with timeout of %d ms", gScanFirstIp, gScanLastIp, @sysvar::Config::Modbus::RequestTimeout); gScanFirst = ipGetAddressAsNumber(gScanFirstIp); // We have to use big endian here gScanLast = swapDWord(ipGetAddressAsNumber(gScanLastIp)); // But not here :) @@ -102,11 +109,15 @@ void DetectDevicesNext() { gScanFirst = swapDWord(gScanFirst); gScanFirst++; - if ((gScanFirst & 0xFF) == 0xFF) // skip .255 + if (skip255 && (gScanFirst & 0xFF) == 0xFF) // skip .255 { gScanFirst++; writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF); } + else if (!skip255 && (gScanFirst & 0xFF) == 0x00) + { + writeLineEx(0, 0, "%d.%d.%d.%d ", gScanFirst >> 24, (gScanFirst >> 16) & 0xFF, (gScanFirst >> 8) & 0xFF, gScanFirst & 0xFF); + } if (gScanFirst > gScanLast) { @@ -124,12 +135,7 @@ void DetectDevicesNext() /// void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { - switch (error) - { - case FinalTimeout: - case Exception: - DetectDevicesNext(); // Timeout! We will go to the next device - } + DetectDevicesNext(); // Timeout, NotSent, Exception! We will go to the next device } /// void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) @@ -238,6 +244,9 @@ void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusExcep case FinalTimeout: writeLineEx(0, 3, "Error while analyzing %s! The device did not respond! Ignoring...", gIpsSorted[ips[ADi]].IP); break; + case NotSent: + writeLineEx(0, 3, "Error while analyzing %s! The device was not available! Ignoring...", gIpsSorted[ips[ADi]].IP); + break; } gQueueAck.Clear(); // Clear all queues gQueuePending.Clear(); @@ -317,8 +326,11 @@ void GenSysvars() DeviceInit(gIpsSorted[ipN].Vendor); PutString(" 0 && address < devEndAddr) { @@ -279,7 +281,7 @@ void _ModbusReadRegisters(enum ModbusFuncCode funcCode, word address, long count writeDbg(MbWarning, "_ModbusReadBits: Impossible to read %d bits at 0x%04X. Changed count to %d.", curCount, address, devEndAddr - address); curCount = devEndAddr - address; } - write("address = 0x%04X, count = %d, curCount = %d, devStartAddr = 0x%04X, devEndAddr = 0x%04X", address, count, curCount, devStartAddr, devEndAddr); + //write("address = 0x%04X, count = %d, curCount = %d, devStartAddr = 0x%04X, devEndAddr = 0x%04X", address, count, curCount, devStartAddr, devEndAddr); _ModbusMakeHeader(mbreq.Header, length, funcCode); @@ -440,6 +442,7 @@ void ModbusWriteBits(word address, long count, byte values[]) long offset; // FC15: Write Multiple Bits (DOs) + offset = 0; while (count > 0) { if (count > gMaxBitsPerWrite) @@ -463,7 +466,7 @@ void ModbusWriteBits(word address, long count, byte values[]) for (i = 0; i < dataLength; i++) // [264] Byte status, 8 per byte mbreq.Data[i] = values[i+offset/8]; - writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address, curCount); + writeDbg(MbDebug, "Sending 'Write Bits' (0x0F) command. TxID: 0x%04X, Addr: 0x%04X, Count: %d", mbreq.Header.TxID, address+offset, curCount); memcpy_h2n(buffer, mbreq); _ModbusSend(buffer, overallLength, mbreq.Header.TxID); @@ -955,7 +958,6 @@ void _ModbusStartQueue() // The pending packets may be sent when there is free space in the sending window on timer gtModbusRobin { - struct ModbusApHeader mbap; enum ModbusRequestError reqError; writeDbg(ConnDebug, "gtModbusRobin: Queue Sent: %d, Queue Pending: %d, Queue Ack: %d", gQueueSent.Size(), gQueuePending.Size(), gQueueAck.Size()); @@ -968,7 +970,7 @@ on timer gtModbusRobin // timed out! if (++gQueueSent[TxID].Timeouts < gMaxTransmissionCount) // if we may resend it { - writeDbg(ConnInfo, "Packet 0x%04X timed out! Retrying...", TxID); + writeDbg(ConnInfo, "gtModbusRobin: Packet 0x%04X timed out! Retrying...", TxID); gQueueSent[TxID].TimeoutTicks = 0; _ModbusSnd(gQueueSent[TxID].Buffer, gQueueSent[TxID].Length); // resend it reqError = Timeout; @@ -976,43 +978,14 @@ on timer gtModbusRobin } else // we will NOT resend it { - writeDbg(ConnWarning, "Packet 0x%04X timed out! Giving up", TxID); + writeDbg(ConnWarning, "gtModbusRobin: Packet 0x%04X timed out! Giving up", TxID); reqError = FinalTimeout; } - memcpy_n2h(mbap, gQueueSent[TxID].Buffer); - switch(mbap.FuncCode) // throw an "error" in each case - { - case ReadBitsOut: - case ReadBitsIn: - OnModbusReadBitsFailed(reqError, None, mbap); - break; - case ReadRegistersOut: - case ReadRegistersIn: - OnModbusReadRegistersFailed(reqError, None, mbap); - break; - case WriteBit: - OnModbusWriteBitFailed(reqError, None, mbap); - break; - case WriteRegister: - OnModbusWriteRegisterFailed(reqError, None, mbap); - break; - case WriteBits: - OnModbusWriteBitsFailed(reqError, None, mbap); - break; - case WriteRegisters: - OnModbusWriteRegistersFailed(reqError, None, mbap); - break; - case MaskRegister: - OnModbusWriteMasksFailed(reqError, None, mbap); - break; - case ReadWriteRegisters: - OnModbusReadWriteRegistersFailed(reqError, None, mbap); - break; - } - - if (reqError == FinalTimeout) // remove the packet from queue - gQueueSent.Remove(TxID); // wait until here to let the methods above access the request + _ModbusSendTimerError(gQueueSent[TxID].Buffer, reqError); // throw an "error" in each case + + if (reqError == FinalTimeout) // remove the packet from queue + gQueueSent.Remove(TxID); // wait until here to let the methods above access the request } // Second: send new packets @@ -1025,16 +998,59 @@ on timer gtModbusRobin // if packet was sent or the socket is not currently being opened if (_ModbusSnd(gQueuePending[TxID].Buffer, gQueuePending[TxID].Length) == 0) { - memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue + memcpy(gQueueSent[TxID], gQueuePending[TxID]); // move packet to sent queue + gQueuePending.Remove(TxID); + _ModbusRecv(); // wait for new packets + } + else if (gQueuePending[TxID].SendTries++ > 10) // We have tried to send this packet too often. Something is wrong!? + { + writeDbg(ConnError, "gtModbusRobin: The packet 0x%04X could not be sent, _ModbusSnd() rejected it several times", TxID); + _ModbusSendTimerError(gQueuePending[TxID].Buffer, NotSent); gQueuePending.Remove(TxID); - _ModbusRecv(); // wait for new packets } } // Stop timer to reduce load and latency of first new packet if (gSocketState == ERROR || gQueueSent.Size() == 0 && gQueuePending.Size() == 0) { - writeDbg(ConnDebug, "Stopping Timer gtModbusRobin"); + writeDbg(ConnDebug, "gtModbusRobin: Stopping Timer"); this.Cancel(); } +} + +/// <-ModbusSend> +// This method will give an Error +void _ModbusSendTimerError(byte buffer[], enum ModbusRequestError reqError) +{ + struct ModbusApHeader mbap; + memcpy_n2h(mbap, buffer); + switch(mbap.FuncCode) + { + case ReadBitsOut: + case ReadBitsIn: + OnModbusReadBitsFailed(reqError, None, mbap); + break; + case ReadRegistersOut: + case ReadRegistersIn: + OnModbusReadRegistersFailed(reqError, None, mbap); + break; + case WriteBit: + OnModbusWriteBitFailed(reqError, None, mbap); + break; + case WriteRegister: + OnModbusWriteRegisterFailed(reqError, None, mbap); + break; + case WriteBits: + OnModbusWriteBitsFailed(reqError, None, mbap); + break; + case WriteRegisters: + OnModbusWriteRegistersFailed(reqError, None, mbap); + break; + case MaskRegister: + OnModbusWriteMasksFailed(reqError, None, mbap); + break; + case ReadWriteRegisters: + OnModbusReadWriteRegistersFailed(reqError, None, mbap); + break; + } } \ No newline at end of file diff --git a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin index 2e742e5..7ddba46 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusStructs.cin @@ -28,7 +28,7 @@ variables word Protocol; word Length; byte UnitID; - /*enum ModbusFuncCode*/ byte FuncCode; + byte FuncCode; }; // Read Data from the host. We only need the start address and the number of bits/registers we want to read _align(1) struct ModbusReqRead @@ -95,7 +95,7 @@ variables { struct ModbusApHeader Header; byte ByteCount; - word Data[gMaxRegsPerRead]; // Max length: 125 registers + word Data[gMaxRegsPerRead]; // Max length: 125 registers }; // Confirm the write of a single bit/register _align(1) struct ModbusResConfirmSingle @@ -127,7 +127,8 @@ variables { Exception, Timeout, - FinalTimeout + FinalTimeout, + NotSent }; enum ModbusException { diff --git a/Modbus-CAPL/include/DBC/generated.dbc b/Modbus-CAPL/include/DBC/generated.dbc index bb9596d..e790666 100644 --- a/Modbus-CAPL/include/DBC/generated.dbc +++ b/Modbus-CAPL/include/DBC/generated.dbc @@ -33,7 +33,7 @@ NS_ : BS_: -BU_: Client_ Client_100 Client_101 +BU_: Client_2 Client_3