Example #1
0
static void
program_flash(cyg_addrword_t arg)
{
    diag_printf("PROGRAM FLASH here!\n");
    HAL_UCACHE_SYNC();     // ROM space is marked cacheable which causes problems!
    HAL_UCACHE_DISABLE();  // So, just disable caches.
    identify_FLASH();
    diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end);
    diag_printf("*** Press RESET now to abort!\n");
    cyg_thread_delay(5*100);
    diag_printf("\n");
    diag_printf("... Erase sector\n");
    if (erase_sector(ROM_address)) {
        diag_printf("... Programming FLASH\n");
        while (flash_buffer < flash_buffer_end) {
            if (!write_flash(flash_buffer++, ROM_address++)) break;
        }
    }
    
    // Exit Program Mode
    switch (manuf_code) {
    case ATMEL_MANUF:
        FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
        FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
        FLASH[ATMEL_SEQ_ADD1] = ATMEL_STOP_CMD;
        break;
    case INTEL_MANUF:
        FLASH[0] = INTEL_STOP_CMD;
        break;
    }
    diag_printf("All done!\n");
    cyg_test_exit();
}
void find_erase_sector(unsigned cclk, unsigned dst)
{
 unsigned k;

  __disable_irq();

  for(k = USER_START_SECTOR;k <= MAX_USER_SECTOR; k++)
  {
	if(dst < sector_end_map[k])
	{
	  if(dst == sector_start_map[k])
	  {
		erase_sector(k, k, cclk);
	  }

	  break;
	}
  }

  __enable_irq();
  if(result_table[0] != CMD_SUCCESS)
  {
      serial_writestr("Error: erasing data\n");
  }
}
Example #3
0
/*---------------------------------------------------------------------------*/
int
xmem_erase(long size, unsigned long addr)
{
  unsigned long end = addr + size;

  if(size % XMEM_ERASE_UNIT_SIZE != 0) {
    PRINTF("xmem_erase: bad size\n");
    return -1;
  }

  if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
    PRINTF("xmem_erase: bad offset\n");
    return -1;
  }

  watchdog_stop();

  for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
    erase_sector(addr);
  }

  watchdog_start();

  return size;
}
/*
  erase both sectors
 */
bool AP_FlashStorage::erase_all(void)
{
    write_error = false;

    current_sector = 0;
    write_offset = sizeof(struct sector_header);
    
    if (!erase_sector(0) || !erase_sector(1)) {
        return false;
    }
    
    // mark current sector as in-use
    struct sector_header header;
    header.signature = signature;
    header.state = SECTOR_STATE_IN_USE;
    return flash_write(current_sector, 0, (const uint8_t *)&header, sizeof(header));    
}
void erase_user_flash(void)
{
  prepare_sector(USER_START_SECTOR,MAX_USER_SECTOR,SystemCoreClock/1000);
  erase_sector(USER_START_SECTOR,MAX_USER_SECTOR,SystemCoreClock/1000);
  if(result_table[0] != CMD_SUCCESS)
  {
      serial_writestr("Error: erasing data\n");
  }
}
Example #6
0
void erase_user_flash(void)
{
  prepare_sector(USER_START_SECTOR,MAX_USER_SECTOR,SystemCoreClock/1000);
  erase_sector(USER_START_SECTOR,MAX_USER_SECTOR,SystemCoreClock/1000);
  if(result_table[0] != CMD_SUCCESS)
  {
    while(1); /* No way to recover. Just let OS report a write failure */
  }
}
Example #7
0
/*
 * Erase an address range on the flash chip.  The address range may extend
 * one or more erase sectors.  Return an error is there is a problem erasing.
 */
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 addr,len;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
			flash->spi->dev.bus_id, __func__, "at",
			(u32)instr->addr, instr->len);

	/* sanity checks */
	if (instr->addr + instr->len > flash->mtd.size)
		return -EINVAL;
	if ((instr->addr % mtd->erasesize) != 0
			|| (instr->len % mtd->erasesize) != 0) {
		return -EINVAL;
	}

	addr = instr->addr;
	len = instr->len;

	mutex_lock(&flash->lock);

	/* whole-chip erase? */
	if (len == flash->mtd.size && erase_chip(flash)) {
		instr->state = MTD_ERASE_FAILED;
		mutex_unlock(&flash->lock);
		return -EIO;

	/* REVISIT in some cases we could speed up erasing large regions
	 * by using OPCODE_SE instead of OPCODE_BE_4K.  We may have set up
	 * to use "small sector erase", but that's not always optimal.
	 */

	/* "sector"-at-a-time erase */
	} else {
		while (len) {
			if (erase_sector(flash, addr)) {
				instr->state = MTD_ERASE_FAILED;
				mutex_unlock(&flash->lock);
				return -EIO;
			}

			addr += mtd->erasesize;
			len -= mtd->erasesize;
		}
	}

	mutex_unlock(&flash->lock);

	instr->state = MTD_ERASE_DONE;
	mtd_erase_callback(instr);

	return 0;
}
Example #8
0
int Usb3Camera::erase_eeprom (std::function<void(int)> progress)
{
    int r = -1;
    progress(0);

    for (unsigned int i = 0; i < 5; ++i)
    {
        r = erase_sector(i * SECTOR_SIZE);

        if (r == 0)
            progress(20 * (i+1));
    }
    return r;
}
/*
 * Erase an address range on the flash chip.  The address range may extend
 * one or more erase sectors.  Return an error is there is a problem erasing.
 */
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 addr,len;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
			flash->spi->dev.bus_id, __func__, "at",
			(u32)instr->addr, instr->len);

	/* sanity checks */
	if (instr->addr + instr->len > flash->mtd.size)
		return -EINVAL;
	if ((instr->addr % mtd->erasesize) != 0
			|| (instr->len % mtd->erasesize) != 0) {
		return -EINVAL;
	}

	addr = instr->addr;
	len = instr->len;

	mutex_lock(&flash->lock);

	/* REVISIT in some cases we could speed up erasing large regions
	 * by using OPCODE_SE instead of OPCODE_BE_4K
	 */

	/* now erase those sectors */
	while (len) {
		if (erase_sector(flash, addr)) {
			instr->state = MTD_ERASE_FAILED;
			mutex_unlock(&flash->lock);
			return -EIO;
		}

		addr += mtd->erasesize;
		len -= mtd->erasesize;
	}

	mutex_unlock(&flash->lock);

	instr->state = MTD_ERASE_DONE;
	mtd_erase_callback(instr);

	return 0;
}
// switch full sector - should only be called when safe to have CPU
// offline for considerable periods as an erase will be needed
bool AP_FlashStorage::switch_full_sector(void)
{
    debug("running switch_full_sector()\n");
    
    // clear any write error
    write_error = false;
    reserved_space = 0;
    
    if (!write_all()) {
        return false;
    }

    if (!erase_sector(current_sector ^ 1)) {
        return false;
    }

    return switch_sectors();
}
Example #11
0
int parameter_flashfs_erase(void)
{
	int rv = -ENXIO;

	if (sector_map) {
		rv = 0;

		for (int s = 0; sector_map[s].address; s++) {
			int sz = erase_sector(&sector_map[s], (flash_entry_header_t *)sector_map[s].address);

			if (sz != 0) {
				return sz;
			}

			rv += sector_map[s].size;
		}
	}

	return rv;
}
Example #12
0
void find_erase_prepare_sector(unsigned cclk, unsigned dst)
{
  unsigned i;

  __disable_irq();
  for(i = USER_START_SECTOR; i <= MAX_USER_SECTOR; i++)
  {
    if(dst < sector_end_map[i])
    {
      if(dst == sector_start_map[i])
      {
        prepare_sector(i, i, cclk);
        erase_sector(i, i, cclk);
      }
      prepare_sector(i , i, cclk);
      break;
    }
  }
  __enable_irq();
}
Example #13
0
File: iap.c Project: matzipan/hapr
// Check if a sector is blank and if not, erase it
// wipe_sector isn't working for unknown reasons
// Doesn't return an error, just seems to freeze the MBED
// uint16_t sector => sector id to wipe
unsigned wipe_sector(uint16_t sector) {
#if DEBUG==1
    tty_writeln("Wiping sector");
#endif
    blank_check_sector(sector, sector);
    if(output[0] == SECTOR_NOT_BLANK) {
        prepare_sector_write(sector, sector);
        if (output[0] !=0) {
            write_error(output[0]);
            return output[0];
        }
        erase_sector(sector, sector);
        if (output[0] !=0) {
            write_error(output[0]);
            return output[0];
        }
    }
#if DEBUG==1
    tty_writeln("Sector wipe");
#endif
    return 0;
}
/*
 * Erase an address range on the flash chip.  The address range may extend
 * one or more erase sectors.  Return an error is there is a problem erasing.
 */
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 addr,len;
	uint64_t tmpdiv;
	int rem, rem1;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
			flash->spi->dev.bus_id, __FUNCTION__, "at",
			(u32)instr->addr, instr->len);

	/* sanity checks */
	if (instr->addr + instr->len > device_size(&(flash->mtd)))
		return -EINVAL;
	tmpdiv = (uint64_t) instr->addr;
 	rem = do_div(tmpdiv, mtd->erasesize);
	tmpdiv = (uint64_t) instr->len;
	rem1 = do_div(tmpdiv, mtd->erasesize);
	if (rem != 0 || rem1 != 0) {
		return -EINVAL;
	}

	addr = instr->addr;
	len = instr->len;

	mutex_lock(&flash->lock);

	/* REVISIT in some cases we could speed up erasing large regions
	 * by using OPCODE_SE instead of OPCODE_BE_4K
	 */

	/* now erase those sectors */
	while (len) {
#ifdef CONFIG_MIPS_BRCM97XXX
		/* BSPI remaps each 4MB segment */
		if (erase_sector(flash, (addr + 0x400000) & 0xffffff)) {
#else
		if (erase_sector(flash, addr)) {
#endif
			instr->state = MTD_ERASE_FAILED;
			mutex_unlock(&flash->lock);
			return -EIO;
		}

		addr += mtd->erasesize;
		len -= mtd->erasesize;
	}

	mutex_unlock(&flash->lock);

	instr->state = MTD_ERASE_DONE;
	mtd_erase_callback(instr);

	return 0;
}

/*
 * Read an address range from the flash chip.  The address range
 * may be any size provided it is within the physical boundaries.
 */
static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
	size_t *retlen, u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	struct spi_transfer t[2];
	struct spi_message m;
	size_t total_len = len;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __FUNCTION__, "from",
			(u32)from, len);

	/* sanity checks */
	if (!len)
		return 0;

	if (from + len > device_size(&(flash->mtd)))
		return -EINVAL;

	if (retlen)
		*retlen = 0;

	total_len = len;
	while(total_len) {
		len = total_len;

#if 0 //defined(BRCM_SPI_SS_WAR)
	/*
	 * For testing purposes only - read 12 bytes at a time:
	 *
	 * 3548a0 MSPI has a 12-byte limit (PR42350).
	 * MSPI emulated via BSPI has no such limit.
	 * In production BSPI is always used because it is much faster.
	 */
		if(len > 12)
			len = 12;
#endif
#ifdef CONFIG_MIPS_BRCM97XXX
		/* don't cross a 4MB boundary due to remapping */
		len = min(len, (0x400000 - ((u32)from & 0x3fffff)));
#endif
		spi_message_init(&m);
		memset(t, 0, (sizeof t));

		t[0].tx_buf = flash->command;
		t[0].len = sizeof(flash->command);
		spi_message_add_tail(&t[0], &m);

		t[1].rx_buf = buf;
		t[1].len = len;
		spi_message_add_tail(&t[1], &m);

		/* Byte count starts at zero. */

		mutex_lock(&flash->lock);

		/* Wait till previous write/erase is done. */
		if (wait_till_ready(flash)) {
			/* REVISIT status return?? */
			mutex_unlock(&flash->lock);
			return 1;
		}

		/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
		 * clocks; and at this writing, every chip this driver handles
		 * supports that opcode.
		 */

		/* Set up the write data buffer. */
		flash->command[0] = OPCODE_READ;
#ifdef CONFIG_MIPS_BRCM97XXX
		/* BSPI remaps each 4MB segment */
		flash->command[1] = ((from >> 16) + 0x40) & 0xff;
#else
		flash->command[1] = from >> 16;
#endif
		flash->command[2] = from >> 8;
		flash->command[3] = from;

		spi_sync(flash->spi, &m);

		*retlen += m.actual_length - sizeof(flash->command);

		mutex_unlock(&flash->lock);

		from += len;
		buf += len;
		total_len -= len;
	}

	return 0;
}

/*
 * Write an address range to the flash chip.  Data must be written in
 * FLASH_PAGESIZE chunks.  The address range may be any size provided
 * it is within the physical boundaries.
 */
static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
	size_t *retlen, const u_char *buf)
{
	struct m25p *flash = mtd_to_m25p(mtd);
	u32 page_offset, page_size;
	struct spi_transfer t[2];
	struct spi_message m;

	DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
			flash->spi->dev.bus_id, __FUNCTION__, "to",
			(u32)to, len);

	if (retlen)
		*retlen = 0;

	/* sanity checks */
	if (!len)
		return(0);

	if (to + len > device_size(&(flash->mtd)))
		return -EINVAL;
#ifdef BRCM_SPI_SS_WAR
	if(len > 12)
		return -EIO;
#endif

	spi_message_init(&m);
	memset(t, 0, (sizeof t));

	t[0].tx_buf = flash->command;
	t[0].len = sizeof(flash->command);
	spi_message_add_tail(&t[0], &m);

	t[1].tx_buf = buf;
	spi_message_add_tail(&t[1], &m);

	mutex_lock(&flash->lock);

	/* Wait until finished previous write command. */
	if (wait_till_ready(flash))
		return 1;

	write_enable(flash);

	/* Set up the opcode in the write buffer. */
	flash->command[0] = OPCODE_PP;
#ifdef CONFIG_MIPS_BRCM97XXX
	/* BSPI remaps each 4MB segment */
	flash->command[1] = ((to >> 16) + 0x40) & 0xff;
#else
	flash->command[1] = to >> 16;
#endif
	flash->command[2] = to >> 8;
	flash->command[3] = to;

	/* what page do we start with? */
	page_offset = to % FLASH_PAGESIZE;

	/* do all the bytes fit onto one page? */
	if (page_offset + len <= FLASH_PAGESIZE) {
		t[1].len = len;

		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - sizeof(flash->command);
	} else {
		u32 i;

		/* the size of data remaining on the first page */
		page_size = FLASH_PAGESIZE - page_offset;

		t[1].len = page_size;
		spi_sync(flash->spi, &m);

		*retlen = m.actual_length - sizeof(flash->command);

		/* write everything in PAGESIZE chunks */
		for (i = page_size; i < len; i += page_size) {
			page_size = len - i;
			if (page_size > FLASH_PAGESIZE)
				page_size = FLASH_PAGESIZE;

			/* write the next page to flash */
#ifdef CONFIG_MIPS_BRCM97XXX
			/* BSPI remaps each 4MB segment */
			flash->command[1] = (((to + i) >> 16) + 0x40) & 0xff;
#else
			flash->command[1] = (to + i) >> 16;
#endif
			flash->command[2] = (to + i) >> 8;
			flash->command[3] = (to + i);

			t[1].tx_buf = buf + i;
			t[1].len = page_size;

			wait_till_ready(flash);

			write_enable(flash);

			spi_sync(flash->spi, &m);

			if (retlen)
				*retlen += m.actual_length
					- sizeof(flash->command);
		}
	}

	mutex_unlock(&flash->lock);

	return 0;
}


/****************************************************************************/

/*
 * SPI device driver setup and teardown
 */

struct flash_info {
	char		*name;

	/* JEDEC id zero means "no ID" (most older chips); otherwise it has
	 * a high byte of zero plus three data bytes: the manufacturer id,
	 * then a two byte device id.
	 */
	u32		jedec_id;

	/* The size listed here is what works with OPCODE_SE, which isn't
	 * necessarily called a "sector" by the vendor.
	 */
	unsigned	sector_size;
	u16		n_sectors;

	u16		flags;
#define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
};


/* NOTE: double check command sets and memory organization when you add
 * more flash chips.  This current list focusses on newer chips, which
 * have been converging on command sets which including JEDEC ID.
 */
static struct flash_info __devinitdata m25p_data [] = {

	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
	{ "at25fs010",  0x1f6601, 32 * 1024, 4, SECT_4K, },
	{ "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },

	{ "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },

	{ "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
	{ "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
	{ "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
	{ "at26df321",  0x1f4701, 64 * 1024, 64, SECT_4K, },

	/* Spansion -- single (large) sector size only, at least
	 * for the chips listed here (without boot sectors).
	 */
	{ "s25sl004a", 0x010212, 64 * 1024, 8, },
	{ "s25sl008a", 0x010213, 64 * 1024, 16, },
	{ "s25sl016a", 0x010214, 64 * 1024, 32, },
	{ "s25sl032a", 0x010215, 64 * 1024, 64, },
	{ "s25sl064a", 0x010216, 64 * 1024, 128, },
#ifdef CONFIG_MIPS_BRCM97XXX
	{ "s25fl128p", 0x012018, 64 * 1024, 256, },
#endif

	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
	{ "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
	{ "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
	{ "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
	{ "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },

	/* ST Microelectronics -- newer production may have feature updates */
	{ "m25p05",  0x202010,  32 * 1024, 2, },
	{ "m25p10",  0x202011,  32 * 1024, 4, },
	{ "m25p20",  0x202012,  64 * 1024, 4, },
	{ "m25p40",  0x202013,  64 * 1024, 8, },
#ifndef CONFIG_MIPS_BRCM97XXX
	/* ID 0 is detected when there's nothing on the bus */
	{ "m25p80",         0,  64 * 1024, 16, },
#endif
	{ "m25p16",  0x202015,  64 * 1024, 32, },
	{ "m25p32",  0x202016,  64 * 1024, 64, },
	{ "m25p64",  0x202017,  64 * 1024, 128, },
	{ "m25p128", 0x202018, 256 * 1024, 64, },

	{ "m45pe80", 0x204014,  64 * 1024, 16, },
	{ "m45pe16", 0x204015,  64 * 1024, 32, },

	{ "m25pe80", 0x208014,  64 * 1024, 16, },
	{ "m25pe16", 0x208015,  64 * 1024, 32, SECT_4K, },

	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
	{ "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
	{ "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
	{ "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
	{ "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
	{ "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
	{ "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
	{ "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
};

static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
{
	int			tmp;
	u8			code = OPCODE_RDID;
	u8			id[3];
	u32			jedec;
	struct flash_info	*info;

	/* JEDEC also defines an optional "extended device information"
	 * string for after vendor-specific data, after the three bytes
	 * we use here.  Supporting some chips might require using it.
	 */
	tmp = spi_write_then_read(spi, &code, 1, id, 3);
	if (tmp < 0) {
		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
			spi->dev.bus_id, tmp);
		return NULL;
	}
	jedec = id[0];
	jedec = jedec << 8;
	jedec |= id[1];
	jedec = jedec << 8;
	jedec |= id[2];

	for (tmp = 0, info = m25p_data;
			tmp < ARRAY_SIZE(m25p_data);
			tmp++, info++) {
		if (info->jedec_id == jedec)
			return info;
	}
	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
	return NULL;
}
// initialise storage
bool AP_FlashStorage::init(void)
{
    debug("running init()\n");
    
    // start with empty memory buffer
    memset(mem_buffer, 0, storage_size);

    // find state of sectors
    struct sector_header header[2];

    // read headers and possibly initialise if bad signature
    for (uint8_t i=0; i<2; i++) {
        if (!flash_read(i, 0, (uint8_t *)&header[i], sizeof(header[i]))) {
            return false;
        }
        bool bad_header = (header[i].signature != signature);
        enum SectorState state = (enum SectorState)header[i].state;
        if (state != SECTOR_STATE_AVAILABLE &&
            state != SECTOR_STATE_IN_USE &&
            state != SECTOR_STATE_FULL) {
            bad_header = true;
        }

        // initialise if bad header
        if (bad_header) {
            return erase_all();
        }
    }

    // work out the first sector to read from using sector states
    enum SectorState states[2] {(enum SectorState)header[0].state, (enum SectorState)header[1].state};
    uint8_t first_sector;

    if (states[0] == states[1]) {
        if (states[0] != SECTOR_STATE_AVAILABLE) {
            return erase_all();
        }
        first_sector = 0;
    } else if (states[0] == SECTOR_STATE_FULL) {
        first_sector = 0;
    } else if (states[1] == SECTOR_STATE_FULL) {
        first_sector = 1;
    } else if (states[0] == SECTOR_STATE_IN_USE) {
        first_sector = 0;
    } else if (states[1] == SECTOR_STATE_IN_USE) {
        first_sector = 1;
    } else {
        // doesn't matter which is first
        first_sector = 0;
    }

    // load data from any current sectors
    for (uint8_t i=0; i<2; i++) {
        uint8_t sector = (first_sector + i) & 1;
        if (states[sector] == SECTOR_STATE_IN_USE ||
            states[sector] == SECTOR_STATE_FULL) {
            if (!load_sector(sector)) {
                return erase_all();
            }
        }
    }

    // clear any write error
    write_error = false;
    reserved_space = 0;
    
    // if the first sector is full then write out all data so we can erase it
    if (states[first_sector] == SECTOR_STATE_FULL) {
        current_sector = first_sector ^ 1;
        if (!write_all()) {
            return erase_all();
        }
    }

    // erase any sectors marked full
    for (uint8_t i=0; i<2; i++) {
        if (states[i] == SECTOR_STATE_FULL) {
            if (!erase_sector(i)) {
                return false;
            }
        }
    }

    reserved_space = 0;
    
    // ready to use
    return true;
}
Example #16
0
bool	FLASHDRVR::write(const unsigned addr, const unsigned len,
		const unsigned *data, const bool verify) {
	// Work through this one sector at a time.
	// If this buffer is equal to the sector value(s), go on
	// If not, erase the sector

	// m_fpga->writeio(R_QSPI_CREG, 2);
	// m_fpga->readio(R_VERSION);	// Read something innocuous
	// m_fpga->writeio(R_QSPI_SREG, 0);
	// m_fpga->readio(R_VERSION);	// Read something innocuous

	for(unsigned s=SECTOROF(addr); s<SECTOROF(addr+len+SECTORSZ-1); s+=SECTORSZ) {
		// printf("IN LOOP, s=%08x\n", s);
		// Do we need to erase?
		bool	need_erase = false;
		unsigned newv = 0; // (s<addr)?addr:s;
		{
			DEVBUS::BUSW	*sbuf = new DEVBUS::BUSW[SECTORSZ];
			const DEVBUS::BUSW *dp;
			unsigned	base,ln;
			base = (addr>s)?addr:s;
			ln=((addr+len>s+SECTORSZ)?(s+SECTORSZ):(addr+len))-base;
			m_fpga->readi(base, ln, sbuf);

			dp = &data[base-addr];
			for(unsigned i=0; i<ln; i++) {
				if ((sbuf[i]&dp[i]) != dp[i]) {
					printf("\nNEED-ERASE @0x%08x ... %08x != %08x (Goal)\n", 
						i+base-addr, sbuf[i], dp[i]);
					need_erase = true;
					newv = i+base;
					break;
				} else if ((sbuf[i] != dp[i])&&(newv == 0)) {
					// if (newv == 0)
						// printf("MEM[%08x] = %08x (!= %08x (Goal))\n",
							// i+base, sbuf[i], dp[i]);
					newv = i+base;
				}
			}
		}

		if (newv == 0)
			continue; // This sector already matches

		// Just erase anyway
		if ((need_erase)&&(!erase_sector(s, verify))) {
			printf("SECTOR ERASE FAILED!\n");
			return false;
		} else if (!need_erase)
			printf("NO ERASE NEEDED\n");
		else {
			printf("ERASING SECTOR %08x\n", s);
			newv = (s<addr) ? addr : s;
		}
		for(unsigned p=newv; (p<s+SECTORSZ)&&(p<addr+len); p=PAGEOF(p+PGLEN))
			if (!write_page(p, (p+PGLEN<addr+len)
				?((PAGEOF(p)!=PAGEOF(p+PGLEN-1))?(PAGEOF(p+PGLEN-1)-p):PGLEN)
				:(addr+len-p), &data[p-addr]), verify) {
				printf("WRITE-PAGE FAILED!\n");
				return false;
		}
	}

	m_fpga->writeio(R_QSPI_EREG, 0); // Re-enable write protection

	return true;
}
Example #17
0
int
parameter_flashfs_write(flash_file_token_t token, uint8_t *buffer, size_t buf_size)
{
	int rv = -ENXIO;

	if (sector_map) {

		rv = 0;

		/* Calculate the total space needed */

		size_t total_size = buf_size + sizeof(flash_entry_header_t);
		size_t alignment = sizeof(h_magic_t) - 1;
		size_t  size_adjust = ((total_size + alignment) & ~alignment) - total_size;
		total_size += size_adjust;

		/* Is this and existing entry */

		flash_entry_header_t *pf = find_entry(token);

		if (!pf) {

			/* No Entry exists for this token so find a place for it */

			pf = find_free(total_size);

			/* No Space */

			if (pf == 0) {
				return -ENOSPC;
			}

		} else {

			/* Do we have space after the entry in the sector for the update */

			sector_descriptor_t *current_sector = check_free_space_in_sector(pf,
							      total_size);


			if (current_sector == 0) {

				/* Mark the last entry erased */

				/* todo:consider a 2 stage erase or write before erase and do a fs check
				 * at start up
				 */

				rv = erase_entry(pf);

				if (rv < 0) {
					return rv;
				}

				/* We had space and marked the last entry erased so use the  Next Free */

				pf = next_entry(pf);

			} else {

				/*
				 * We did not have space in the current sector so select the next sector
				 */

				current_sector = get_next_sector_descriptor(current_sector);

				/* Will the data fit */

				if (current_sector->size < total_size) {
					return -ENOSPC;
				}

				/* Mark the last entry erased */

				/* todo:consider a 2 stage erase or write before erase and do a fs check
				 * at start up
				 */

				rv = erase_entry(pf);

				if (rv < 0) {
					return rv;
				}

				pf = (flash_entry_header_t *) current_sector->address;
			}

			if (!blank_check(pf, total_size)) {
				rv = erase_sector(current_sector, pf);
			}
		}

		flash_entry_header_t *pn = (flash_entry_header_t *)(buffer - sizeof(flash_entry_header_t));
		pn->magic = MagicSig;
		pn->file_token.t = token.t;
		pn->flag = ValidEntry + size_adjust;
		pn->size = total_size;

		for (size_t a = 0; a < size_adjust; a++) {
			buffer[buf_size + a] = (uint8_t)BlankSig;
		}

		pn->crc = crc32(entry_crc_start(pn), entry_crc_length(pn));
		rv = up_progmem_write((size_t) pf, pn, pn->size);
		int system_bytes = (sizeof(flash_entry_header_t) + size_adjust);

		if (rv >= system_bytes) {
			rv -= system_bytes;
		}
	}

	return rv;
}
Example #18
0
File: main.cpp Project: osrf/wandrr
void burn(libusb_device_handle *h, const char *filename)
{
  printf("burning %s\n", filename);
  FILE *f = fopen(filename, "rb");
  if (!f)
  {
    printf("couldn't open %s\n", filename);
    exit(1);
  }
  uint32_t write_addr = 0; // this image will start to be burned at zero
  uint8_t tx_msg[64] = {0};
  tx_msg[0] =  1; // command: flash
  tx_msg[1] =  1; // subcmd: write
  tx_msg[2] = 32; // write length
  int num_transferred = 0;
  while (!feof(f))
  {
    if ((write_addr & 0xffff) == 0)
    {
      // we're on a new sector boundary. erase it so we can program it.
      printf("erasing sector starting at 0x%08x\n", (unsigned)write_addr);
      if (!erase_sector(h, write_addr))
        break;
    }
    if (write_addr % 0x1000 == 0)
      printf("writing to 0x%08x\r\n", write_addr);
    //if (write_addr >= 0x10000)
    //  break;
    memcpy(&tx_msg[4], &write_addr, sizeof(write_addr));
    memset(&tx_msg[8], 0, 32);
    size_t nread = fread(&tx_msg[8], 1, 32, f);
    if (nread != 32)
      printf("read %d bytes. last page?\n", (int)nread);
    if (nread == 0)
      break;
    int tx_rc = libusb_bulk_transfer(h, 2, tx_msg, sizeof(tx_msg),
                                     &num_transferred, 100);
    if (tx_rc != 0)
    {
      printf("tx_rc = %d\n", tx_rc);
      break;
    }
    uint8_t rx_msg[64] = {0};
    int rx_rc = libusb_bulk_transfer(h, 0x81, 
                                     rx_msg, sizeof(rx_msg),
                                     &num_transferred, 100);
    if (rx_rc != 0)
    {
      printf("rx err code: %d\n", rx_rc);
      printf("errno: %d = %s\n", errno, strerror(errno));
      break;
    }
    uint32_t response_write_addr = 0;
    memcpy(&response_write_addr, &rx_msg[4], sizeof(uint32_t));
    if (write_addr != response_write_addr)
    {
      printf("write addr mismatch: 0x%08x != 0x%08x\n",
             response_write_addr, write_addr);
      break;
    }
    write_addr += 32;
  }
}
Example #19
0
//*----------------------------------------------------------------------------
//* Function Name       : flash_at49_erase_write_block
//* Object              : check if sector is erased if not erase erase and write
//* Input Parameters    : <buffer> data block addressFlash
//*                       <size> sector size in byte
//* Output Parameters   : if data sector erase TRUE or FALSE
//*----------------------------------------------------------------------------
int flash_at49_erase_write_block ( u_char *buffer,int size)
//* Begin

{
    unsigned short  data ;
    unsigned int    count;
    int         sector_found ;
    int         change_sector ;

    //* For each word read from the file
    for  ( count =0 ; count < size ; count +=2 )
    {
    //data = buffer[count];
         data =  (unsigned short) buffer[count]| (unsigned short)buffer[count+1]  << 8 ;
        //* Clear sector found flag
        sector_found = FALSE ;
        //* Clear Sector change flag
        change_sector = FALSE ;
        //* While sector not found
        while ( sector_found == FALSE )
        {
            //* If program address lower than current sector address + its size
            if (( addr_prg_sector + (flash->flash_org[block].sector_size/2) )
                > addr_load )
            {
                //* Flag sector found
                sector_found = TRUE ;
            }
            //* Else
            else
            {
                //* Flag sector change
                change_sector = TRUE ;
                //* Add current sector size to program address
                addr_prg_sector += (flash->flash_org[block].sector_size/2) ;

                //* Increment the sector number
                nb_sector++ ;
                //* If last sector in block tested
                if ( nb_sector >= flash->flash_org[block].sector_number )
                {
                    //* Re-initialize sector number in block
                    nb_sector = 0 ;
                    //* Increment block number
                    block ++ ;
                    //* If last block tested
                    if ( block >= flash->flash_block_nb )
                    {
                        //*  Error Address not found in the Flash Address Field Return False
                        return ( FALSE ) ;
                    }
                    //* Endif
                }
                //* Endif
            }
            //* EndIf
        }
        //* EndWhile

        //* Unflag Erasing
        erase = FALSE ;
        //* If new sector or first sector
        if (( change_sector == TRUE ) || ( first == TRUE ))
        {
            //* If not first sector
            if ( first == FALSE )
            {
                //* Flag Erasing
                erase = TRUE ;
            }
            //* Else, if first sector
            else
            {
                //* Flag to erase the sector
                erase = TRUE ;

            }
            //* Endif
        }
        //* Endif

        //* If Erasing flagged
        if ( erase == TRUE )
        {
            //* Erase, if Timeout
            if ( erase_sector ( addr_base,
                                addr_prg_sector,
                                flash->flash_org[block].sector_size) != TRUE )
            {
                //* Return False
                return ( FALSE ) ;
            }
            //* Endif
        }
        //* Endif


        //* Write the value read in Flash, if error
        if ( flash_at49_write_flash ( addr_base,addr_load, data )!= TRUE )
        {
            //* Return False
            return ( FALSE ) ;
        }
        //* Endif

        //* Increment load address
        addr_load ++ ;

        //* Remove first address to program flag
        first = FALSE ;
    }
    //* EndWhile

    //* Return True
    return ( TRUE ) ;
}