Use a more robust command to write flash memory
The S_BLOCK_WRITE (0x30) command sends a stream of bytes to the dive computer. Because the payload has no fixed length and there is no length field included, the hwOS firmware detects the end of the stream by means of a 400ms timeout. The main disadvantage of this approach is that a short hiccup in the communication will be incorrectly detected as the end of the stream. Hence only a part of the data will get written to the flash memory, and the remainder of the data will get interpreted as the next commands. To avoid this problem, the hwOS firmware v3.09 and later supports a new S_BLOCK_WRITE2 (0x31) command, which uses a fixed size payload of 256 bytes. Reported-by: Ralph Lembcke <mail@ralph-lembcke.de>
This commit is contained in:
parent
dff6d0c514
commit
9e92381be4
@ -43,6 +43,7 @@
|
||||
#define SZ_FWINFO 4
|
||||
#define SZ_FIRMWARE 0x01E000 // 120KB
|
||||
#define SZ_FIRMWARE_BLOCK 0x1000 // 4KB
|
||||
#define SZ_FIRMWARE_BLOCK2 0x0100 // 256B
|
||||
#define FIRMWARE_AREA 0x3E0000
|
||||
|
||||
#define RB_LOGBOOK_SIZE_COMPACT 16
|
||||
@ -51,6 +52,7 @@
|
||||
|
||||
#define S_BLOCK_READ 0x20
|
||||
#define S_BLOCK_WRITE 0x30
|
||||
#define S_BLOCK_WRITE2 0x31
|
||||
#define S_ERASE 0x42
|
||||
#define S_READY 0x4C
|
||||
#define READY 0x4D
|
||||
@ -1249,7 +1251,7 @@ hw_ostc3_firmware_block_read (hw_ostc3_device_t *device, unsigned int addr, unsi
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int addr, const unsigned char block[], unsigned int block_size)
|
||||
hw_ostc3_firmware_block_write1 (hw_ostc3_device_t *device, unsigned int addr, const unsigned char block[], unsigned int block_size)
|
||||
{
|
||||
unsigned char buffer[3 + SZ_FIRMWARE_BLOCK];
|
||||
|
||||
@ -1263,6 +1265,44 @@ hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int addr, con
|
||||
return hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE, buffer, 3 + block_size, NULL, 0, TIMEOUT);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc3_firmware_block_write2 (hw_ostc3_device_t *device, unsigned int address, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
|
||||
if ((address % SZ_FIRMWARE_BLOCK2 != 0) ||
|
||||
(size % SZ_FIRMWARE_BLOCK2 != 0)) {
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
unsigned char buffer[3 + SZ_FIRMWARE_BLOCK2];
|
||||
array_uint24_be_set (buffer, address);
|
||||
memcpy (buffer + 3, data + nbytes, SZ_FIRMWARE_BLOCK2);
|
||||
|
||||
status = hw_ostc3_transfer (device, NULL, S_BLOCK_WRITE2, buffer, sizeof(buffer), NULL, 0, NODELAY);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
address += SZ_FIRMWARE_BLOCK2;
|
||||
nbytes += SZ_FIRMWARE_BLOCK2;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int address, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
if (device->firmware >= 0x0309) {
|
||||
return hw_ostc3_firmware_block_write2 (device, address, data, size);
|
||||
} else {
|
||||
return hw_ostc3_firmware_block_write1 (device, address, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc3_firmware_upgrade (dc_device_t *abstract, unsigned int checksum)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user