cwalter-at / freemodbus Goto Github PK
View Code? Open in Web Editor NEWBSD licensed MODBUS RTU/ASCII and TCP slave
BSD licensed MODBUS RTU/ASCII and TCP slave
Hi,
In the modbus slave service, when I read INPUT registers, it always return "0" value for any register. But I want to have some dummy values for these registers by default when slave service come-up.
How can we do this using this library ? Really appreciate for all your help.
AvoidTimeout中的last和cur都是函数里面临时变量,该如何起到作用了?
freemodbus/modbus/functions/mbfuncholding.c;
line 185, usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
like should be: usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
Hi,
@pvyleta Can I make use of the same library stack for a Modbus Master implementation. Any tweaks in the stack code required ?
Please change license of demo/BARE/ to same as the main code. Currently one can not use freemodbus under the bsd license due to documentation on how to integrate the project in your own code being a bit incomplete without this code. To make a working integration one pretty much must start from demo/BARE, pushing the gpl license requirements onto the custom application.
Alternatively extend the documentation so that it includes the needed pieces without having to refer to demo/BARE. Today the documentation assumes one starts from demo/BARE and do not cover all of the required interactions with the library when porting it to a new target.
Hi,
I found this bug which leads demo/LINUXTCP to crash while conducting fuzzing experiment.
The log information of message which lead server to crash:
modbusbug2.txt
The ASAN information:
=================================================================
==9863==ERROR: AddressSanitizer: SEGV on unknown address 0x000009026928 (pc 0x0000004c4c97 bp 0x7f2c32efede0 sp 0x7f2c32efed20 T1)
==9863==The signal is caused by a READ memory access.
#0 0x4c4c97 in xMBPortTCPPool /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/port/porttcp.c:205:13
#1 0x4c4667 in xMBPortEventGet /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/port/portevent.c:69:17
#2 0x4c6084 in eMBPoll /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/../../modbus/mb.c:351:9
#3 0x4c416f in pvPollingThread /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/demo.c:215:17
#4 0x7f2c36853608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8608)
#5 0x7f2c365fe352 in clone (/lib/x86_64-linux-gnu/libc.so.6+0x11f352)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/port/porttcp.c:205:13 in xMBPortTCPPool
Thread T1 created by T0 here:
#0 0x47e85a in pthread_create (/home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/tcpmodbus+0x47e85a)
#1 0x4c39db in bCreatePollingThread /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/demo.c:189:13
#2 0x4c3502 in main /home/linuxbrew/pin-3.28-98749-g6643ecee5-gcc-linux/source/tools/BinPRE/src/freemodbus/demo/LINUXTCP/demo.c:126:21
#3 0x7f2c36503082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
==9863==ABORTING
Hello! I'm trying to run modbus tcp on lwip stack (NUCLEO-H755ZI-Q), so the problem:
Modbus init sequence:
if(eMBTCPInit(0) != MB_ENOERR)
return;
if(eMBSetSlaveID( 1, TRUE, Vendor, sizeof(Vendor)) != MB_ENOERR)
return;
if(eMBEnable() != MB_ENOERR)
return;
while(1)
{
eMBPoll();
MX_LWIP_Process();
}
There is wrong bit name in file portserial.c in function void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
:
if( xTxEnable )
{
UCSRB |= _BV( TXEN ) | _BV( UDRE );
#ifdef RTS_ENABLE
RTS_HIGH;
#endif
}
else
{
UCSRB &= ~( _BV( UDRE ) );
}
Must be:
if( xTxEnable )
{
UCSRB |= _BV( TXEN ) | _BV( UDRIE );
#ifdef RTS_ENABLE
RTS_HIGH;
#endif
}
else
{
UCSRB &= ~( _BV( UDRIE ) );
}
May be UDRIE
must be defined like #define UDRIE UDRIE0 //or UDRIE1
in file port.h
in file mbfuncinput.c
usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
usRegAddress++; ---> Why incremente the addr ???
Is there any plans to implement modbus master?
freemodbus/modbus/functions/mbfuncdisc.c
Line 54 in f167010
I checked the utility mbpoll
: mbpoll -m rtu -a 0x0A -u -b 38400 -d 8 -s 2 -P none /dev/ttyUSB0 -v
and get this result:
[0A][11][C7][1C]
Waiting for a confirmation...
ERROR Connection timed out: select
Report slave ID failed(-1): Connection timed out
<0A><11><34><FF><AA><BB><CC><61><14>
I think this code will be more correct or not (why)?:
eMBErrorCode
eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
UCHAR const *pucAdditional, USHORT usAdditionalLen )
{
eMBErrorCode eStatus = MB_ENOERR;
/* the first byte in the buffer is reserved for the Byte Count
* the second byte in the buffer is reserved for the parameter ucSlaveID
* the third byte in the buffer is reserver for running flag.
* The rest of the buffer is available for additional data. */
if( usAdditionalLen + 3 <= MB_FUNC_OTHER_REP_SLAVEID_BUF )
{
usMBSlaveIDLen = 0;
ucMBSlaveID[usMBSlaveIDLen++] = 2 + usAdditionalLen;
ucMBSlaveID[usMBSlaveIDLen++] = ucSlaveID;
ucMBSlaveID[usMBSlaveIDLen++] = ( UCHAR )( xIsRunning ? 0xFF : 0x00 );
if( usAdditionalLen > 0 )
{
memcpy( &ucMBSlaveID[usMBSlaveIDLen], pucAdditional,
( size_t )usAdditionalLen );
usMBSlaveIDLen += usAdditionalLen;
}
}
else
{
eStatus = MB_ENORES;
}
return eStatus;
}
with this code, I get the correct response
[0A][11][C7][1C]
Waiting for a confirmation...
<0A><11><05><34><FF><AA><BB><CC><12><75>
Length: 5
Id : 0x34
Status: On
Data : \AA\BB\CC
I tried to send the modbus broadcast request i.e; slave id = 00, using the sample code of esp-idf modbus. the master sends the request and enters into an illegal state as shown in the figure and does not allow any further requests until reboot. As per the MODBUS protocol standard, the slave only receives request and processes it but doesn't respond since it is the broadcast request. But the freemodbus is making the master enter into illegal state. What is the exact problem for this error of modbus master entering into an unknown state? I suspect that the master is checking the port for any packet received from slave end. Since there is no packet on the port, it gives this error "receive buffer initialization fail." But the master goes into unknown state even without connecting to any slave. The log images of both modbus master and slave are attached for reference. Let me know the issue and ways to fix it.
MODBUS Master logs with broadcast request:
MODBUS Slave logs:
Thanks in advance!
at line 71 of mbfuncinput.c there is an increment of usRegAddress variable
before calling at line 96 the function eMBRegInputCB().
i think, the function eMBRegInputCB() will read the next register address of the desired.
George
Hi,
I am running some experiments for AFLNET and it has found a global-buffer-overflow bug in recv
when sent this pdus to tcpmodbus
poc:
poc.zip
To reproduce:
Complie the demo/LINUXTCP with ASAN
then use aflnet-replay to send the binary_poc to the port, detail in aflnet
I also captured the pcap file when send those pdus to the tcpmodbus, both pcap and binary in poc.zip
ASAN show this information:
=================================================================
==62032==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000daefa7 at pc 0x00000046d94c bp 0x7f77940fec50 sp 0x7f77940fe418
WRITE of size 36 at 0x000000daefa7 thread T1
#0 0x46d94b in recv (/home/ubuntu/Documents/freemodbus/demo/LINUXTCP/tcpmodbus+0x46d94b)
#1 0x4c9d48 in xMBPortTCPPool /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/port/porttcp.c:224:25
#2 0x4c8ca4 in xMBPortEventGet /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/port/portevent.c:69:17
#3 0x4cb3df in eMBPoll /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/../../modbus/mb.c:351:9
#4 0x4c7dd4 in pvPollingThread /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/demo.c:195:17
#5 0x7f7797a97608 in start_thread /build/glibc-SzIz7B/glibc-2.31/nptl/pthread_create.c:477:8
#6 0x7f7797842132 in clone /build/glibc-SzIz7B/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95
0x000000daefa7 is located 0 bytes to the right of global variable 'aucTCPBuf' defined in 'port/porttcp.c:80:17' (0xdaeea0) of size 263
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/ubuntu/Documents/freemodbus/demo/LINUXTCP/tcpmodbus+0x46d94b) in recv
Shadow bytes around the buggy address:
0x0000801adda0: 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
0x0000801addb0: f9 f9 f9 f9 00 00 00 00 04 f9 f9 f9 f9 f9 f9 f9
0x0000801addc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000801addd0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0000801adde0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000801addf0: 00 00 00 00[07]f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x0000801ade00: 02 f9 f9 f9 f9 f9 f9 f9 02 f9 f9 f9 f9 f9 f9 f9
0x0000801ade10: 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
0x0000801ade20: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
0x0000801ade30: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9
0x0000801ade40: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
Thread T1 created by T0 here:
#0 0x480dfa in pthread_create (/home/ubuntu/Documents/freemodbus/demo/LINUXTCP/tcpmodbus+0x480dfa)
#1 0x4c6264 in bCreatePollingThread /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/demo.c:169:13
#2 0x4c6264 in main /home/ubuntu/Documents/freemodbus/demo/LINUXTCP/demo.c:92:21
#3 0x7f7797747082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
==62032==ABORTING
I'm wondering if someone can tell me what the rationale is behind the EV_EXECUTE event in eMBPoll?
It is only invoked if the handler for EV_FRAME_RECEIVED posts EV_EXECUTE, but why isn't the code for EV_EXECUTE just included in the handler for EV_FRAME_RECEIVED? It would make the setup simpler and use less resources in a scheduled environment (e.g. FreeRTOS) because 1) there would be less (unnecessary) kernel calls, and 2) in many cases you would have ISR to task events only (i.e. no task to same task event). This is assuming you implement the events using a kernel queue mechanism.
Some of the above goes for the EV_FRAME_SENT event also, which doesn't do anything.
Hi,
I found this bug which leads demo/LINUXTCP to crash while conducting fuzzing experiment. The cause of this bug may be similar to #34.
The log information of message which lead server to crash:
modbusbug1.txt
Hi, Thank you very much for this great stack. I've used it on old Atmega644 with success. Now I'm trying to run it on new devices from microchip. I'm struggling to get running on ATmega3209. I've changed all port related files (port.h, porttimer.c and portserial.c). Done all test from porting.docx, everything look good, receiver and transmitter working as expected, interrupt on timer toggle LED, but when trying to test it using mbpull and usb-rs485 converter always got Timeout error.
Code after changes attached.
Any ideas why it's not working??
Atmega3209_Modbus.zip
The eMBRTUReceive asserts on 256 bytes received. A bit sensetiv to selfdestruct on a bit to musch on the line? The usRcvBufferPos is both a "indexer" and a "length checker".
Hi, I am running this software on an STM32F407 running as a modbus slave device. Everything works fine except when i poll data from the device and read the holding registers via either RTU or TCP I only receive the least significant byte of the register even though the modbus master specifies to read INT16 data. Any idea why it is not transmitting the upper byte of the register? I inherited this project from a previous developer so I do not want to start modifying it until I know if there is a simple solution or not.
It seems more appropriate that it return eStatus, rather than always returning success. This would have a chance for the caller to track that things have gone wrong.
I am using this API as a modbus master for Linux platform. Demo.c doesn't include reading and writing of register also it isn't sending any data frame. Can you please help me it.
I have a slave device which supports writing 150 registers at once which is around 300 bytes. I have framed a modbus request which is greater than 300 bytes including slave ID, function code, register start address, number of registers, number of bytes, data and CRC and sent it to the modbus slave device using standard modbus master template code. In standard documentations it is mentioned that the modbus can support writing multiple registers of 123 registers at once. Is there any way to that can support the bulk and huge payload of writing multiple registers?
Is it possible with this library to choose between RTU and TCP at runtime ?
Can we choose from a variable if Modbus RTU or Modbus TCP needed to be activated ?
freemodbus/modbus/functions/mbfuncholding.c
Line 185 in f167010
It should be usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
Demo portevent.c variables are optimized-out by current compilers. No events received from a bus.
Here, demo/BARE/port/portevent.c:
/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL xEventInQueue;
Both variables MUST be declared with volatile qualifier:
/* ----------------------- Variables ----------------------------------------*/
static volatile eMBEventType eQueuedEvent;
static volatile BOOL xEventInQueue;
This is because both variables are changing in an interrupts, unexpectedly for the compiler.
When I compiled my RTU port using BARE demo template, I discovered it works without an optimization and doesn't with high level.
The single failure point was portevent.c with variable definition. It is obvious that these variables need to be volatile to be processed correctly in MODBUS poll function.
Firstly, thanks to the authors for this nice concise modbus slave ported to multiple devices. I tested it on a MSP430F5529 so made a few changes to the provided MSP430F169 port. I got it working but only after addressing a couple of issues which I think should impact all devices.
The issue I had to fix had to do with the current position of the buffer use to store received bytes (usRcvBufferPos) which only gets reset in STATE_RX_IDLE. If for whatever reason a slave doesn't respond to a request then the start position of the buffer doesn't get reset and is in an unknown state when the next request comes in. Setting it back to zero at the end of receiving the current frame seems to fix the problem though I'm not sure whether it introduces other problems.
eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength ) { ... usRcvBufferPos = 0; return eStatus; }
There's probably a better solution to this. Anybody else encounter this issue?
if i send : 01 0F 00 00 00 03 01 0f CF 53
i means wirte three coils to bit 1,but it returns four bits to bit 1,
if we should just get three bits in 0x0f ?
Hi,
When i test demo/LINUXTCP app, I see service using 100% CPU all the time. Any resolution ?
mbrtu.c line 313 may disable the transmitter prematurely on targets that raises a TX buffer empty ISR/event whilst still transmitting: https://github.com/cwalter-at/freemodbus/blob/master/modbus/rtu/mbrtu.c#LL311C1-L313C48
Removing this line on an R7FA2L1 target and raising another buffer empty callback when TX complete event is received allows the RS485 transceiver to change back to receive AFTER the byte is actually sent.
I've ported the code to be used on a atXMega32D4 and got it working with several Master applications.
The common thing that is not working is that after 35 messages, the USART completely stops receiving any data into the DATA register.
Did anyone ever encounter anything like this? Do I need to clear the DATA register somewhere again?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.