/* if yes, load thing token from memory */
uint8_t thethingsio_example_load_thing_token_nvm(void) 
{
	/* check for valid thing token in NVM of device */
	uint8_t readBuffer_Temp[NVMCTRL_PAGE_SIZE] = { 0, };
	uint8_t readToken_Temp[NVMCTRL_PAGE_SIZE] = { 0, };
		
	enum status_code status = nvm_read_buffer(NVM_ADDR_THING_TOKEN, readBuffer_Temp, NVMCTRL_PAGE_SIZE);

	if(status != STATUS_OK) {
		printf("load thing token, read thing token error (0x%x)\r\n", status);
		return false;
	}
	
	
	// update thingsiO read write URL
	uint8_t thing_token_offset = sizeof(gau8TheThingsiOHttpRWUrl) - THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH - 1;
	
	memcpy((gau8TheThingsiOHttpRWUrl+thing_token_offset), readBuffer_Temp, THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH);	
	
	// update thingIO subscribe URL
	// add by jb to support subscription
	uint8_t things_token_subscribe_offset = sizeof(gau0TheThingsIOHttpSubsURL) - THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH -1;
	memcpy((gau0TheThingsIOHttpSubsURL+things_token_subscribe_offset), readBuffer_Temp, THETHINGSIO_EXAMPLE_THING_TOKEN_LENGTH);
	printf("subscribe thing token %s", readBuffer_Temp);
	printf("URL subscription %s"DEBUG_EOL, gau0TheThingsIOHttpSubsURL);
	// memcpy((gau0TheThingsIOHttpSubsURL+things_token_subscribe_offset + sizeof(KEEP_ALIVE_VALUE)), KEEP_ALIVE_VALUE, sizeof(KEEP_ALIVE_VALUE));
	
	
	return true;
}
Esempio n. 2
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 */
	}
}
Esempio n. 3
0
static int
samd21_flash_write(uint32_t address, const void *src, uint32_t len)
{
    int base_address;
    int offset;
    struct nvm_parameters params;
    uint8_t page_buffer[64];
    const uint8_t *psrc = src;
    
    /* make sure this fits into our stack buffer  */
    nvm_get_parameters(&params);      
    assert(params.page_size <= sizeof(page_buffer));
    
    /* get the page address (this is not a sector, there are 4 pages per
     * row */
    while(len) {   
        int write_len;
        
        base_address = address & ~(params.page_size - 1);
        
        offset = address - base_address;
        write_len = params.page_size - offset;
        
        if(write_len > len) {
            write_len = len;
        }

        if(nvm_read_buffer(base_address, page_buffer, params.page_size) 
                        != STATUS_OK) {
            return -1;
        }

        /* move the pointers since this is a sure thing */
        len -= write_len;
        address += write_len;
        
        /* copy it into the page buffer */
        while(write_len--) {
            page_buffer[offset++] = *psrc++;
        }
        
        /* 0x000054a4 */
#if 1
        /* write back the page buffer buffer */
        if(nvm_write_buffer(base_address,page_buffer, params.page_size)
                        != STATUS_OK) {
            return -1;
        }                
#endif
    }    
    return 0;
}
/* check if thing has been configured already (thing token) */
uint8_t thethingsio_example_thing_token_available_nvm(void)
{
	uint8_t token_saved = false;
	enum status_code status = nvm_read_buffer(NVM_ADDR_THING_TOKEN_SAVED, &token_saved, 1);
	
	if(status != STATUS_OK) {
		printf("load thing token, read NVM error (0x%x) \r\n", status);
		return false;
	}
	
	if(token_saved != true) {
		printf("load thing token, thing token does not exist in NVM \r\n");
		return false;
	}
	return true;
}
Esempio n. 5
0
/**
 * \brief Test NVM update
 *
 * This test modifies first half of the test page with different pattern,
 * reads it back and checks whether the values are updated
 *
 * \param test Current test case.
 */
static void run_nvm_update_test(const struct test_case *test)
{
	uint8_t buffer[NVMCTRL_PAGE_SIZE], i;
	enum status_code status;

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

	/* Fill half of the buffer with pattern 2 */
	for (i = 0; i < (NVMCTRL_PAGE_SIZE / 2); i++) {
		buffer[i] = BYTE_PATTERN2(i);
	}

	/* Update first half of the test page with new data */
	status = nvm_update_buffer(TEST_PAGE_ADDR, buffer, 0,
		(NVMCTRL_PAGE_SIZE / 2));

	/* Validate whether the update operation is complete */
	test_assert_true(test, status == STATUS_OK,
			"Update operation error");

	/* Flush the buffer */
	for (i = 0; i < NVMCTRL_PAGE_SIZE; i++) {
		buffer[i] = 0;
	}

	/* Read the NVM contents at test address to buffer */
	status = nvm_read_buffer(TEST_PAGE_ADDR, buffer, NVMCTRL_PAGE_SIZE);

	/* Validate whether the read operation is complete */
	test_assert_true(test, status == STATUS_OK,
			"Read operation error");

	/* Check the integrity of data in NVM */
	for (i = 0; i < (NVMCTRL_PAGE_SIZE / 2); i++) {
		test_assert_true(test, buffer[i] == BYTE_PATTERN2(i),
				"Value not expected @ byte %d (read: 0x%02x,"
				" expected: 0x%02x)", i, buffer[i], BYTE_PATTERN2(i));
	}
	for (i = (NVMCTRL_PAGE_SIZE / 2); i < NVMCTRL_PAGE_SIZE; i++) {
		test_assert_true(test, buffer[i] == BYTE_PATTERN1(i),
				"Value not expected @ byte %d (read: 0x%02x,"
				" expected: 0x%02x)", i, buffer[i], BYTE_PATTERN1(i));
	}
}
Esempio n. 6
0
static int
samd21_flash_read(uint32_t address, void *dst, uint32_t num_bytes)
{
    int base_address;
    int offset;
    struct nvm_parameters params;
    uint8_t page_buffer[64];
    uint8_t *pdst = dst;
    
    /* make sure this fits into our stack buffer  */
    nvm_get_parameters(&params);      
    assert(params.page_size <= sizeof(page_buffer));
    
    /* get the page address (this is not a sector, there are 4 pages per
     * row */
    while(num_bytes) {   
        int read_len;
        
        base_address = address & ~(params.page_size - 1);
        
        offset = address - base_address;
        read_len = params.page_size - offset;
        
        if(read_len > num_bytes) {
            read_len = num_bytes;
        }

        if(nvm_read_buffer(base_address, page_buffer, params.page_size) 
                        != STATUS_OK) {
            return -1;
        }
        
        /* move the pointers since this is a sure thing now */
        num_bytes -= read_len;
        address += read_len;     

        /* copy it into the page buffer */
        while(read_len--) {
             *pdst++ = page_buffer[offset++];
        }                              
    }    
    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;
}