Implement the read function
The read command appears to be limited to the range 0x1000-0x1100. That range seems to correspond with the first 256 bytes of the full memory dump. The packet size of 32 bytes is an arbitrary choice.
This commit is contained in:
parent
39aa859d19
commit
c3dc368163
@ -45,6 +45,9 @@
|
||||
#define RB_PROFILE_END SZ_MEMORY
|
||||
#define RB_PROFILE_DISTANCE(a,b) ringbuffer_distance (a, b, 0, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
||||
|
||||
#define MAXRETRIES 4
|
||||
#define PACKETSIZE 32
|
||||
|
||||
typedef struct cressi_leonardo_device_t {
|
||||
dc_device_t base;
|
||||
dc_serial_t *port;
|
||||
@ -52,6 +55,7 @@ typedef struct cressi_leonardo_device_t {
|
||||
} cressi_leonardo_device_t;
|
||||
|
||||
static dc_status_t cressi_leonardo_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t cressi_leonardo_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||
static dc_status_t cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
static dc_status_t cressi_leonardo_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t cressi_leonardo_device_close (dc_device_t *abstract);
|
||||
@ -60,13 +64,102 @@ static const dc_device_vtable_t cressi_leonardo_device_vtable = {
|
||||
sizeof(cressi_leonardo_device_t),
|
||||
DC_FAMILY_CRESSI_LEONARDO,
|
||||
cressi_leonardo_device_set_fingerprint, /* set_fingerprint */
|
||||
NULL, /* read */
|
||||
cressi_leonardo_device_read, /* read */
|
||||
NULL, /* write */
|
||||
cressi_leonardo_device_dump, /* dump */
|
||||
cressi_leonardo_device_foreach, /* foreach */
|
||||
cressi_leonardo_device_close /* close */
|
||||
};
|
||||
|
||||
static void
|
||||
cressi_leonardo_make_ascii (const unsigned char raw[], unsigned int rsize, unsigned char ascii[], unsigned int asize)
|
||||
{
|
||||
assert (asize == 2 * (rsize + 3));
|
||||
|
||||
// Header
|
||||
ascii[0] = '{';
|
||||
|
||||
// Data
|
||||
array_convert_bin2hex (raw, rsize, ascii + 1, 2 * rsize);
|
||||
|
||||
// Checksum
|
||||
unsigned short crc = checksum_crc_ccitt_uint16 (ascii + 1, 2 * rsize);
|
||||
unsigned char checksum[] = {
|
||||
(crc >> 8) & 0xFF, // High
|
||||
(crc ) & 0xFF}; // Low
|
||||
array_convert_bin2hex (checksum, sizeof(checksum), ascii + 1 + 2 * rsize, 4);
|
||||
|
||||
// Trailer
|
||||
ascii[asize - 1] = '}';
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_packet (cressi_leonardo_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
// Send the command to the device.
|
||||
status = dc_serial_write (device->port, command, csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive the answer of the device.
|
||||
status = dc_serial_read (device->port, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to receive the answer.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the header and trailer of the packet.
|
||||
if (answer[0] != '{' || answer[asize - 1] != '}') {
|
||||
ERROR (abstract->context, "Unexpected answer header/trailer byte.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
// Convert the checksum of the packet.
|
||||
unsigned char checksum[2] = {0};
|
||||
array_convert_hex2bin (answer + asize - 5, 4, checksum, sizeof(checksum));
|
||||
|
||||
// Verify the checksum of the packet.
|
||||
unsigned short crc = array_uint16_be (checksum);
|
||||
unsigned short ccrc = checksum_crc_ccitt_uint16 (answer + 1, asize - 6);
|
||||
if (crc != ccrc) {
|
||||
ERROR (abstract->context, "Unexpected answer checksum.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_transfer (cressi_leonardo_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
unsigned int nretries = 0;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
while ((rc = cressi_leonardo_packet (device, command, csize, answer, asize)) != DC_STATUS_SUCCESS) {
|
||||
// Automatically discard a corrupted packet,
|
||||
// and request a new one.
|
||||
if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
|
||||
return rc;
|
||||
|
||||
// Abort if the maximum number of retries is reached.
|
||||
if (nretries++ >= MAXRETRIES)
|
||||
return rc;
|
||||
|
||||
// Discard any garbage bytes.
|
||||
dc_serial_sleep (device->port, 100);
|
||||
dc_serial_purge (device->port, DC_DIRECTION_INPUT);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const char *name)
|
||||
{
|
||||
@ -168,6 +261,47 @@ cressi_leonardo_device_set_fingerprint (dc_device_t *abstract, const unsigned ch
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
// Calculate the packet size.
|
||||
unsigned int len = size - nbytes;
|
||||
if (len > PACKETSIZE)
|
||||
len = PACKETSIZE;
|
||||
|
||||
// Build the raw command.
|
||||
unsigned char raw[] = {
|
||||
(address >> 8) & 0xFF, // High
|
||||
(address ) & 0xFF, // Low
|
||||
(len >> 8) & 0xFF, // High
|
||||
(len ) & 0xFF}; // Low
|
||||
|
||||
// Build the ascii command.
|
||||
unsigned char command[2 * (sizeof (raw) + 3)] = {0};
|
||||
cressi_leonardo_make_ascii (raw, sizeof (raw), command, sizeof (command));
|
||||
|
||||
// Send the command and receive the answer.
|
||||
unsigned char answer[2 * (PACKETSIZE + 3)] = {0};
|
||||
rc = cressi_leonardo_transfer (device, command, sizeof (command), answer, 2 * (len + 3));
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Extract the raw data from the packet.
|
||||
array_convert_hex2bin (answer + 1, 2 * len, data, len);
|
||||
|
||||
nbytes += len;
|
||||
address += len;
|
||||
data += len;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user