Modbus RTU class for slave devices. It shares data with other software components via a Message queue object, and can exist more than one Modbus Slave RTU instances in a application program.

Dependents:   Nucleo_modbus_protocol_test

Committer:
gabrielrivas
Date:
Wed Jan 21 02:59:27 2015 +0000
Revision:
6:0143a57e0c8e
Parent:
1:5efaa10b9a3f
Added timer based synchronization to the serial port receiving part.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gabrielrivas 0:81fee41d95f1 1 /* Modbus RTU Slave Library
gabrielrivas 1:5efaa10b9a3f 2 * Copyright (c) 2015 Gabriel Rivas
gabrielrivas 0:81fee41d95f1 3 *
gabrielrivas 0:81fee41d95f1 4 * Licensed under the Apache License, Version 2.0 (the "License");
gabrielrivas 0:81fee41d95f1 5 * you may not use this file except in compliance with the License.
gabrielrivas 0:81fee41d95f1 6 * You may obtain a copy of the License at
gabrielrivas 0:81fee41d95f1 7 *
gabrielrivas 0:81fee41d95f1 8 * http://www.apache.org/licenses/LICENSE-2.0
gabrielrivas 0:81fee41d95f1 9 *
gabrielrivas 0:81fee41d95f1 10 * Unless required by applicable law or agreed to in writing, software
gabrielrivas 0:81fee41d95f1 11 * distributed under the License is distributed on an "AS IS" BASIS,
gabrielrivas 0:81fee41d95f1 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
gabrielrivas 0:81fee41d95f1 13 * See the License for the specific language governing permissions and
gabrielrivas 0:81fee41d95f1 14 * limitations under the License.
gabrielrivas 0:81fee41d95f1 15 */
gabrielrivas 0:81fee41d95f1 16
gabrielrivas 0:81fee41d95f1 17 #include "ModbusSlaveRTU.h"
gabrielrivas 0:81fee41d95f1 18 #include "MessageQueue.h"
gabrielrivas 0:81fee41d95f1 19
gabrielrivas 0:81fee41d95f1 20 #define MODBUS_FRAME_OVERHEAD_BYTES (5)
gabrielrivas 0:81fee41d95f1 21 #define MODBUS_ID_FUNCTION_SIZE (3)
gabrielrivas 0:81fee41d95f1 22 #define CRC_POSITION1 (m_frame.mByteCount + MODBUS_ID_FUNCTION_SIZE)
gabrielrivas 0:81fee41d95f1 23 #define CRC_POSITION2 (m_frame.mByteCount + MODBUS_ID_FUNCTION_SIZE + 1)
gabrielrivas 0:81fee41d95f1 24
gabrielrivas 0:81fee41d95f1 25 ModbusSlaveRTU::ModbusSlaveRTU( uint8_t id,
gabrielrivas 0:81fee41d95f1 26 MessageQueue<uint8_t>* txQueue,
gabrielrivas 0:81fee41d95f1 27 MessageQueue<uint8_t>* rxQueue,
gabrielrivas 0:81fee41d95f1 28 ThreadSafeArray_t *coilRegisters,
gabrielrivas 0:81fee41d95f1 29 ThreadSafeArray_t *inputRegisters,
gabrielrivas 0:81fee41d95f1 30 ThreadSafeArray_t *holdingRegisters)
gabrielrivas 0:81fee41d95f1 31 {
gabrielrivas 0:81fee41d95f1 32 // assert(txQueue != NULL);
gabrielrivas 0:81fee41d95f1 33 m_bTxQueue = txQueue;
gabrielrivas 0:81fee41d95f1 34
gabrielrivas 0:81fee41d95f1 35 // assert(rxQueue != NULL);
gabrielrivas 0:81fee41d95f1 36 m_bRxQueue = rxQueue;
gabrielrivas 0:81fee41d95f1 37
gabrielrivas 0:81fee41d95f1 38 m_state = WAIT_REQUEST_MESSAGE;
gabrielrivas 0:81fee41d95f1 39
gabrielrivas 1:5efaa10b9a3f 40 m_address = id;
gabrielrivas 1:5efaa10b9a3f 41 m_status = LISTENING;
gabrielrivas 0:81fee41d95f1 42
gabrielrivas 0:81fee41d95f1 43 // assert(coilRegisters != NULL);
gabrielrivas 0:81fee41d95f1 44 m_memoryMap.coilRegisters = coilRegisters;
gabrielrivas 0:81fee41d95f1 45
gabrielrivas 0:81fee41d95f1 46 // assert(inputRegisters != NULL);
gabrielrivas 0:81fee41d95f1 47 m_memoryMap.inputRegisters = inputRegisters;
gabrielrivas 0:81fee41d95f1 48
gabrielrivas 0:81fee41d95f1 49 // assert(holdingRegisters != NULL);
gabrielrivas 0:81fee41d95f1 50 m_memoryMap.holdingRegisters = holdingRegisters;
gabrielrivas 0:81fee41d95f1 51 }
gabrielrivas 0:81fee41d95f1 52
gabrielrivas 0:81fee41d95f1 53 void ModbusSlaveRTU::trigger(void)
gabrielrivas 0:81fee41d95f1 54 {
gabrielrivas 0:81fee41d95f1 55 m_state = GET_RECEIVED_BYTES;
gabrielrivas 0:81fee41d95f1 56 }
gabrielrivas 0:81fee41d95f1 57
gabrielrivas 0:81fee41d95f1 58 ModbusSlaveRTU::MbStatusTypes_t ModbusSlaveRTU::getStatus(void)
gabrielrivas 0:81fee41d95f1 59 {
gabrielrivas 1:5efaa10b9a3f 60 return m_status;
gabrielrivas 0:81fee41d95f1 61 }
gabrielrivas 0:81fee41d95f1 62
gabrielrivas 0:81fee41d95f1 63 void ModbusSlaveRTU::FSM(void)
gabrielrivas 0:81fee41d95f1 64 {
gabrielrivas 0:81fee41d95f1 65 uint32_t count;
gabrielrivas 0:81fee41d95f1 66
gabrielrivas 0:81fee41d95f1 67 switch(m_state) {
gabrielrivas 0:81fee41d95f1 68 case WAIT_REQUEST_MESSAGE:
gabrielrivas 1:5efaa10b9a3f 69 m_status = LISTENING;
gabrielrivas 0:81fee41d95f1 70
gabrielrivas 0:81fee41d95f1 71 break;
gabrielrivas 0:81fee41d95f1 72 case GET_RECEIVED_BYTES:
gabrielrivas 0:81fee41d95f1 73 count = m_bRxQueue->getWriteIndex();
gabrielrivas 1:5efaa10b9a3f 74 m_status = PROCESSING;
gabrielrivas 0:81fee41d95f1 75 if ((count > 0) && (count < MODBUS_MAX_LEN)) {
gabrielrivas 0:81fee41d95f1 76 for (uint32_t i = 0; i < count; i++) {
gabrielrivas 0:81fee41d95f1 77 uint8_t data = m_bRxQueue->read();
gabrielrivas 0:81fee41d95f1 78 m_receivedMessage[i] = data;
gabrielrivas 0:81fee41d95f1 79 }
gabrielrivas 0:81fee41d95f1 80 m_state = BUILD_RESPONSE_MESSAGE;
gabrielrivas 0:81fee41d95f1 81 m_bRxQueue->reset();
gabrielrivas 0:81fee41d95f1 82 } else {
gabrielrivas 0:81fee41d95f1 83 m_state = WAIT_REQUEST_MESSAGE;
gabrielrivas 0:81fee41d95f1 84 }
gabrielrivas 0:81fee41d95f1 85 break;
gabrielrivas 0:81fee41d95f1 86 case BUILD_RESPONSE_MESSAGE:
gabrielrivas 1:5efaa10b9a3f 87 if (buildResponse() == NO_ERROR) {
gabrielrivas 1:5efaa10b9a3f 88 m_status = SENDING;
gabrielrivas 0:81fee41d95f1 89 m_state = TRANSMIT_RESPONSE_MESSAGE;
gabrielrivas 0:81fee41d95f1 90 } else {
gabrielrivas 1:5efaa10b9a3f 91 m_status = LISTENING;
gabrielrivas 0:81fee41d95f1 92 m_state = WAIT_REQUEST_MESSAGE;
gabrielrivas 0:81fee41d95f1 93 }
gabrielrivas 0:81fee41d95f1 94 break;
gabrielrivas 0:81fee41d95f1 95 case TRANSMIT_RESPONSE_MESSAGE:
gabrielrivas 0:81fee41d95f1 96 for (uint32_t i = 0; i < m_frame.mSize; i++) {
gabrielrivas 0:81fee41d95f1 97 m_bTxQueue->write(m_responseMessage[i]);
gabrielrivas 0:81fee41d95f1 98 }
gabrielrivas 0:81fee41d95f1 99
gabrielrivas 1:5efaa10b9a3f 100 m_status = LISTENING;
gabrielrivas 0:81fee41d95f1 101 m_state = WAIT_REQUEST_MESSAGE;
gabrielrivas 0:81fee41d95f1 102 break;
gabrielrivas 0:81fee41d95f1 103 default:
gabrielrivas 0:81fee41d95f1 104 break;
gabrielrivas 0:81fee41d95f1 105 }
gabrielrivas 0:81fee41d95f1 106
gabrielrivas 0:81fee41d95f1 107 }
gabrielrivas 0:81fee41d95f1 108
gabrielrivas 1:5efaa10b9a3f 109 ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::buildResponse(void)
gabrielrivas 0:81fee41d95f1 110 {
gabrielrivas 1:5efaa10b9a3f 111 MbReceivedMessageErrors_t result = NO_ERROR;
gabrielrivas 0:81fee41d95f1 112
gabrielrivas 0:81fee41d95f1 113 switch(m_receivedMessage[FUNCTION]) {
gabrielrivas 0:81fee41d95f1 114 case READ_COIL_STATUS:
gabrielrivas 0:81fee41d95f1 115 result = readCoilRegistersHandler();
gabrielrivas 0:81fee41d95f1 116 break;
gabrielrivas 0:81fee41d95f1 117 case READ_HOLDING_REGISTERS:
gabrielrivas 0:81fee41d95f1 118 result = readHoldingRegistersHandler();
gabrielrivas 0:81fee41d95f1 119 break;
gabrielrivas 0:81fee41d95f1 120 case FORCE_SINGLE_COIL:
gabrielrivas 0:81fee41d95f1 121 break;
gabrielrivas 0:81fee41d95f1 122 default:
gabrielrivas 0:81fee41d95f1 123 break;
gabrielrivas 0:81fee41d95f1 124 }
gabrielrivas 0:81fee41d95f1 125
gabrielrivas 0:81fee41d95f1 126 return result;
gabrielrivas 0:81fee41d95f1 127 }
gabrielrivas 0:81fee41d95f1 128
gabrielrivas 0:81fee41d95f1 129 uint8_t ModbusSlaveRTU::checkMessageCRC(uint8_t * data)
gabrielrivas 0:81fee41d95f1 130 {
gabrielrivas 0:81fee41d95f1 131 uint8_t function = data[FUNCTION];
gabrielrivas 0:81fee41d95f1 132 uint8_t byteCount;
gabrielrivas 0:81fee41d95f1 133 uint16_t crcVal;
gabrielrivas 0:81fee41d95f1 134 uint16_t crcCalc;
gabrielrivas 0:81fee41d95f1 135 uint8_t result;
gabrielrivas 0:81fee41d95f1 136
gabrielrivas 0:81fee41d95f1 137 if (function != READ_EXCEPTION_STATUS) {
gabrielrivas 0:81fee41d95f1 138 byteCount = 8;
gabrielrivas 0:81fee41d95f1 139 crcVal = data[byteCount-1];
gabrielrivas 0:81fee41d95f1 140 crcVal = (crcVal << 8) | data[byteCount - 2];
gabrielrivas 0:81fee41d95f1 141 crcCalc = getCRC(data, byteCount - 2);
gabrielrivas 0:81fee41d95f1 142
gabrielrivas 0:81fee41d95f1 143 if (crcVal == crcCalc) {
gabrielrivas 0:81fee41d95f1 144 result = 1;
gabrielrivas 0:81fee41d95f1 145 } else {
gabrielrivas 0:81fee41d95f1 146 result = 0;
gabrielrivas 0:81fee41d95f1 147 }
gabrielrivas 0:81fee41d95f1 148 } else {
gabrielrivas 0:81fee41d95f1 149 result = 0;
gabrielrivas 0:81fee41d95f1 150 }
gabrielrivas 0:81fee41d95f1 151
gabrielrivas 0:81fee41d95f1 152 return result;
gabrielrivas 0:81fee41d95f1 153 }
gabrielrivas 0:81fee41d95f1 154
gabrielrivas 0:81fee41d95f1 155 uint16_t ModbusSlaveRTU::getCRC(uint8_t * data,uint8_t len)
gabrielrivas 0:81fee41d95f1 156 {
gabrielrivas 0:81fee41d95f1 157 uint16_t crc = 0xFFFF;
gabrielrivas 0:81fee41d95f1 158 uint8_t i;
gabrielrivas 0:81fee41d95f1 159
gabrielrivas 0:81fee41d95f1 160 while (len--) {
gabrielrivas 0:81fee41d95f1 161 i = *data++;
gabrielrivas 0:81fee41d95f1 162 *(uint8_t *)&crc ^= i;
gabrielrivas 0:81fee41d95f1 163
gabrielrivas 0:81fee41d95f1 164 for (i = 0; i != 8; i++) {
gabrielrivas 0:81fee41d95f1 165 if (crc & 0x0001) {
gabrielrivas 0:81fee41d95f1 166 crc = (crc >> 1);
gabrielrivas 0:81fee41d95f1 167 crc ^= 0xA001;
gabrielrivas 0:81fee41d95f1 168 } else {
gabrielrivas 0:81fee41d95f1 169 crc = (crc >> 1);
gabrielrivas 0:81fee41d95f1 170 }
gabrielrivas 0:81fee41d95f1 171 }
gabrielrivas 0:81fee41d95f1 172 }
gabrielrivas 0:81fee41d95f1 173 return crc;
gabrielrivas 0:81fee41d95f1 174 }
gabrielrivas 0:81fee41d95f1 175
gabrielrivas 1:5efaa10b9a3f 176 ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::readHoldingRegistersHandler(void)
gabrielrivas 0:81fee41d95f1 177 {
gabrielrivas 0:81fee41d95f1 178 uint8_t i;
gabrielrivas 1:5efaa10b9a3f 179 MbReceivedMessageErrors_t result = NO_ERROR;
gabrielrivas 0:81fee41d95f1 180
gabrielrivas 0:81fee41d95f1 181 m_frame.mAddress = m_receivedMessage[ADDRESS];
gabrielrivas 0:81fee41d95f1 182 m_frame.mFunction = static_cast<MbFunctionCodes_t>(m_receivedMessage[FUNCTION]);
gabrielrivas 0:81fee41d95f1 183
gabrielrivas 0:81fee41d95f1 184 result = checkReceivedMessageErrors(m_memoryMap.holdingRegisters);
gabrielrivas 0:81fee41d95f1 185
gabrielrivas 0:81fee41d95f1 186 if (result < ADDRESS_ERROR) {
gabrielrivas 1:5efaa10b9a3f 187 m_frame.mByteCount = ((m_receivedMessage[REGISTER_COUNT] << 8) | (m_receivedMessage[REGISTER_COUNT + 1] & 0xFF));
gabrielrivas 0:81fee41d95f1 188 m_frame.mByteCount <<= 1;
gabrielrivas 0:81fee41d95f1 189
gabrielrivas 0:81fee41d95f1 190
gabrielrivas 0:81fee41d95f1 191 if ((m_frame.mByteCount + m_frame.mOffset) > m_memoryMap.holdingRegisters->length)
gabrielrivas 0:81fee41d95f1 192 m_frame.mByteCount = m_memoryMap.holdingRegisters->length - m_frame.mOffset;
gabrielrivas 0:81fee41d95f1 193
gabrielrivas 0:81fee41d95f1 194 (m_memoryMap.holdingRegisters)->mutex.lock();
gabrielrivas 0:81fee41d95f1 195
gabrielrivas 0:81fee41d95f1 196 m_frame.mSize = m_frame.mByteCount + MODBUS_FRAME_OVERHEAD_BYTES;
gabrielrivas 0:81fee41d95f1 197
gabrielrivas 0:81fee41d95f1 198 for(i = 0; i < m_frame.mByteCount; i++) {
gabrielrivas 0:81fee41d95f1 199 m_responseMessage[i + DATA_START] = *((m_memoryMap.holdingRegisters)->data + i + m_frame.mOffset);
gabrielrivas 0:81fee41d95f1 200 }
gabrielrivas 0:81fee41d95f1 201
gabrielrivas 0:81fee41d95f1 202 appendHeaderAndTailToMessage();
gabrielrivas 0:81fee41d95f1 203
gabrielrivas 0:81fee41d95f1 204 (m_memoryMap.holdingRegisters)->mutex.unlock();
gabrielrivas 0:81fee41d95f1 205 }
gabrielrivas 0:81fee41d95f1 206
gabrielrivas 0:81fee41d95f1 207 return result;
gabrielrivas 0:81fee41d95f1 208 }
gabrielrivas 0:81fee41d95f1 209
gabrielrivas 1:5efaa10b9a3f 210 ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::readCoilRegistersHandler(void)
gabrielrivas 0:81fee41d95f1 211 {
gabrielrivas 1:5efaa10b9a3f 212 MbReceivedMessageErrors_t result = NO_ERROR;
gabrielrivas 0:81fee41d95f1 213 uint16_t initRegister;
gabrielrivas 0:81fee41d95f1 214 uint16_t initCoil;
gabrielrivas 0:81fee41d95f1 215 uint16_t endRegister;
gabrielrivas 0:81fee41d95f1 216 uint16_t i = 0;
gabrielrivas 0:81fee41d95f1 217 uint16_t j = 0;
gabrielrivas 0:81fee41d95f1 218 uint8_t mask;
gabrielrivas 0:81fee41d95f1 219 uint8_t residual_bits;
gabrielrivas 0:81fee41d95f1 220
gabrielrivas 0:81fee41d95f1 221 m_frame.mAddress = m_receivedMessage[ADDRESS];
gabrielrivas 0:81fee41d95f1 222 m_frame.mFunction = static_cast<MbFunctionCodes_t>(m_receivedMessage[FUNCTION]);
gabrielrivas 0:81fee41d95f1 223
gabrielrivas 0:81fee41d95f1 224 result = checkReceivedMessageErrors(m_memoryMap.coilRegisters);
gabrielrivas 0:81fee41d95f1 225
gabrielrivas 0:81fee41d95f1 226 if (result < ADDRESS_ERROR) {
gabrielrivas 1:5efaa10b9a3f 227 m_frame.mByteCount = ((m_receivedMessage[REGISTER_COUNT] << 8) | (m_receivedMessage[REGISTER_COUNT + 1] & 0xFF));
gabrielrivas 0:81fee41d95f1 228
gabrielrivas 0:81fee41d95f1 229 residual_bits = (m_frame.mByteCount) % 8;
gabrielrivas 0:81fee41d95f1 230 m_frame.mByteCount >>= 3;
gabrielrivas 0:81fee41d95f1 231
gabrielrivas 0:81fee41d95f1 232 if (residual_bits > 0)
gabrielrivas 0:81fee41d95f1 233 m_frame.mByteCount += 1;
gabrielrivas 0:81fee41d95f1 234
gabrielrivas 0:81fee41d95f1 235 initRegister = m_frame.mOffset >> 3;
gabrielrivas 0:81fee41d95f1 236 initCoil = m_frame.mOffset % 8;
gabrielrivas 0:81fee41d95f1 237 endRegister = initRegister + (m_frame.mByteCount);
gabrielrivas 0:81fee41d95f1 238
gabrielrivas 0:81fee41d95f1 239 if (m_frame.mByteCount == 0)
gabrielrivas 0:81fee41d95f1 240 endRegister -= 1;
gabrielrivas 0:81fee41d95f1 241
gabrielrivas 0:81fee41d95f1 242 mask = (1 << residual_bits) - 1;
gabrielrivas 0:81fee41d95f1 243
gabrielrivas 0:81fee41d95f1 244 if ((m_frame.mByteCount + m_frame.mOffset) > m_memoryMap.holdingRegisters->length)
gabrielrivas 0:81fee41d95f1 245 m_frame.mByteCount = m_memoryMap.holdingRegisters->length - m_frame.mOffset;
gabrielrivas 0:81fee41d95f1 246
gabrielrivas 0:81fee41d95f1 247 m_frame.mSize = m_frame.mByteCount + MODBUS_FRAME_OVERHEAD_BYTES;
gabrielrivas 0:81fee41d95f1 248
gabrielrivas 0:81fee41d95f1 249 m_memoryMap.coilRegisters->mutex.lock();
gabrielrivas 0:81fee41d95f1 250
gabrielrivas 0:81fee41d95f1 251 //Process coil data to generate the response message.
gabrielrivas 0:81fee41d95f1 252 for (i = initRegister; i < endRegister; i++) {
gabrielrivas 0:81fee41d95f1 253 m_responseMessage[j++ + DATA_START] = (m_memoryMap.coilRegisters->data[i] >> initCoil) |
gabrielrivas 0:81fee41d95f1 254 (m_memoryMap.coilRegisters->data[i+1] << (8 - initCoil));
gabrielrivas 0:81fee41d95f1 255 }
gabrielrivas 0:81fee41d95f1 256
gabrielrivas 0:81fee41d95f1 257 m_responseMessage[j + DATA_START] = (m_memoryMap.coilRegisters->data[i] >> initCoil) |
gabrielrivas 0:81fee41d95f1 258 (m_memoryMap.coilRegisters->data[i+1] << (8 - initCoil));
gabrielrivas 0:81fee41d95f1 259 m_responseMessage[j + DATA_START] &= mask;
gabrielrivas 0:81fee41d95f1 260
gabrielrivas 0:81fee41d95f1 261 appendHeaderAndTailToMessage();
gabrielrivas 0:81fee41d95f1 262
gabrielrivas 0:81fee41d95f1 263 m_memoryMap.coilRegisters->mutex.unlock();
gabrielrivas 0:81fee41d95f1 264 }
gabrielrivas 0:81fee41d95f1 265
gabrielrivas 0:81fee41d95f1 266 return result;
gabrielrivas 0:81fee41d95f1 267 }
gabrielrivas 0:81fee41d95f1 268
gabrielrivas 0:81fee41d95f1 269 void ModbusSlaveRTU::appendHeaderAndTailToMessage(void)
gabrielrivas 0:81fee41d95f1 270 {
gabrielrivas 0:81fee41d95f1 271 uint16_t mCRC;
gabrielrivas 0:81fee41d95f1 272
gabrielrivas 0:81fee41d95f1 273 m_responseMessage[ADDRESS] = m_frame.mAddress;
gabrielrivas 0:81fee41d95f1 274 m_responseMessage[FUNCTION] = m_frame.mFunction;
gabrielrivas 0:81fee41d95f1 275 m_responseMessage[BYTE_COUNT] = m_frame.mByteCount;
gabrielrivas 0:81fee41d95f1 276
gabrielrivas 0:81fee41d95f1 277 mCRC = getCRC(m_responseMessage,m_frame.mByteCount + DATA_START);
gabrielrivas 0:81fee41d95f1 278
gabrielrivas 0:81fee41d95f1 279 m_responseMessage[CRC_POSITION1] = (uint8_t) mCRC & 0xFF;
gabrielrivas 0:81fee41d95f1 280 m_responseMessage[CRC_POSITION2] = (uint8_t) (mCRC >> 8) & 0xFF;
gabrielrivas 0:81fee41d95f1 281 }
gabrielrivas 0:81fee41d95f1 282
gabrielrivas 1:5efaa10b9a3f 283 ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::checkReceivedMessageErrors(ThreadSafeArray_t *array)
gabrielrivas 0:81fee41d95f1 284 {
gabrielrivas 1:5efaa10b9a3f 285 MbReceivedMessageErrors_t result = NO_ERROR;
gabrielrivas 0:81fee41d95f1 286
gabrielrivas 0:81fee41d95f1 287 //Check if Modbus Address is correct
gabrielrivas 1:5efaa10b9a3f 288 if (m_frame.mAddress != m_address) {
gabrielrivas 0:81fee41d95f1 289 result = ADDRESS_ERROR;
gabrielrivas 0:81fee41d95f1 290 }
gabrielrivas 0:81fee41d95f1 291
gabrielrivas 0:81fee41d95f1 292 //Verify message errors
gabrielrivas 0:81fee41d95f1 293 if (checkMessageCRC(m_receivedMessage) == 0) {
gabrielrivas 0:81fee41d95f1 294 result = CRC_ERROR;
gabrielrivas 0:81fee41d95f1 295 }
gabrielrivas 0:81fee41d95f1 296
gabrielrivas 0:81fee41d95f1 297 //Verify offset
gabrielrivas 1:5efaa10b9a3f 298 m_frame.mOffset = ((m_receivedMessage[BYTE_OFFSET] << 8) | (m_receivedMessage[BYTE_OFFSET + 1] & 0xFF));
gabrielrivas 0:81fee41d95f1 299 if ((m_frame.mOffset > array->length - 1) ||
gabrielrivas 0:81fee41d95f1 300 (m_frame.mOffset > MODBUS_MAX_LEN-1)) {
gabrielrivas 0:81fee41d95f1 301 result = OFFSET_ERROR;
gabrielrivas 0:81fee41d95f1 302 }
gabrielrivas 0:81fee41d95f1 303
gabrielrivas 0:81fee41d95f1 304 return result;
gabrielrivas 0:81fee41d95f1 305 }