Class CbusBootloaderPane

All Implemented Interfaces:
ImageObserver, MenuContainer, Serializable, EventListener, Accessible, AbstractMRListener, CanListener, CanPanelInterface

public class CbusBootloaderPane extends CanPanel implements CanListener
Bootloader client for uploading CBUS node firmware.

Update March 2022 A new CBUS bootloader protocol supports two new features: - Reading back device ID - Reading back bootloader ID - Positive acknowledgement (or error) for write command - Possibility fro alternative checksum algorithms.

The module may buffer write commands in RAM, sending an immediate ACK and only writing when a FLASH page worth of data is received, which will result in a delayed ACK.

A new command, that will be ignored by the old bootloader, is used to request the bootloader ID. If no reply is received after a suitable timeout then the original protocol will be used. The old protocol is only supported for older PIC18 K8x devices. Modules based on any other devices are expected to support the new protocol.

See Also:
  • Field Details

  • Constructor Details

  • Method Details

    • initComponents

      2nd stage of initialization, invoked after the Constructor is complete.

      This needs to be connected to the initContext() method in implementing classes.

      Specified by:
      initComponents in interface CanPanelInterface
      Overrides:
      initComponents in class CanPanel
      Parameters:
      memo - system connection.
    • init

      public void init()
      Not sure this comment really applies here as init() does not use the tc Don't use initComponent() as memo doesn't yet exist when that gets called. Instead, call init() function from initComponents(memo)
    • getTitle

      public String getTitle()
      Provide a recommended title for an enclosing frame.
      Overrides:
      getTitle in class JmriPanel
      Returns:
      the title; a null value will be treated as "" by the enclosing frame
    • getMenus

      public List<JMenu> getMenus()
      Creates a Menu List. Provide menu items to add to a menu bar.
      Overrides:
      getMenus in class JmriPanel
      Returns:
      a list of menu items to add or an empty list
    • getWriteDelay

      Get the delay to be inserted between bootloader data writes. For AN247, that has no handshaking can be slow or fast and then extended for slow writes to EEPROM and CONFIG. Only a single long timeout is used for CBUS protocol, which has full handshaking
      Returns:
      Delay in ms
    • message

      public void message(CanMessage m)
      Process some outgoing CAN frames

      The CBUS bootloader was originally "fire and forget", with no positive acknowledgement. We had to wait an indeterminate time and assume the write was successful.

      A PIC based node will halt execution for some time ((10+ ms with newer Q series devices) whilst FLASH operations (erase and/or write) complete, during which time I/O will not be serviced. This is probably OK with CAN transport, assuming the ECAN continues to accept frames. With serial (UART) transport, as used by Pi-SPROG, the timing is much more critical as a single missed character will corrupt the node firmware.

      Furthermore, on some platforms, e.g., Raspberry Pi, there can be considerable delays between the call to the traffic controller sendMessage() method and the message being sent by the transmit thread. This may be due to Flash file system operations and could be affected by the speed of the SD card. Once the message leaves the transmit thread, we are at the mercy of the underlying OS, where there can be further delays.

      We could set an overlong timeout, but that would slow down the bootloading process in all cases.

      To improve things somewhat we wait until the message has definitely reached the TC transmit thread, by looking for bootloader data write messages here. Testing indicates this is a marked improvement with no failures observed. This is unnecessary, and not used, for the new protocol which has a positive acknowledge mechanism.

      Specified by:
      message in interface CanListener
      Parameters:
      m - CanMessage
    • reply

      public void reply(CanReply r)
      Processes incoming CAN replies

      The bootloader is only interested in standard parameter responses and extended bootloader responses. Called when an incoming CanFrame is received from the CAN Network.

      Specified by:
      reply in interface CanListener
      Parameters:
      r - the CanReply being received.
    • showDevId

      Show the device ID Manufacturere and device from cbusdefs.h, device ID from the device
      Parameters:
      r - device ID reply
    • showBootId

      Show the bootloader ID Major/Minor version number, checksum algorithm error report capability
      Parameters:
      r - Bootloader ID reply
    • sendBootEnables

      Send the memory region write enable bit mask for CBUS bootloader protocol
    • protocolError

      Protocol Error
    • isProgrammingNeeded

      boolean isProgrammingNeeded(byte[] d)
      Is Programming Needed Check if any data bytes actually need programming
      Parameters:
      d - data bytes to check
      Returns:
      false if all bytes are 0xFF, else true
    • logFrame

      protected void logFrame(CanMessage m)
    • dataIsFiltered

      protected boolean dataIsFiltered(int address)
      Check if data is filtered (e.g., EEPROM selection unticked) Used only for AN247
      Parameters:
      address - of data record
      Returns:
      true if data is filtered and should not be written
    • sendData

      protected void sendData(int timeout)
      Send data to the hardware and keep a running checksum
      Parameters:
      timeout - timeout for write operation
    • writeNextDataAn247

      Write next data for AN247 protocol
    • writeNextDataCbus

      Write next data for CBUS protocol
    • writeNextData

      Write the next data frame for the bootloader
    • requestDevId

      protected void requestDevId()
    • requestBootId

      protected void requestBootId()
    • sendReset

      protected void sendReset()
      Send bootloader reset frame to put the node back into operating mode. There will be no reply to this.
    • updateChecksum

      protected void updateChecksum(byte[] d)
      Add array of bytes to checksum
      Parameters:
      d - the array of bytes
    • requestParam

      public void requestParam(int param)
      Request a single Parameter from a Physical Node

      Will not send the request if there are existing active timers. Starts Parameter timeout

      Parameters:
      param - Parameter Index Number, Index 0 is total parameters
    • hasActiveTimers

      protected boolean hasActiveTimers()
      See if any timers are running, ie waiting for a response from a physical Node.
      Returns:
      true if timers are running else false
    • addToLog

      public void addToLog(String boottext)
      Add to boot loader Log
      Parameters:
      boottext - String console message
    • dispose

      public void dispose()
      disconnect from the CBUS
      Overrides:
      dispose in class JmriPanel