1#ifndef LIGHTMODBUS_BASE_H
2#define LIGHTMODBUS_BASE_H
18#ifndef LIGHTMODBUS_WARN_UNUSED
19#define LIGHTMODBUS_WARN_UNUSED __attribute__((warn_unused_result))
28#ifndef LIGHTMODBUS_ALWAYS_INLINE
29#define LIGHTMODBUS_ALWAYS_INLINE __attribute__((always_inline))
32#define MODBUS_PDU_MIN 1
33#define MODBUS_PDU_MAX 253
35#define MODBUS_RTU_ADU_MIN 4
36#define MODBUS_RTU_ADU_MAX 256
37#define MODBUS_RTU_ADU_PADDING 3
38#define MODBUS_RTU_PDU_OFFSET 1
40#define MODBUS_TCP_ADU_MIN 8
41#define MODBUS_TCP_ADU_MAX 260
42#define MODBUS_TCP_ADU_PADDING 7
43#define MODBUS_TCP_PDU_OFFSET 7
49#define LIGHTMODBUS_RET_ERROR LIGHTMODBUS_WARN_UNUSED ModbusErrorInfo
56#define MODBUS_ERROR_SOURCE_GENERAL 0u
62#define MODBUS_ERROR_SOURCE_REQUEST 1u
68#define MODBUS_ERROR_SOURCE_RESPONSE 2u
74#define MODBUS_ERROR_SOURCE_RESERVED 3u
80#define MODBUS_MAKE_ERROR(s, e) ((ModbusErrorInfo){.source = (s), .error = (e)})
86#define MODBUS_NO_ERROR() MODBUS_MAKE_ERROR(MODBUS_ERROR_SOURCE_GENERAL, MODBUS_OK)
93#define MODBUS_GENERAL_ERROR(e) MODBUS_MAKE_ERROR(MODBUS_ERROR_SOURCE_GENERAL, (MODBUS_ERROR_##e))
100#define MODBUS_REQUEST_ERROR(e) MODBUS_MAKE_ERROR(MODBUS_ERROR_SOURCE_REQUEST, (MODBUS_ERROR_##e))
107#define MODBUS_RESPONSE_ERROR(e) MODBUS_MAKE_ERROR(MODBUS_ERROR_SOURCE_RESPONSE, (MODBUS_ERROR_##e))
298uint16_t
modbusCRC(
const uint8_t *data, uint16_t length);
335 return (mask[n >> 3] & (1 << (n & 7))) != 0;
347 mask[n >> 3] |= (1 << (n & 7));
349 mask[n >> 3] &= ~(1 << (n & 7));
368 uint8_t hi = *(p + 1);
369 return (uint16_t) lo | ((uint16_t) hi << 8);
375static inline uint16_t
modbusWLE(uint8_t *p, uint16_t val)
387 uint8_t lo = *(p + 1);
389 return (uint16_t) lo | ((uint16_t) hi << 8);
395static inline uint16_t
modbusWBE(uint8_t *p, uint16_t val)
398 *(p + 1) = val & 0xff;
411 return index > UINT16_MAX - count + 1;
490 const uint8_t *frame,
554 const uint8_t *frame,
558 uint16_t *transactionID,
566 uint16_t protocolID =
modbusRBE(&frame[2]);
571 uint16_t messageLength =
modbusRBE(&frame[4]);
572 if (messageLength != length - 6)
595 uint16_t transactionID,
void modbusBufferFree(ModbusBuffer *buffer, void *context)
Frees memory allocated inside the buffer.
Definition base.impl.h:68
#define LIGHTMODBUS_WARN_UNUSED
Definition base.h:19
ModbusExceptionCode
Represents a Modbus exception code.
Definition base.h:230
@ MODBUS_EXCEP_ILLEGAL_ADDRESS
Illegal data address.
Definition base.h:233
@ MODBUS_EXCEP_ACK
Acknowledge.
Definition base.h:236
@ MODBUS_EXCEP_NONE
Definition base.h:231
@ MODBUS_EXCEP_NACK
Negative acknowledge.
Definition base.h:237
@ MODBUS_EXCEP_SLAVE_FAILURE
Slave could not process the request.
Definition base.h:235
@ MODBUS_EXCEP_ILLEGAL_FUNCTION
Illegal function code.
Definition base.h:232
@ MODBUS_EXCEP_ILLEGAL_VALUE
Illegal data value.
Definition base.h:234
static uint16_t modbusRLE(const uint8_t *p)
Safely reads a little-endian 16-bit word from provided pointer.
Definition base.h:365
uint16_t modbusCRC(const uint8_t *data, uint16_t length)
Calculates 16-bit Modbus CRC of provided data.
Definition base.impl.h:126
static ModbusError modbusGetErrorCode(ModbusErrorInfo err)
Returns ModbusError contained in ModbusErrorInfo.
Definition base.h:431
ModbusDataType
Represents different Modbus data types.
Definition base.h:244
@ MODBUS_DISCRETE_INPUT
Discrete input.
Definition base.h:248
@ MODBUS_HOLDING_REGISTER
Holding register.
Definition base.h:245
@ MODBUS_INPUT_REGISTER
Input register.
Definition base.h:246
@ MODBUS_COIL
Coil.
Definition base.h:247
#define LIGHTMODBUS_ALWAYS_INLINE
Definition base.h:29
#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_ERROR_FUNCTION
Invalid function.
Definition base.h:168
@ MODBUS_ERROR_RANGE
Invalid register range.
Definition base.h:193
@ MODBUS_ERROR_VALUE
Invalid register value.
Definition base.h:185
@ MODBUS_ERROR_OK
Same as MODBUS_OK.
Definition base.h:148
@ MODBUS_ERROR_LENGTH
Invalid frame length.
Definition base.h:156
@ MODBUS_ERROR_CRC
CRC invalid.
Definition base.h:199
@ MODBUS_ERROR_BAD_TRANSACTION
Mismatched transaction ID.
Definition base.h:213
@ MODBUS_ERROR_ALLOC
Memory allocation error.
Definition base.h:163
@ MODBUS_ERROR_BAD_PROTOCOL
Invalid protocol ID (nonzero)
Definition base.h:205
@ MODBUS_ERROR_OTHER
Other error.
Definition base.h:223
@ MODBUS_ERROR_COUNT
Invalid register count.
Definition base.h:175
@ MODBUS_ERROR_ADDRESS
Invalid slave address.
Definition base.h:218
@ MODBUS_ERROR_INDEX
Invalid index value.
Definition base.h:180
@ 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
ModbusError modbusBufferAllocateADU(ModbusBuffer *buffer, uint16_t pduSize, void *context)
Allocates memory to hold Modbus ADU.
Definition base.impl.h:98
static ModbusError modbusGetRequestError(ModbusErrorInfo err)
Returns request error from ModbusErrorInfo.
Definition base.h:462
static void modbusMaskWrite(uint8_t *mask, uint16_t n, uint8_t value)
Writes n-th bit in an array.
Definition base.h:344
#define MODBUS_ERROR_SOURCE_RESPONSE
The response frame contains errors.
Definition base.h:68
static uint8_t modbusCheckRangeU16(uint16_t index, uint16_t count)
Checks whether provided address range causes an uint16_t overflow.
Definition base.h:408
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
#define MODBUS_RTU_ADU_MAX
Maximum length of ADU in Modbus RTU.
Definition base.h:36
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
static uint16_t modbusWBE(uint8_t *p, uint16_t val)
Safely writes a big-endian 16-bit word to provided pointer.
Definition base.h:395
#define LIGHTMODBUS_RET_ERROR
Return type for library functions returning ModbusErrorInfo that should be handled properly.
Definition base.h:49
static ModbusError modbusGetGeneralError(ModbusErrorInfo err)
Returns general error from ModbusErrorInfo.
Definition base.h:452
ModbusError modbusDefaultAllocator(ModbusBuffer *buffer, uint16_t size, void *context)
The default memory allocator based on realloc()
Definition base.impl.h:21
ModbusError(* ModbusAllocator)(struct ModbusBuffer *buffer, uint16_t size, void *context)
Pointer to a memory allocator function.
Definition base.h:259
static uint8_t modbusGetErrorSource(ModbusErrorInfo err)
Returns uint8_t describing error source of ModbusErrorInfo.
Definition base.h:422
void modbusBufferDestroy(ModbusBuffer *buffer, void *context)
Equivalent of modbusBufferFree() \copydetail modbusBufferFree()
Definition base.impl.h:78
static ModbusError modbusGetResponseError(ModbusErrorInfo err)
Returns response error from ModbusErrorInfo.
Definition base.h:472
static uint16_t modbusRBE(const uint8_t *p)
Safely reads a big-endian 16-bit word from provided pointer.
Definition base.h:385
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 uint16_t modbusBitsToBytes(uint16_t n)
Returns number of bytes necessary to hold given number of bits.
Definition base.h:357
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
static uint16_t modbusWLE(uint8_t *p, uint16_t val)
Safely writes a little-endian 16-bit word to provided pointer.
Definition base.h:375
#define MODBUS_TCP_ADU_MAX
Maximum length of ADU in Modbus TCP.
Definition base.h:41
static uint8_t modbusMaskRead(const uint8_t *mask, uint16_t n)
Reads n-th bit from an array.
Definition base.h:333
Stores a Modbus frame.
Definition base.h:276
uint16_t length
Length of the entire frame (PDU size + padding)
Definition base.h:282
ModbusAllocator allocator
Pointer to the allocator function.
Definition base.h:278
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
unsigned int source
Source of the error (e.g. MODBUS_ERROR_SOURCE_REQUEST)
Definition base.h:127
unsigned int error
Contains ModbusError.
Definition base.h:128