code: async def update_firmware(module, firmware_file_path, loop):
      
      # TODO: Make sure the module isn't in the middle of operation
  
      ports_before_update = await _discover_ports()
      config_file_path = os.path.join(package_root,
                                      'config', 'modules', 'avrdude.conf')
      proc = await asyncio.create_subprocess_exec(
          'avrdude', '-C{}'.format(config_file_path), '-v',
          '-p{}'.format(PART_NO),
          '-c{}'.format(PROGRAMMER_ID),
          '-P{}'.format(module.port),
          '-b{}'.format(BAUDRATE), '-D',
          '-Uflash:w:{}:i'.format(firmware_file_path),
          stdout=asyncio.subprocess.PIPE,
          stderr=asyncio.subprocess.PIPE, loop=loop)
      await proc.wait()
  
      _result = await proc.communicate()
      result = _result[1].decode()
      log.debug(result)
      log.debug("Switching back to non-bootloader port")
      module._port = _port_on_mode_switch(ports_before_update)
  
      return _format_avrdude_response(result)
docs: Run avrdude firmware upload command. Switch back to normal module port
  
      Note: For modules with old bootloader, the kernel could assign the module
      a new port after the update (since the board is automatically reset).
      Scan for such a port change and use the appropriate port