! @brief Double-buffered program by first performing an erase all.

def _chip_erase_program_double_buffer(self, progress_cb=_stub_progress):
        """! @brief Double-buffered program by first performing an erase all."""
        LOG.debug("%i of %i pages have erased data", len(self.page_list) - self.chip_erase_count, len(self.page_list))
        progress_cb(0.0)
        progress = 0

        self.flash.init(self.flash.Operation.ERASE)
        self.flash.erase_all()
        self.flash.uninit()
        
        progress += self.flash.get_flash_info().erase_weight
        progress_cb(float(progress) / float(self.chip_erase_weight))

        # Set up page and buffer info.
        current_buf = 0
        next_buf = 1
        page, i = self._next_unerased_page(0)
        assert page is not None

        # Load first page buffer
        self.flash.load_page_buffer(current_buf, page.addr, page.data)

        self.flash.init(self.flash.Operation.PROGRAM)
        while page is not None:
            # Kick off this page program.
            current_addr = page.addr
            current_weight = page.get_program_weight()
            self.flash.start_program_page_with_buffer(current_buf, current_addr)

            # Get next page and load it.
            page, i = self._next_unerased_page(i)
            if page is not None:
                self.flash.load_page_buffer(next_buf, page.addr, page.data)

            # Wait for the program to complete.
            result = self.flash.wait_for_completion()
            if result != 0:
                raise FlashProgramFailure('program_page(0x%x) error: %i'
                        % (current_addr, result), current_addr, result)

            # Swap buffers.
            current_buf, next_buf = next_buf, current_buf

            # Update progress.
            progress += current_weight
            progress_cb(float(progress) / float(self.chip_erase_weight))
        
        self.flash.uninit()
        progress_cb(1.0)
        return FlashBuilder.FLASH_CHIP_ERASE