Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5032

General • Re: Wear leveling on flash is not helpful?

$
0
0
The data isn't terribly important and will fall back to a reasonable behavior if it reads an unexpected value.

I appreciate all the tips on this. I never would have guessed (and obviously haven't yet read the datasheet) that I could program the flash from 1 to 0, but not vice versa. Here's what I currently have (moderately well tested) if anyone else comes across this and is curious for implementation details.

Code:

#include <hardware/sync.h>#include <hardware/flash.h>// end - 4096. This doesn't include the XIP_BASE, which the flash_*() functions don't need#define FLASH_LAST_SECTOR (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)// XIP_BASE is execute in place (see pg24: ROM, XIP, SRAM, ...)#define XIP_FLASH_START   (XIP_BASE + FLASH_LAST_SECTOR)#define XIP_FLASH_END     (XIP_BASE + PICO_FLASH_SIZE_BYTES)#define PAGES_PER_SECTOR (FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE)// Erased flash has 0xFF in each byte, so find the last// non-0XFF value uint8_t flash_read_byte() {  uint8_t *p;  uint8_t last_val = 0;  for (uint32_t addr = XIP_FLASH_START; addr < XIP_FLASH_END; addr++) {    p = (uint8_t *)addr;    if (*p == 0xFF) {      // went too far      break;    } else {      last_val = *p;    }  }  return last_val;}// Taking advantage of this: Individual bytes can have any bit changed from 1 to 0 without requiring erasure. // https://forums.raspberrypi.com/viewtopic.php?t=369026&e=1void flash_update_byte(uint8_t new_val) {  // since we will ultimately write an entire page anyway, let's read a page at a time too  uint8_t buffer[FLASH_PAGE_SIZE];  uint8_t found_end = 0;  uint8_t last_val = 0;  uint8_t page;  uint8_t *p;  uint16_t addr_offset;  for (page = 0; page < PAGES_PER_SECTOR; page++) {    // clear the buffer    memset(buffer, 0xFF, FLASH_PAGE_SIZE);        for (addr_offset = 0; addr_offset < FLASH_PAGE_SIZE; addr_offset++) {      uint32_t addr = XIP_FLASH_START + (page * FLASH_PAGE_SIZE) + addr_offset;      p = (uint8_t *)addr;      buffer[addr_offset] = *p;      if (*p == 0xFF) {        found_end = 1;        buffer[addr_offset] = new_val;        break;      } else {        last_val = *p;      }    }    if (found_end) break;  }  // if value hasn't changed, don't write it.  if (last_val == new_val) {    return;  }  uint32_t save_interrupts = save_and_disable_interrupts();  // is the sector full?  if (!found_end) {    // Erase the last sector of the flash    flash_range_erase(FLASH_LAST_SECTOR, FLASH_SECTOR_SIZE);    page = 0;    memset(buffer, 0xFF, FLASH_PAGE_SIZE);    buffer[0] = new_val;  }  flash_range_program(    FLASH_LAST_SECTOR + page * FLASH_PAGE_SIZE,    (uint8_t *)buffer,    FLASH_PAGE_SIZE  );  restore_interrupts(save_interrupts);}

Statistics: Posted by mstrat — Sun Apr 14, 2024 6:33 pm



Viewing all articles
Browse latest Browse all 5032

Trending Articles