Autodetect the bootloader protocol variant.

When updating the firmware while the OSTC is running in normal mode, the
V2 protocol should be used. However, the OSTC can also be rebooted from
the menu or reset using the magnetic switch, and then the V1 protocol
should be used. The only difference with the V2 protocol is the slower
baudrate (19200 vs 115200).

True autodetection of the protocol variant is difficult, because the
bootloader will abort the firmware update when not receiving a 0xC1
byte. But we can still take advantage of the fact that the normal
firmware does ignore any 0xC1 bytes sent at the wrong baudrate, and
probe with the V1 protocol first. If the bootloader is already running,
it will respond immediately and we're done. If the normal firmware is
still running, it won't respond and the probing with the V1 protocol
will fail. If we then switch to the V2 protocol, the firmware update
will continue as before.

The result is a firmware updater which supports both bootloader
protocols without requiring any manual configuration.
This commit is contained in:
Jef Driesen 2013-07-26 22:39:56 +02:00
parent 14286e8236
commit bc89e0a3de

View File

@ -793,7 +793,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device)
static dc_status_t
hw_ostc_firmware_setup (hw_ostc_device_t *device)
hw_ostc_firmware_setup (hw_ostc_device_t *device, unsigned int maxretries)
{
dc_status_t rc = DC_STATUS_SUCCESS;
@ -803,7 +803,7 @@ hw_ostc_firmware_setup (hw_ostc_device_t *device)
break;
// Abort if the maximum number of retries is reached.
if (nretries++ >= MAXRETRIES)
if (nretries++ >= maxretries)
break;
}
@ -893,7 +893,21 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
serial_set_timeout (device->port, 300);
// Setup the bootloader.
rc = hw_ostc_firmware_setup (device);
const unsigned int baudrates[] = {19200, 115200};
for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
// Adjust the baudrate.
if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
ERROR (abstract->context, "Failed to set the terminal attributes.");
free (firmware);
return DC_STATUS_IO;
}
// Try to setup the bootloader.
unsigned int maxretries = (i == 0 ? 1 : MAXRETRIES);
rc = hw_ostc_firmware_setup (device, maxretries);
if (rc == DC_STATUS_SUCCESS)
break;
}
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to setup the bootloader.");
free (firmware);