Browse Source

Fix compatibility with old bootloader versions

Keir Fraser 5 years ago
parent
commit
602eb76a0a
5 changed files with 63 additions and 47 deletions
  1. 1 1
      inc/cdc_acm_protocol.h
  2. 21 7
      scripts/greaseweazle/USB.py
  3. 36 33
      scripts/gw.py
  4. 3 4
      src/floppy.c
  5. 2 2
      src/fw_update.c

+ 1 - 1
inc/cdc_acm_protocol.h

@@ -14,7 +14,7 @@
  * GREASEWEAZLE COMMAND SET
  */
 
-/* CMD_GET_INFO, length=4, 0, nr_bytes. Returns nr_bytes after ACK. */
+/* CMD_GET_INFO, length=3, 0. Returns 32 bytes after ACK. */
 #define CMD_GET_INFO        0
 /* CMD_SEEK, length=3, cyl# */
 #define CMD_SEEK            1

+ 21 - 7
scripts/greaseweazle/USB.py

@@ -6,7 +6,7 @@
 # See the file COPYING for more details, or visit <http://unlicense.org>.
 
 import struct, collections
-
+from . import version
 
 ## Control-Path command set
 class ControlCmd:
@@ -77,15 +77,29 @@ class Unit:
   def __init__(self, ser):
     self.ser = ser
     self.reset()
+    # Copy firmware info to instance variables (see above for definitions).
+    self.send_cmd(struct.pack("3B", Cmd.GetInfo, 3, 0))
+    x = struct.unpack("<4BI24x", self.ser.read(32))
+    (self.major, self.minor, self.max_index,
+     self.max_cmd, self.sample_freq) = x
+    # Check whether firmware is in update mode: limited command set if so.
+    self.update_mode = (self.max_index == 0)
+    if self.update_mode:
+      self.update_jumpered = (self.sample_freq & 1)
+      del self.max_index
+      del self.sample_freq
+      return
+    # We are running main firmware: Check whether an update is needed.
+    # We can use only the GetInfo command if the firmware is out of date.
+    self.update_needed = (version.major != self.major
+                          or version.minor != self.minor)
+    if self.update_needed:
+      return
     # Initialise the delay properties with current firmware values.
     self.send_cmd(struct.pack("4B", Cmd.GetParams, 4, Params.Delays, 10))
     (self._select_delay, self._step_delay,
-     self._seek_settle_delay, self._motor_delay,
-     self._auto_off_delay) = struct.unpack("<5H", self.ser.read(10))
-    # Copy firmware info to instance variables (see above for definitions).
-    self.send_cmd(struct.pack("4B", Cmd.GetInfo, 4, 0, 8))
-    (self.major, self.minor, self.max_index,
-     self.max_cmd, self.sample_freq) = struct.unpack("<4BI", self.ser.read(8))
+    self._seek_settle_delay, self._motor_delay,
+       self._auto_off_delay) = struct.unpack("<5H", self.ser.read(10))
     
 
   ## reset:

+ 36 - 33
scripts/gw.py

@@ -196,6 +196,24 @@ def write_from_scp(args):
 # update_firmware:
 # Updates the Greaseweazle firmware using the specified Update File.
 def update_firmware(args):
+
+  # Check that an update operation was actually requested.
+  if args.action != "update":
+    print("Greaseweazle is in Firmware Update Mode:")
+    print(" The only available action is \"update <update_file>\"")
+    if usb.update_jumpered:
+      print(" Remove the Update Jumper for normal operation")
+    else:
+      print(" Main firmware is erased: You *must* perform an update!")
+    return
+
+  # Check that the firmware is actually in update mode.
+  if not usb.update_mode:
+    print("Greaseweazle is in Normal Mode:")
+    print(" To \"update\" you must install the Update Jumper")
+    return
+
+  # Read and check the update file.
   with open(args.file, "rb") as f:
     dat = f.read()
   (sig, maj, min, pad1, pad2, crc) = struct.unpack(">2s4BH", dat[-8:])
@@ -206,6 +224,8 @@ def update_firmware(args):
   crc16.update(dat)
   if crc16.crcValue != 0:
     print("%s: Bad CRC" % (args.file))
+
+  # Perform the update.
   print("Updating to v%u.%u..." % (maj, min))
   ack = usb.update_firmware(dat)
   if ack != 0:
@@ -248,46 +268,30 @@ def _main(argv):
   global usb
   usb = USB.Unit(serial.Serial(args.device))
 
-  update_mode = (usb.max_index == 0)
-
   print("** %s v%u.%u, Host Tools v%u.%u"
-        % (("Greaseweazle","Bootloader")[update_mode],
+        % (("Greaseweazle","Bootloader")[usb.update_mode],
            usb.major, usb.minor,
            version.major, version.minor))
+
+  if args.action == "update" or usb.update_mode:
+    return actions[args.action](args)
   
-  if (not update_mode
-      and (version.major > usb.major
-           or (version.major == usb.major and version.minor > usb.minor))):
-    print("Firmware is out of date: Require >= v%u.%u"
+  elif usb.update_needed:
+    print("Firmware is out of date: Require v%u.%u"
           % (version.major, version.minor))
     print("Install the Update Jumper and \"update <update_file>\"")
     return
   
-  if update_mode and args.action != "update":
-    print("Greaseweazle is in Firmware Update Mode:")
-    print(" The only available action is \"update <update_file>\"")
-    if usb.sample_freq & 1:
-      print(" Remove the Update Jumper for normal operation")
-    else:
-      print(" Main firmware is erased: You *must* perform an update!")
-    return
-
-  if not update_mode and args.action == "update":
-    print("Greaseweazle is in Normal Mode:")
-    print(" To \"update\" you must install the Update Jumper")
-    return
-
-  usb.step_delay = 5000
-  print("Select Delay: %uus" % usb.select_delay)
-  print("Step Delay: %uus" % usb.step_delay)
-  print("Settle Time: %ums" % usb.seek_settle_delay)
-  print("Motor Delay: %ums" % usb.motor_delay)
-  print("Auto Off: %ums" % usb.auto_off_delay)
+  #usb.step_delay = 5000
+  #print("Select Delay: %uus" % usb.select_delay)
+  #print("Step Delay: %uus" % usb.step_delay)
+  #print("Settle Time: %ums" % usb.seek_settle_delay)
+  #print("Motor Delay: %ums" % usb.motor_delay)
+  #print("Auto Off: %ums" % usb.auto_off_delay)
 
   try:
-    if not update_mode:
-      usb.drive_select(True)
-      usb.drive_motor(True)
+    usb.drive_select(True)
+    usb.drive_motor(True)
     actions[args.action](args)
   except KeyboardInterrupt:
     print()
@@ -295,9 +299,8 @@ def _main(argv):
     usb.ser.close()
     usb.ser.open()
   finally:
-    if not update_mode:
-      usb.drive_motor(False)
-      usb.drive_select(False)
+    usb.drive_motor(False)
+    usb.drive_select(False)
 
 
 def main(argv):

+ 3 - 4
src/floppy.c

@@ -792,14 +792,13 @@ static void process_command(void)
     switch (cmd) {
     case CMD_GET_INFO: {
         uint8_t idx = u_buf[2];
-        uint8_t nr = u_buf[3];
-        if ((len != 4) || (idx != 0) || (nr > 32))
+        if ((len != 3) || (idx != 0))
             goto bad_command;
-        memset(&u_buf[2], 0, nr);
+        memset(&u_buf[2], 0, 32);
         gw_info.fw_major = fw_major;
         gw_info.fw_minor = fw_minor;
         memcpy(&u_buf[2], &gw_info, sizeof(gw_info));
-        resp_sz += nr;
+        resp_sz += 32;
         break;
     }
     case CMD_SEEK: {

+ 2 - 2
src/fw_update.c

@@ -116,8 +116,8 @@ static void process_command(void)
     switch (cmd) {
     case CMD_GET_INFO: {
         uint8_t idx = u_buf[2];
-        if (len != 3) goto bad_command;
-        if (idx != 0) goto bad_command;
+        if ((len != 3) || (idx != 0))
+            goto bad_command;
         memset(&u_buf[2], 0, 32);
         gw_info.fw_major = fw_major;
         gw_info.fw_minor = fw_minor;