def flash_file(self, path, addr, on_progress=None, power_on=False):
        """Flashes the target device.

        The given ``on_progress`` callback will be called as
        ``on_progress(action, progress_string, percentage)`` periodically as the
        data is written to flash.  The action is one of ``Compare``, ``Erase``,
        ``Verify``, ``Flash``.

        Args:
          self (JLink): the ``JLink`` instance
          path (str): absolute path to the source file to flash
          addr (int): start address on flash which to write the data
          on_progress (function): callback to be triggered on flash progress
          power_on (boolean): whether to power the target before flashing

        Returns:
          Integer value greater than or equal to zero.  Has no significance.

        Raises:
          JLinkException: on hardware errors.
        """
        if on_progress is not None:
            # Set the function to be called on flash programming progress.
            func = enums.JLinkFunctions.FLASH_PROGRESS_PROTOTYPE(on_progress)
            self._dll.JLINK_SetFlashProgProgressCallback(func)
        else:
            self._dll.JLINK_SetFlashProgProgressCallback(0)

        # First power on the device.
        if power_on:
            self.power_on()

        try:
            # Stop the target before flashing.  This is required to be in a
            # try-catch as the 'halted()' check may fail with an exception.
            if not self.halted():
                self.halt()
        except errors.JLinkException:
            pass

        # Program the target.
        bytes_flashed = self._dll.JLINK_DownloadFile(path.encode(), addr)
        if bytes_flashed < 0:
            raise errors.JLinkFlashException(bytes_flashed)

        return bytes_flashed