liblightmodbus 3.0
A lightweight, header-only, hardware-agnostic Modbus RTU/TCP library
Loading...
Searching...
No Matches
slave.impl.h
Go to the documentation of this file.
1#ifndef LIGHTMODBUS_SLAVE_IMPL_H
2#define LIGHTMODBUS_SLAVE_IMPL_H
3
4#include "slave.h"
5#include "slave_func.h"
6
19{
20#if defined(LIGHTMODBUS_F01S) || defined(LIGHTMODBUS_SLAVE_FULL)
22#endif
23
24#if defined(LIGHTMODBUS_F02S) || defined(LIGHTMODBUS_SLAVE_FULL)
26#endif
27
28#if defined(LIGHTMODBUS_F03S) || defined(LIGHTMODBUS_SLAVE_FULL)
30#endif
31
32#if defined(LIGHTMODBUS_F04S) || defined(LIGHTMODBUS_SLAVE_FULL)
34#endif
35
36#if defined(LIGHTMODBUS_F05S) || defined(LIGHTMODBUS_SLAVE_FULL)
38#endif
39
40#if defined(LIGHTMODBUS_F06S) || defined(LIGHTMODBUS_SLAVE_FULL)
42#endif
43
44#if defined(LIGHTMODBUS_F15S) || defined(LIGHTMODBUS_SLAVE_FULL)
46#endif
47
48#if defined(LIGHTMODBUS_F16S) || defined(LIGHTMODBUS_SLAVE_FULL)
50#endif
51
52#if defined(LIGHTMODBUS_F22S) || defined(LIGHTMODBUS_SLAVE_FULL)
54#endif
55
56 // Guard - prevents 0 array size
57 {0, NULL}
58};
59
64
80 ModbusSlave *status,
81 ModbusRegisterCallback registerCallback,
82 ModbusSlaveExceptionCallback exceptionCallback,
83 ModbusAllocator allocator,
84 const ModbusSlaveFunctionHandler *functions,
85 uint8_t functionCount)
86{
87 status->functions = functions;
88 status->functionCount = functionCount;
89 status->registerCallback = registerCallback;
90 status->exceptionCallback = exceptionCallback;
91 status->context = NULL;
92
93 return modbusBufferInit(&status->response, allocator);
94}
95
103
119 ModbusSlave *status,
120 uint8_t function,
122{
123 // Call the exception callback
124 if (status->exceptionCallback)
125 status->exceptionCallback(status, function, code);
126
127 if (modbusSlaveAllocateResponse(status, 2))
128 return MODBUS_GENERAL_ERROR(ALLOC);
129
130 status->response.pdu[0] = function | 0x80;
131 status->response.pdu[1] = code;
132
133 return MODBUS_NO_ERROR();
134}
135
144 ModbusSlave *status,
145 uint8_t function,
147{
148 status->response.pduOffset = 0;
149 status->response.padding = 0;
150
151 ModbusErrorInfo err = modbusBuildException(status, function, code);
152 if (!modbusIsOk(err))
153 return err;
154
155 return MODBUS_NO_ERROR();
156}
157
169 ModbusSlave *status,
170 uint8_t address,
171 uint8_t function,
173{
174 if (address == 0)
175 return MODBUS_GENERAL_ERROR(ADDRESS);
176
179
180 ModbusErrorInfo errinfo = modbusBuildException(status, function, code);
181
182 if (!modbusIsOk(errinfo))
183 return errinfo;
184
186 &status->response.data[0],
187 status->response.length,
188 address);
189
190 // There's literally no reason for modbusPackRTU()
191 // to return MODBUS_ERROR_LENGTH here
192 (void) err;
193
194 return MODBUS_NO_ERROR();
195}
196
208 ModbusSlave *status,
209 uint16_t transactionID,
210 uint8_t unitID,
211 uint8_t function,
213{
216
217 ModbusErrorInfo errinfo = modbusBuildException(status, function, code);
218
219 if (!modbusIsOk(errinfo))
220 return errinfo;
221
223 &status->response.data[0],
224 status->response.length,
225 transactionID,
226 unitID);
227
228 // There's literally no reason for modbusPackTCP()
229 // to return MODBUS_ERROR_LENGTH here
230 (void) err;
231
232 return MODBUS_NO_ERROR();
233}
234
249LIGHTMODBUS_RET_ERROR modbusParseRequest(ModbusSlave *status, const uint8_t *request, uint8_t requestLength)
250{
251 uint8_t function = request[0];
252
253 // Look for matching function
254 for (uint16_t i = 0; i < status->functionCount; i++)
255 if (function == status->functions[i].id)
256 return status->functions[i].ptr(status, function, &request[0], requestLength);
257
258 // No match found
259 return modbusBuildException(status, function, MODBUS_EXCEP_ILLEGAL_FUNCTION);
260}
261
275LIGHTMODBUS_RET_ERROR modbusParseRequestPDU(ModbusSlave *status, const uint8_t *request, uint8_t requestLength)
276{
277 // Check length
278 if (!requestLength || requestLength > MODBUS_PDU_MAX)
279 return MODBUS_REQUEST_ERROR(LENGTH);
280
282 return modbusParseRequest(status, request, requestLength);
283}
284
299LIGHTMODBUS_RET_ERROR modbusParseRequestRTU(ModbusSlave *status, uint8_t slaveAddress, const uint8_t *request, uint16_t requestLength)
300{
301 // Unpack the request
302 const uint8_t *pdu;
303 uint16_t pduLength;
304 uint8_t requestAddress;
306 request,
307 requestLength,
308 1,
309 &pdu,
310 &pduLength,
311 &requestAddress
312 );
313
314 if (err != MODBUS_OK)
316
317 // Verify if the frame is meant for us
318 if (requestAddress != 0 && requestAddress != slaveAddress)
319 return MODBUS_REQUEST_ERROR(ADDRESS);
320
321 // Parse the request
322 ModbusErrorInfo errinfo;
324 if (!modbusIsOk(errinfo = modbusParseRequest(status, pdu, pduLength)))
325 return errinfo;
326
327 if (status->response.length)
328 {
329 // Discard any response frames if the request
330 // was broadcast
331 if (requestAddress == 0)
332 {
334 return MODBUS_NO_ERROR();
335 }
336
337 // Pack the response frame
338 err = modbusPackRTU(
339 &status->response.data[0],
340 status->response.length,
341 slaveAddress);
342
343 if (err != MODBUS_OK)
345 }
346
347 return MODBUS_NO_ERROR();
348}
349
362LIGHTMODBUS_RET_ERROR modbusParseRequestTCP(ModbusSlave *status, const uint8_t *request, uint16_t requestLength)
363{
364 // Unpack the request
365 const uint8_t *pdu;
366 uint16_t pduLength;
367 uint16_t transactionID;
368 uint8_t unitID;
370 request,
371 requestLength,
372 &pdu,
373 &pduLength,
374 &transactionID,
375 &unitID
376 );
377
378 if (err != MODBUS_OK)
380
381 // Parse the request
382 ModbusErrorInfo errinfo;
384 if (!modbusIsOk(errinfo = modbusParseRequest(status, pdu, pduLength)))
385 return errinfo;
386
387 // Write MBAP header
388 if (status->response.length)
389 {
390 // Pack the resonse
391 err = modbusPackTCP(
392 &status->response.data[0],
393 status->response.length,
394 transactionID,
395 unitID
396 );
397
398 if (err != MODBUS_OK)
400 }
401
402 return MODBUS_NO_ERROR();
403}
404
405#endif
ModbusExceptionCode
Represents a Modbus exception code.
Definition base.h:230
@ MODBUS_EXCEP_ILLEGAL_FUNCTION
Illegal function code.
Definition base.h:232
#define MODBUS_REQUEST_ERROR(e)
Constructs a ModbusErrorInfo where source is set to MODBUS_ERROR_SOURCE_REQUESTL and the error code i...
Definition base.h:100
#define MODBUS_RTU_ADU_PADDING
Number of extra bytes added to the PDU in Modbus RTU.
Definition base.h:37
static ModbusError modbusPackTCP(uint8_t *frame, uint16_t length, uint16_t transactionID, uint8_t unitID)
Sets up the MBAP header in a Modbus TCP frame.
Definition base.h:592
ModbusError
Represtents different kinds of errors.
Definition base.h:137
@ MODBUS_OK
No error.
Definition base.h:143
#define MODBUS_TCP_PDU_OFFSET
Offset of PDU relative to the frame beginning in Modbus TCP.
Definition base.h:43
#define MODBUS_ERROR_SOURCE_REQUEST
The request frame contains errors.
Definition base.h:62
#define MODBUS_TCP_ADU_PADDING
Number of extra bytes added to the PDU in Modbus TCP.
Definition base.h:42
static ModbusError modbusUnpackRTU(const uint8_t *frame, uint16_t length, uint8_t checkCRC, const uint8_t **pdu, uint16_t *pduLength, uint8_t *address)
Unpacks data from a Modbus RTU frame and optionally checks CRC.
Definition base.h:489
ModbusErrorInfo modbusBufferInit(ModbusBuffer *buffer, ModbusAllocator allocator)
Initializes a buffer for use.
Definition base.impl.h:51
#define MODBUS_NO_ERROR()
Construcs a ModbusErrorInfo object for which modbusIsOK() is guaranteed to return true.
Definition base.h:86
static ModbusError modbusUnpackTCP(const uint8_t *frame, uint16_t length, const uint8_t **pdu, uint16_t *pduLength, uint16_t *transactionID, uint8_t *unitID)
Unpacks data from a Modbus TCP frame.
Definition base.h:553
static uint8_t modbusIsOk(ModbusErrorInfo err)
Checks if ModbusErrorInfo contains an error.
Definition base.h:442
static void modbusBufferModePDU(ModbusBuffer *buffer)
Prepares buffer to only store a Modbus PDU.
Definition base.h:303
#define MODBUS_ERROR_SOURCE_GENERAL
General library error - can be caused by providing an incorrect argument or a internal library error.
Definition base.h:56
#define LIGHTMODBUS_RET_ERROR
Return type for library functions returning ModbusErrorInfo that should be handled properly.
Definition base.h:49
ModbusError(* ModbusAllocator)(struct ModbusBuffer *buffer, uint16_t size, void *context)
Pointer to a memory allocator function.
Definition base.h:259
#define MODBUS_MAKE_ERROR(s, e)
Constructs a ModbusErrorInfo object from a ModbusErrorCode and a MODBUS_ERROR_SOURCE_* macro.
Definition base.h:80
void modbusBufferDestroy(ModbusBuffer *buffer, void *context)
Equivalent of modbusBufferFree() \copydetail modbusBufferFree()
Definition base.impl.h:78
#define MODBUS_GENERAL_ERROR(e)
Constructs a ModbusErrorInfo where source is set to MODBUS_ERROR_SOURCE_GENERAL and the error code is...
Definition base.h:93
static void modbusBufferModeRTU(ModbusBuffer *buffer)
Prepares buffer to store a Modbus RTU message.
Definition base.h:312
static void modbusBufferModeTCP(ModbusBuffer *buffer)
Prepares buffer to store a Modbus TCP message.
Definition base.h:321
#define MODBUS_RTU_PDU_OFFSET
Offset of PDU relative to the frame beginning in Modbus RTU.
Definition base.h:38
static ModbusError modbusPackRTU(uint8_t *frame, uint16_t length, uint8_t address)
Sets up address and CRC in a Modbus RTU frame.
Definition base.h:522
#define MODBUS_PDU_MAX
Maximum length of a PDU.
Definition base.h:33
Slave's types and basic functions (header)
static void * modbusSlaveGetUserPointer(const ModbusSlave *status)
Retreieves the custom context pointer.
Definition slave.h:174
static void modbusSlaveFreeResponse(ModbusSlave *status)
Frees memory allocated for slave's response frame.
Definition slave.h:192
ModbusError(* ModbusRegisterCallback)(const ModbusSlave *status, const ModbusRegisterCallbackArgs *args, ModbusRegisterCallbackResult *out)
A pointer to callback for performing all register operations.
Definition slave.h:69
ModbusError(* ModbusSlaveExceptionCallback)(const ModbusSlave *status, uint8_t function, ModbusExceptionCode code)
A pointer to a callback called when a Modbus exception is generated (for slave)
Definition slave.h:78
static ModbusError modbusSlaveAllocateResponse(ModbusSlave *status, uint16_t pduSize)
Allocates memory for slave's response frame.
Definition slave.h:184
ModbusSlaveFunctionHandler modbusSlaveDefaultFunctions[]
Associates function IDs with pointers to functions responsible for parsing. Length of this array is s...
Definition slave.impl.h:18
ModbusErrorInfo modbusBuildExceptionRTU(ModbusSlave *status, uint8_t address, uint8_t function, ModbusExceptionCode code)
Builds a Modbus RTU exception.
Definition slave.impl.h:168
const uint8_t modbusSlaveDefaultFunctionCount
Stores length of modbusSlaveDefaultFunctions.
Definition slave.impl.h:63
ModbusErrorInfo modbusSlaveInit(ModbusSlave *status, ModbusRegisterCallback registerCallback, ModbusSlaveExceptionCallback exceptionCallback, ModbusAllocator allocator, const ModbusSlaveFunctionHandler *functions, uint8_t functionCount)
Initializes slave device.
Definition slave.impl.h:79
ModbusErrorInfo modbusBuildExceptionPDU(ModbusSlave *status, uint8_t function, ModbusExceptionCode code)
Builds an exception PDU.
Definition slave.impl.h:143
ModbusErrorInfo modbusBuildException(ModbusSlave *status, uint8_t function, ModbusExceptionCode code)
Builds an exception response frame.
Definition slave.impl.h:118
ModbusErrorInfo modbusParseRequestTCP(ModbusSlave *status, const uint8_t *request, uint16_t requestLength)
Parses provided Modbus TCP request frame and generates a Modbus TCP response.
Definition slave.impl.h:362
ModbusErrorInfo modbusParseRequestRTU(ModbusSlave *status, uint8_t slaveAddress, const uint8_t *request, uint16_t requestLength)
Parses provided Modbus RTU request frame and generates a Modbus RTU response.
Definition slave.impl.h:299
void modbusSlaveDestroy(ModbusSlave *status)
Frees memory allocated in the ModbusSlave struct.
Definition slave.impl.h:99
ModbusErrorInfo modbusBuildExceptionTCP(ModbusSlave *status, uint16_t transactionID, uint8_t unitID, uint8_t function, ModbusExceptionCode code)
Builds a Modbus TCP exception.
Definition slave.impl.h:207
ModbusErrorInfo modbusParseRequestPDU(ModbusSlave *status, const uint8_t *request, uint8_t requestLength)
Parses provided PDU and generates PDU for the response frame.
Definition slave.impl.h:275
ModbusErrorInfo modbusParseRequest(ModbusSlave *status, const uint8_t *request, uint8_t requestLength)
Parses provided PDU and generates response honorinng pduOffset and padding set in ModbusSlave during ...
Definition slave.impl.h:249
Slave's functions for parsing requests (header)
ModbusErrorInfo modbusParseRequest1516(ModbusSlave *status, uint8_t function, const uint8_t *requestPDU, uint8_t requestLength)
Handles requests 15 and 16 (Write Multiple XX) and generates response.
Definition slave_func.impl.h:190
ModbusErrorInfo modbusParseRequest0506(ModbusSlave *status, uint8_t function, const uint8_t *requestPDU, uint8_t requestLength)
Handles requests 05 and 06 (Write Single XX) and generates response.
Definition slave_func.impl.h:131
ModbusErrorInfo modbusParseRequest22(ModbusSlave *status, uint8_t function, const uint8_t *requestPDU, uint8_t requestLength)
Handles request 22 (Mask Write Register) and generates response.
Definition slave_func.impl.h:270
ModbusErrorInfo modbusParseRequest01020304(ModbusSlave *status, uint8_t function, const uint8_t *requestPDU, uint8_t requestLength)
Handles requests 01, 02, 03 and 04 (Read Multiple XX) and generates response.
Definition slave_func.impl.h:21
uint16_t length
Length of the entire frame (PDU size + padding)
Definition base.h:282
uint8_t pduOffset
PDU offset relative to the beginning of the frame.
Definition base.h:285
uint8_t * data
Pointer to the frame buffer.
Definition base.h:280
uint8_t * pdu
A pointer to the PDU section of the frame.
Definition base.h:281
uint8_t padding
Number of extra bytes surrounding the PDU.
Definition base.h:284
Richer error represenation - source and type of error.
Definition base.h:126
Associates Modbus function ID with a pointer to a parsing function.
Definition slave.h:28
ModbusRequestParsingFunction ptr
Definition slave.h:30
uint8_t id
Definition slave.h:29
Slave device status.
Definition slave.h:90
uint8_t functionCount
Number of function handlers in the array (functions)
Definition slave.h:94
ModbusSlaveExceptionCallback exceptionCallback
A pointer to exception callback (optional)
Definition slave.h:92
const ModbusSlaveFunctionHandler * functions
A pointer to an array of function handlers (required)
Definition slave.h:93
ModbusRegisterCallback registerCallback
A pointer to register callback (required)
Definition slave.h:91
void * context
User's context pointer
Definition slave.h:99
ModbusBuffer response
Stores slave's response to master.
Definition slave.h:97