crc: Factor out CRC16 implementation from Modbus
Being able to calculate a CRC16 is useful in multiple places, factor this into a new module with CRC implementation. This module currently only supports ANSI/Modbus/USB flavor of CRC16. Signed-off-by: Andreas Sandberg <andreas@sandberg.pp.se>
This commit is contained in:
parent
8b607a24e7
commit
4ea012bdf5
|
@ -52,6 +52,7 @@ libsigrok_la_SOURCES = \
|
||||||
src/backend.c \
|
src/backend.c \
|
||||||
src/binary_helpers.c \
|
src/binary_helpers.c \
|
||||||
src/conversion.c \
|
src/conversion.c \
|
||||||
|
src/crc.c \
|
||||||
src/device.c \
|
src/device.c \
|
||||||
src/session.c \
|
src/session.c \
|
||||||
src/session_file.c \
|
src/session_file.c \
|
||||||
|
|
|
@ -1783,6 +1783,22 @@ SR_PRIV int bv_get_value(float *out, const struct binary_value_spec *spec, const
|
||||||
SR_PRIV int bv_send_analog_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch,
|
SR_PRIV int bv_send_analog_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch,
|
||||||
const struct binary_analog_channel *spec, const void *data, size_t length);
|
const struct binary_analog_channel *spec, const void *data, size_t length);
|
||||||
|
|
||||||
|
/*--- crc.c -----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define SR_CRC16_DEFAULT_INIT 0xffffU
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a CRC16 checksum using the 0x8005 polynomial.
|
||||||
|
*
|
||||||
|
* This CRC16 flavor is also known as CRC16-ANSI or CRC16-MODBUS.
|
||||||
|
*
|
||||||
|
* @param crc Initial value (typically 0xffff)
|
||||||
|
* @param buffer Input buffer
|
||||||
|
* @param len Buffer length
|
||||||
|
* @return Checksum
|
||||||
|
*/
|
||||||
|
SR_PRIV uint16_t sr_crc16(uint16_t crc, const uint8_t *buffer, int len);
|
||||||
|
|
||||||
/*--- modbus/modbus.c -------------------------------------------------------*/
|
/*--- modbus/modbus.c -------------------------------------------------------*/
|
||||||
|
|
||||||
struct sr_modbus_dev_inst {
|
struct sr_modbus_dev_inst {
|
||||||
|
|
|
@ -81,27 +81,6 @@ static int modbus_serial_rtu_source_remove(struct sr_session *session,
|
||||||
return serial_source_remove(session, serial);
|
return serial_source_remove(session, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t modbus_serial_rtu_crc(uint16_t crc,
|
|
||||||
const uint8_t *buffer, int len)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!buffer || len < 0)
|
|
||||||
return crc;
|
|
||||||
|
|
||||||
while (len--) {
|
|
||||||
crc ^= *buffer++;
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
int carry = crc & 1;
|
|
||||||
crc >>= 1;
|
|
||||||
if (carry)
|
|
||||||
crc ^= 0xA001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int modbus_serial_rtu_send(void *priv,
|
static int modbus_serial_rtu_send(void *priv,
|
||||||
const uint8_t *buffer, int buffer_size)
|
const uint8_t *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
|
@ -119,8 +98,8 @@ static int modbus_serial_rtu_send(void *priv,
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return SR_ERR;
|
return SR_ERR;
|
||||||
|
|
||||||
crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
|
crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
|
||||||
crc = modbus_serial_rtu_crc(crc, buffer, buffer_size);
|
crc = sr_crc16(crc, buffer, buffer_size);
|
||||||
|
|
||||||
result = serial_write_blocking(serial, &crc, sizeof(crc), 0);
|
result = serial_write_blocking(serial, &crc, sizeof(crc), 0);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
|
@ -143,8 +122,8 @@ static int modbus_serial_rtu_read_begin(void *priv, uint8_t *function_code)
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
return SR_ERR;
|
return SR_ERR;
|
||||||
|
|
||||||
modbus->crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
|
modbus->crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
|
||||||
modbus->crc = modbus_serial_rtu_crc(modbus->crc, function_code, 1);
|
modbus->crc = sr_crc16(modbus->crc, function_code, 1);
|
||||||
|
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +136,7 @@ static int modbus_serial_rtu_read_data(void *priv, uint8_t *buf, int maxlen)
|
||||||
ret = serial_read_nonblocking(modbus->serial, buf, maxlen);
|
ret = serial_read_nonblocking(modbus->serial, buf, maxlen);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
modbus->crc = modbus_serial_rtu_crc(modbus->crc, buf, ret);
|
modbus->crc = sr_crc16(modbus->crc, buf, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue