示例#1
0
/**
 * \brief Function for programming data to Flash
 *
 * This function will check whether the data is greater than Flash page size.
 * If it is greater, it splits and writes pagewise.
 *
 * \param address address of the Flash page to be programmed
 * \param buffer  pointer to the buffer containing data to be programmed
 * \param len     length of the data to be programmed to Flash
 */
static void program_memory(uint32_t address, uint8_t *buffer, uint32_t len)
{
	/* Check if length is greater than Flash page size */
	if (len > NVMCTRL_PAGE_SIZE) {
		uint32_t offset = 0;
		while (len > NVMCTRL_PAGE_SIZE) {
			/* Check if it is first page of a row */
			if ((address & 0xFF) == 0) {
				/* Erase row */
				nvm_erase_row(address);
			}
			/* Write one page data to flash */
			nvm_write_buffer(address, buffer + offset, NVMCTRL_PAGE_SIZE);
			/* Increment the address to be programmed */
			address += NVMCTRL_PAGE_SIZE;
			/* Increment the offset of the buffer containing data */
			offset += NVMCTRL_PAGE_SIZE;
			/* Decrement the length */
			len -= NVMCTRL_PAGE_SIZE;
		}
		/* Check if there is data remaining to be programmed*/
		if (len > 0) {
			/* Write the data to flash */
			nvm_write_buffer(address, buffer + offset, len);
		}
	} else {
		/* Check if it is first page of a row) */
		if ((address & 0xFF) == 0) {
			/* Erase row */
			nvm_erase_row(address);
		}
		/* Write the data to flash */
		nvm_write_buffer(address, buffer, len);
	}
}
/* if not, save new thing token to memory and use it */
uint8_t thethingsio_example_write_thing_token_nvm(char * thing_token)
{	
	uint8_t token_saved = true;
	uint8_t writeBuffer_Temp[NVMCTRL_PAGE_SIZE] = {0, };
		
	// erase flash memory area
	enum status_code status = nvm_erase_row(NVM_ADDR_THING_TOKEN_SAVED);
	if(status == STATUS_OK)
		status = nvm_erase_row(NVM_ADDR_THING_TOKEN);

	// rewrite flash memory area
	if(status == STATUS_OK)
		status = nvm_write_buffer(NVM_ADDR_THING_TOKEN_SAVED, &token_saved, 1);
	if(status == STATUS_OK)
		status = nvm_write_buffer(NVM_ADDR_THING_TOKEN, thing_token, THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH);
	
	// check if all the operations went through correctly
	if(status != STATUS_OK)
		printf("set thing token, write thing token error!!\r\n");
	
	// update thingsiO read write URL
	uint8_t thing_token_offset = sizeof(gau8TheThingsiOHttpRWUrl) - THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH - 1;
	memcpy((gau8TheThingsiOHttpRWUrl+thing_token_offset),thing_token, THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH);
	
	return true;
}
示例#3
0
/*---------------------------------------------------------------------------*/
static int
erase(unsigned long from, unsigned long to)
{
  enum status_code ret;
  unsigned long addr;

  if (!opened) {
    return -1;
  }

  from = (from / SECTOR_SIZE) * SECTOR_SIZE;
  to   = (to   / SECTOR_SIZE) * SECTOR_SIZE;

  for(addr = from; addr < to; addr += SECTOR_SIZE) {
    TRACE("addr: %ld", addr);
    if ((ret = nvm_erase_row(addr)) != STATUS_OK) {
      WARN("nvm_erase_row error: %d", ret);
      return -1;
    }
    watchdog_periodic();
  }

  while (!nvm_is_ready());

  return 1;
}
示例#4
0
/**
 * \brief Test NVM erasing
 *
 * This test erases test row and verifies it
 *
 * \param test Current test case.
 */
static void run_nvm_erase_test(const struct test_case *test)
{
	uint16_t offset = 0;
	volatile uint32_t test_page_address;
	test_page_address = TEST_PAGE_ADDR;
	volatile uint32_t *test_address;
	test_address = (uint32_t *) test_page_address;
	enum status_code status;

	/* Skip test if NVM initialization failed */
	test_assert_true(test, nvm_init_success == true,
			"NVM initialization failed, skipping test");

	/* Erase the row at test address */
	status = nvm_erase_row(test_page_address);

	/* Validate erase operation is complete */
	test_assert_true(test, status == STATUS_OK,
			"Erase operation not completed");

	/* Validate whether the data in NVM is 0xff after erasing */
	for (offset  = 0; offset < ((NVMCTRL_ROW_PAGES * NVMCTRL_PAGE_SIZE) / 4);
			offset++) {
		test_assert_true(test, ((uint32_t)test_address[offset]) == 0xffffffff,
				"Flash erase error @ %d offset", offset);
	}
}
示例#5
0
/*---------------------------------------------------------------------------*/
static int
write(unsigned long addr, const unsigned char * buffer, unsigned long len)
{
  enum status_code ret;
  unsigned long page_addr;
  int copy_len, i;

  if (!opened) {
    return -1;
  }

  /* Check if the row address is valid */
  if ((addr + len) >
      ((uint32_t)parameters.page_size * parameters.nvm_number_of_pages)) {
    WARN("addr is outside flash region");
    return -1;
  }

  while (len > 0) {
    /* Determine start address of page */
    page_addr = (addr / SECTOR_SIZE) * SECTOR_SIZE;

    /* Copy content of current page to tmp_buffer */
    memcpy(tmp_buffer, (void *)page_addr, SECTOR_SIZE);

    /* Wait until flash is ready */
    while (!nvm_is_ready());

    /* Erase current page */
    nvm_erase_row(page_addr);

    /* Determine number of bytes to copy */
    copy_len = min(len, (page_addr + SECTOR_SIZE) - addr);

    /* Update tmp_buffer with content from buffer */
    memcpy(&tmp_buffer[addr - page_addr], buffer, copy_len);

    /* Update buffer, len and addr */
    len    -= copy_len;
    addr   += copy_len;
    buffer += copy_len;

    /* Wait until flash is ready */
    while (!nvm_is_ready());

    /* Write contents of tmp_buffer to flash in NVMCTRL_ROW_PAGES steps */
    for (i = 0; i < NVMCTRL_ROW_PAGES; i++) {
      if ((ret = nvm_write_buffer(page_addr + i * PAGE_SIZE, &tmp_buffer[i * PAGE_SIZE], PAGE_SIZE)) != STATUS_OK) {
        WARN("nvm_write_buffer error: %d", ret);
        return -1;
      }
    }
  }

  /* Return OK */
  return 1;
}
示例#6
0
文件: flash.c 项目: abtink/openthread
otError utilsFlashErasePage(uint32_t aAddress)
{
    otError error = OT_ERROR_NONE;

    if (nvm_erase_row(aAddress) != STATUS_OK)
    {
        error = OT_ERROR_FAILED;
    }

    return error;
}
示例#7
0
int main(void)
{
	//! [setup_init]
	configure_nvm();
	//! [setup_init]

//! [main]
	//! [main_1]
	uint8_t page_buffer[NVMCTRL_PAGE_SIZE];
	//! [main_1]

	//! [main_2]
	for (uint32_t i = 0; i < NVMCTRL_PAGE_SIZE; i++) {
		page_buffer[i] = i;
	}
	//! [main_2]

	//! [main_3]
	enum status_code error_code;
	//! [main_3]

	//! [main_4]
	do
	{
		error_code = nvm_erase_row(
				100 * NVMCTRL_ROW_PAGES * NVMCTRL_PAGE_SIZE);
	} while (error_code == STATUS_BUSY);
	//! [main_4]

	//! [main_5]
	do
	{
		error_code = nvm_write_buffer(
				100 * NVMCTRL_ROW_PAGES * NVMCTRL_PAGE_SIZE,
				page_buffer, NVMCTRL_PAGE_SIZE);
	} while (error_code == STATUS_BUSY);
	//! [main_5]

	//! [main_6]
	do
	{
		error_code = nvm_read_buffer(
				100 * NVMCTRL_ROW_PAGES * NVMCTRL_PAGE_SIZE,
				page_buffer, NVMCTRL_PAGE_SIZE);
	} while (error_code == STATUS_BUSY);
	//! [main_6]

//! [main]

	while (true) {
		/* Do nothing */
	}
}
示例#8
0
static int
samd21_flash_erase_sector(uint32_t sector_address)
{
    struct nvm_parameters params;    
    int rc;
    int i;

    nvm_get_parameters(&params);    
    
    /* erase all rows in the sector */
    for(i = 0; i < SAMD21_FLASH_ROWS_PER_SECTOR; i++) {
        uint32_t row_address = sector_address + 
                i*SAMD21_FLASH_PAGES_PER_ROW*params.page_size;
        rc = nvm_erase_row(row_address);    
        if(rc != STATUS_OK) {
            return -1;
        }
    }
    return 0;
}
/**
 * \brief Updates an arbitrary section of a page with new data.
 *
 * Writes from a buffer to a given page in the NVM memory, retaining any
 * unmodified data already stored in the page.
 *
 * \note If manual write mode is enable, write command must be executed after
 * this function, otherwise the data will not write to NVM from page buffer.
 *
 * \warning This routine is unsafe if data integrity is critical; a system reset
 *          during the update process will result in up to one row of data being
 *          lost. If corruption must be avoided in all circumstances (including
 *          power loss or system reset) this function should not be used.
 *
 * \param[in]  destination_address  Destination page address to write to
 * \param[in]  buffer               Pointer to buffer where the data to write is
 *                                  stored
 * \param[in]  offset               Number of bytes to offset the data write in
 *                                  the page
 * \param[in]  length               Number of bytes in the page to update
 *
 * \return Status of the attempt to update a page.
 *
 * \retval STATUS_OK               Requested NVM memory page was successfully
 *                                 read
 * \retval STATUS_BUSY             NVM controller was busy when the operation
 *                                 was attempted
 * \retval STATUS_ERR_BAD_ADDRESS  The requested address was outside the
 *                                 acceptable range of the NVM memory region
 * \retval STATUS_ERR_INVALID_ARG  The supplied length and offset was invalid
 */
enum status_code nvm_update_buffer(
		const uint32_t destination_address,
		uint8_t *const buffer,
		uint16_t offset,
		uint16_t length)
{
	enum status_code error_code = STATUS_OK;
	uint8_t row_buffer[NVMCTRL_ROW_PAGES][NVMCTRL_PAGE_SIZE];

	/* Ensure the read does not overflow the page size */
	if ((offset + length) > _nvm_dev.page_size) {
		return STATUS_ERR_INVALID_ARG;
	}

	/* Calculate the starting row address of the page to update */
	uint32_t row_start_address =
			destination_address & ~((_nvm_dev.page_size * NVMCTRL_ROW_PAGES) - 1);

	/* Read in the current row contents */
	for (uint32_t i = 0; i < NVMCTRL_ROW_PAGES; i++) {
		do
		{
			error_code = nvm_read_buffer(
					row_start_address + (i * _nvm_dev.page_size),
					row_buffer[i], _nvm_dev.page_size);
		} while (error_code == STATUS_BUSY);

		if (error_code != STATUS_OK) {
			return error_code;
		}
	}

	/* Calculate the starting page in the row that is to be updated */
	uint8_t page_in_row =
			(destination_address % (_nvm_dev.page_size * NVMCTRL_ROW_PAGES)) /
			_nvm_dev.page_size;

	/* Update the specified bytes in the page buffer */
	for (uint32_t i = 0; i < length; i++) {
		row_buffer[page_in_row][offset + i] = buffer[i];
	}

	system_interrupt_enter_critical_section();

	/* Erase the row */
	do
	{
		error_code = nvm_erase_row(row_start_address);
	} while (error_code == STATUS_BUSY);

	if (error_code != STATUS_OK) {
		system_interrupt_leave_critical_section();
		return error_code;
	}

	/* Write the updated row contents to the erased row */
	for (uint32_t i = 0; i < NVMCTRL_ROW_PAGES; i++) {
		do
		{
			error_code = nvm_write_buffer(
					row_start_address + (i * _nvm_dev.page_size),
					row_buffer[i], _nvm_dev.page_size);
		} while (error_code == STATUS_BUSY);

		if (error_code != STATUS_OK) {
			system_interrupt_leave_critical_section();
			return error_code;
		}
	}

	system_interrupt_leave_critical_section();

	return error_code;
}