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/binary_helpers.c \
|
||||
src/conversion.c \
|
||||
src/crc.c \
|
||||
src/device.c \
|
||||
src/session.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,
|
||||
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 -------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
const uint8_t *buffer, int buffer_size)
|
||||
{
|
||||
|
@ -119,8 +98,8 @@ static int modbus_serial_rtu_send(void *priv,
|
|||
if (result < 0)
|
||||
return SR_ERR;
|
||||
|
||||
crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
|
||||
crc = modbus_serial_rtu_crc(crc, buffer, buffer_size);
|
||||
crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
|
||||
crc = sr_crc16(crc, buffer, buffer_size);
|
||||
|
||||
result = serial_write_blocking(serial, &crc, sizeof(crc), 0);
|
||||
if (result < 0)
|
||||
|
@ -143,8 +122,8 @@ static int modbus_serial_rtu_read_begin(void *priv, uint8_t *function_code)
|
|||
if (ret != 1)
|
||||
return SR_ERR;
|
||||
|
||||
modbus->crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
|
||||
modbus->crc = modbus_serial_rtu_crc(modbus->crc, function_code, 1);
|
||||
modbus->crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
|
||||
modbus->crc = sr_crc16(modbus->crc, function_code, 1);
|
||||
|
||||
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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
modbus->crc = modbus_serial_rtu_crc(modbus->crc, buf, ret);
|
||||
modbus->crc = sr_crc16(modbus->crc, buf, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue