Example #1
0
static int
samd21_flash_init(void)
{
    int rc;
    struct nvm_config cfg;
    struct nvm_parameters params;
    nvm_get_config_defaults(&cfg);
    
    cfg.manual_page_write = false;
    rc = nvm_set_config(&cfg);
    if(rc != STATUS_OK) {
        return -1;
    }
    
    nvm_get_parameters(&params);    

    /* the samd21 flash doesn't use sector terminology. They use Row and 
     * page.  A row contains 4 pages. Each pages is a fixed size.  You can
     * only erase based on row. Here I will map the rows to sectors and 
     * deal with pages inside this driver.   */    
    samd21_flash_dev.hf_itf = &samd21_flash_funcs;
    samd21_flash_dev.hf_base_addr = SAMD21_FLASH_START_ADDR;
    samd21_flash_dev.hf_size = params.nvm_number_of_pages * params.page_size;
    samd21_flash_dev.hf_sector_cnt = 
            params.nvm_number_of_pages/SAMD21_FLASH_PAGES_PER_SECTOR;
    samd21_flash_dev.hf_align = 1;
    
    return 0;
}
Example #2
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;
}
Example #3
0
/**
 * \brief Test get flash parameter function
 *
 * This test gets the nvm parameters from the function and checks the
 * NVM page count and NVM page size
 *
 * \param test Current test case.
 */
static void run_nvm_parameter_test(const struct test_case *test)
{
	struct nvm_parameters parameters;

	/* Get the NVM parameters */
	nvm_get_parameters(&parameters);

	/* Validate the page size */
	test_assert_true(test, parameters.page_size == NVMCTRL_PAGE_SIZE,
			"Pagesize incorrect (read: 0x%02x,"
			" expected: 0x%02x)", parameters.page_size,
			NVMCTRL_PAGE_SIZE);

	/* Validate the page count */
	test_assert_true(test, parameters.nvm_number_of_pages == NVMCTRL_PAGES,
			"Number of Pages incorrect (read: 0x%02x,"
			" expected: 0x%02x)", parameters.nvm_number_of_pages,
			NVMCTRL_PAGES);
}
Example #4
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;
}
Example #5
0
/* samd21 flash always starts as 0x000000 */
static int
samd21_flash_sector_info(int idx, uint32_t *addr, uint32_t *sz)
{
    struct nvm_parameters params;
    int sector_size;
    int sector_cnt;
        
    nvm_get_parameters(&params);
    sector_cnt = params.nvm_number_of_pages/SAMD21_FLASH_PAGES_PER_SECTOR;
    sector_size = params.page_size*SAMD21_FLASH_PAGES_PER_SECTOR;
    
    if((idx >= sector_cnt) || (idx < 0)){
        return -1;
    }
    
    *sz = sector_size;
    *addr = idx * sector_size + SAMD21_FLASH_START_ADDR; 
    return 0;
}
Example #6
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;
}
Example #7
0
/*---------------------------------------------------------------------------*/
static int
open(void)
{
  if (!opened) {
    struct nvm_config config_nvm;
    nvm_get_config_defaults(&config_nvm);
    nvm_set_config(&config_nvm);
    nvm_get_parameters(&parameters);

    TRACE("bootloader_number_of_pages: %ld, eeprom_number_of_pages: %ld, nvm_number_of_pages: %d, page_size: %d",
          parameters.bootloader_number_of_pages,
          parameters.eeprom_number_of_pages,
          parameters.nvm_number_of_pages,
          parameters.page_size);

    while (!nvm_is_ready());

    opened = 1;
  }

  return 1;
}