Esempio n. 1
0
/**
 * \brief Translates address/size access of a nand_flash_model to block, page
 * and offset values.
 *
 * \param model  nand_flash_model instance.
 * \param address  Access address.
 * \param size  Access size in bytes.
 * \param block  Stores the first accessed block number.
 * \param page  Stores the first accessed page number inside the first block.
 * \param offset  Stores the byte offset inside the first accessed page.
 *
 * \return 0 if the access is correct; otherwise returns
 * NAND_COMMON_ERROR_OUTOFBOUNDS.
 *
 * \note The values are stored in the provided variables if their pointer is
 * not 0.
 */
uint32_t nand_flash_model_translate_access(const struct nand_flash_model
		*model, uint32_t address, uint32_t size, uint16_t *block,
		uint16_t *page, uint16_t *offset)
{
	/* Check that access is not too big */
	if ((address + size) > nand_flash_model_get_device_size_in_bytes(model)) {
		return NAND_COMMON_ERROR_OUTOFBOUNDS;
	}

	/* Get NAND info */
	uint32_t block_size = nand_flash_model_get_block_size_in_bytes(model);
	uint32_t page_size = nand_flash_model_get_page_data_size(model);

	/* Translate address */
	uint16_t temp_block = address / block_size;
	address -= (temp_block * block_size);
	uint16_t temp_page = address / page_size;
	address -= (temp_page * page_size);
	uint16_t temp_Offset = address;

	/* Save results */
	if (block) {
		*block = temp_block;
	}
	if (page) {
		*page = temp_page;
	}
	if (offset) {
		*offset = temp_Offset;
	}

	return 0;
}
Esempio n. 2
0
/**
 * \brief This function transfers the USB MSC data to the memory
 *
 * \param addr Sector address to start write
 * \param nb_sector Number of sectors to transfer (sector=512 bytes)
 *
 * \return Ctrl_status
 */
Ctrl_status nand_flash_usb_write_10(uint32_t addr, uint16_t nb_sector)
{
	uint8_t nb_sector_trans;
	uint16_t page_data_size
		= nand_flash_model_get_page_data_size(MODEL(&nf_translation));

	if (nand_flash_status == NAND_FLASH_READY) {
		while (nb_sector) {
			nb_sector_trans
				= min(nb_sector,
					(page_data_size / SECTOR_SIZE));
			udi_msc_trans_block(false,
					(uint8_t *)nand_flash_usb_buffer,
					(nb_sector_trans * SECTOR_SIZE), NULL);
			if (nand_flash_write((addr * SECTOR_SIZE),
					nand_flash_usb_buffer,
					(nb_sector_trans * SECTOR_SIZE))) {
				return CTRL_FAIL;
			}

			nb_sector -= nb_sector_trans;
			addr += nb_sector_trans;
		}
		return CTRL_GOOD;
	}

	return CTRL_BUSY;
}
Esempio n. 3
0
/**
 * \brief  Read the data and/or spare of a page of a NAND Flash chip, and verify
 * that the data is valid using the ECC information contained in the spare. If
 * one buffer pointer is 0, the corresponding area is not saved.
 *
 * \param ecc  Pointer to an nand_flash_ecc instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer.
 * \param spare  Spare area buffer.
 *
 * \return 0 if the data has been read and is valid; otherwise returns either
 * NAND_COMMON_ERROR_CORRUPTEDDATA or ...
 */
uint32_t nand_flash_ecc_read_page(const struct nand_flash_ecc *ecc,
		uint16_t block, uint16_t page, uint8_t *data, uint8_t *spare)
{
	uint32_t error;

	uint8_t hamming_code[NAND_COMMON_MAX_SPARE_ECC_BYTES];
	uint8_t spare_buffer[NAND_COMMON_MAX_PAGE_SPARE_SIZE];

	uint16_t page_data_size
		= nand_flash_model_get_page_data_size(MODEL(ecc));

	/* if no buffer provided, use a temp one */
	if (!spare) {
		spare = spare_buffer;
	}

	memset(spare, 0xFF, NAND_COMMON_MAX_PAGE_SPARE_SIZE);

	/* Start by reading the spare and the data */
	nand_flash_raw_read_page(RAW(ecc), block, page, data, spare);

	/* Retrieve ECC information from page and verify the data */
	nand_flash_spare_scheme_read_ecc(nand_flash_model_get_scheme(MODEL(ecc)),
			spare, hamming_code);
	error = hamming_verify_256x(data, page_data_size, hamming_code);
	if (error && (error != HAMMING_ERROR_SINGLE_BIT)) {
		return NAND_COMMON_ERROR_CORRUPTEDDATA;
	}

	return 0;
}
/**
 * \brief Translate the given column and row address into first and other (1-4)
 * address cycles. The resulting values are stored in the provided variables
 * if they are not null.
 *
 * \param raw  Pointer to a nand_flash_raw instance.
 * \param column_address  Column address to translate.
 * \param row_address  Row address to translate.
 * \param p_address_cycle0  First address cycle.
 * \param p_address_cycle1234 four address cycles.
 * \param five_address Flag for five address cycles.
 */
static void nfc_translate_address(const struct nand_flash_raw *raw,
		uint32_t column_address, uint32_t row_address,
		uint32_t *p_address_cycle0, uint32_t *p_address_cycle1234,
		uint32_t five_address)
{
	uint16_t page_data_size = nand_flash_model_get_page_data_size(MODEL(raw));
	uint32_t num_page =	nand_flash_model_get_device_size_in_pages(MODEL(raw));
	uint32_t address_cycles = 0;
	uint32_t address_cycle0 = 0;
	uint32_t address_cycle1234 = 0;

	/* Check the data bus width of the NAND Flash */
	if (nand_flash_model_get_data_bus_width(MODEL(raw)) == 16) {
		/* Div 2 is because we address in word and not in byte */
		column_address >>= 1;
	}
Esempio n. 5
0
/**
 * \brief  Write the data and/or spare area of a NAND Flash page, after
 * calculating an ECC for the data area and storing it in the spare. If no
 * data buffer is provided, the ECC is read from the existing page spare. If
 * no spare buffer is provided, the spare area is still written with the ECC
 * information calculated on the data buffer.
 *
 * \param ecc  Pointer to an nand_flash_ecc instance.
 * \param block  Number of block to read from.
 * \param page  Number of page to read inside given block.
 * \param data  Data area buffer.
 * \param spare  Spare area buffer.
 *
 * \return 0 if successful; otherwise return the error code.
 */
uint32_t nand_flash_ecc_write_page(const struct nand_flash_ecc *ecc,
		uint16_t block, uint16_t page, uint8_t *data, uint8_t *spare)
{
	uint32_t error;

	uint16_t page_data_size
		= nand_flash_model_get_page_data_size(MODEL(ecc));

	uint8_t hamming_code[NAND_COMMON_MAX_SPARE_ECC_BYTES];
	uint8_t spare_buffer[NAND_COMMON_MAX_PAGE_SPARE_SIZE];

	/**
	 * Compute ECC on the new data, if provided. If not provided, hamming
	 * code set to 0xFFFF.. to keep existing bytes.
	 */
	memset(hamming_code, 0xFF, NAND_COMMON_MAX_SPARE_ECC_BYTES);
	if (data) {
		/* Compute hamming code on data */
		hamming_compute_256x(data, page_data_size, hamming_code);
	}

	/* if no buffer provided, use a temp one */
	if (!spare) {
		spare = spare_buffer;
	}

	memset(spare, 0xFF, NAND_COMMON_MAX_PAGE_SPARE_SIZE);

	nand_flash_spare_scheme_write_ecc(nand_flash_model_get_scheme(MODEL(ecc)),
			spare, hamming_code);

	/* Perform write operation */
	error = nand_flash_raw_write_page(RAW(ecc), block, page, data, spare);
	if (error) {
		return error;
	}

	return 0;
}
int main(void)
{
	uint16_t block, page;
	uint32_t i;

	uint32_t error = 0;

	/* Initialize the SAM3 system */
	sysclk_init();
	board_init();

	/* Initialize the console uart */
	configure_console();

	/* Output example information */
	printf("-- NAND Flash Raw Example --\n\r");
	printf("-- %s\n\r", BOARD_NAME);
	printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);

	memset(&nf_raw, 0, sizeof(nf_raw));

	if (nand_flash_raw_initialize(&nf_raw, 0, cmd_address,
			addr_address, data_address)) {

		printf("-E- Device Unknown\n\r");
		return 0;
	}

	printf("-I- NAND Flash driver initialized\n\r");

	/* Get device parameters */
	mem_size = nand_flash_model_get_device_size_in_bytes(&nf_raw.model);
	block_size = nand_flash_model_get_block_size_in_bytes(&nf_raw.model);
	num_block = nand_flash_model_get_device_size_in_blocks(&nf_raw.model);
	page_size = nand_flash_model_get_page_data_size(&nf_raw.model);
	pages_per_block =
			nand_flash_model_get_block_size_in_pages(&nf_raw.model);

	printf("-I- Size of the whole device in bytes : 0x%x \n\r", mem_size);
	printf("-I- Size in bytes of one single block of a device : 0x%x \n\r",
			block_size);
	printf("-I- Number of blocks in the entire device : 0x%x \n\r",
			num_block);
	printf("-I- Size of the data area of a page in bytes : 0x%x \n\r",
			page_size);
	printf("-I- Number of pages in the entire device : 0x%x \n\r",
			pages_per_block);

	/* Erase all block and use the last good block for read/write test */
	for (i = 0; i < num_block; i++) {
		error = nand_flash_raw_erase_block(&nf_raw, i);

		if (error == NAND_COMMON_ERROR_BADBLOCK) {
			printf("-E- Block %u is BAD block. \n\r", i);
		} else {
			block = i;
		}
	}
	/* Prepare a page size buffer in SRAM. */
	printf("-I- Preparing a buffer in SRAM ...\n\r");
	for (i = 0; i < page_size; i++) {
		write_buffer[i] = i & 0xFF;
	}

	/* Reset read buffer. */
	memset(read_buffer, 0, sizeof(read_buffer));

	/* Select a page. */
	page = 0;
	/* Write a page to the NAND Flash. */
	printf("-I- Write the buffer in page %d of block %d without ECC.\n\r",
			page, block);
	error = nand_flash_raw_write_page(&nf_raw, block, page, write_buffer,
			0);
	if (error) {
		printf("-E- Cannot write page %d of block %d.\n\r", page,
				block);
		return error;
	}

	/* Read the page from the NAND Flash. */
	printf("-I- Read page %d of block %d without ECC.\n\r", page, block);
	nand_flash_raw_read_page(&nf_raw, block, page, read_buffer, 0);

	/* Test if the read buffer is the same as SRAM buffer */
	error = memcmp(read_buffer, write_buffer, sizeof(write_buffer));
	if (error) {
		printf("-I- Read data is different from write data.\n\r");
		printf("-I- Need ECC module when handle this page.\n\r");

		return 0;
	}
	printf("-I- Read data matches write data.\n\r");

	printf("-I- Test passed.\n\r");

	while (1) {
		/* Do nothing */
	}
}