code: async def update_firmware(port: str,
                            firmware_file_path: str,
                            loop: Optional[asyncio.AbstractEventLoop])\
                            -> Tuple[str, Tuple[bool, str]]:
      
  
      ports_before_update = await _discover_ports()
      config_file_path = os.path.join(package_root,
                                      'config', 'modules', 'avrdude.conf')
      kwargs: Dict[str, Any] = {
          'stdout': asyncio.subprocess.PIPE,
          'stderr': asyncio.subprocess.PIPE
      }
      if loop:
          kwargs['loop'] = loop
      proc = await asyncio.create_subprocess_exec(
          'avrdude', '-C{}'.format(config_file_path), '-v',
          '-p{}'.format(PART_NO),
          '-c{}'.format(PROGRAMMER_ID),
          '-P{}'.format(port),
          '-b{}'.format(BAUDRATE), '-D',
          '-Uflash:w:{}:i'.format(firmware_file_path),
          **kwargs)
      await proc.wait()
  
      _result = await proc.communicate()
      result = _result[1].decode()
      avrdude_res = _format_avrdude_response(result)
      if avrdude_res[0]:
          log.debug(result)
      else:
          log.error("Failed to update module firmware for {}: {}"
                    .format(port, avrdude_res[1]))
      new_port = await _port_on_mode_switch(ports_before_update)
      log.info("New port: {}".format(new_port))
      return new_port, avrdude_res
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.
  
      Returns a tuple of the new port to communicate on (or None if it was not
      found) and a tuple of success and message from avrdude.