For my project, I am writing some code that gets some results and I want to store these results on external flash memory. The external flash memory in question is a MX25R8035F. I found that writing without erasing only works the first time I wrote something to an address.
But because of this I'm running into some memory issues. The smallest erase is a sector erase (4096 bytes.) If I want to write to a specific address I would first need to read the sector that contains that address, change the bytes that I want to be changed and then write the whole sector (writing is only per page.)
Is there a more efficient way of using this external flash memory? Specifically using less memory to change one or two bytes.
The function I use now this can be found below:
uint8_t EXT_FLASH_write(size_t address, uint8_t *buf, size_t length) {/* * The entire sector will be erased when writing to an offset inside that sector * Therefore this function will first retrieve all data inside the sector and update the retrieved * data with the values inside buff which and will then write the entire content back to the sector */ uint8_t wbuf[4]; SPI_Transaction transaction; uint32_t sectorBaseAddr; uint8_t temp[EXT_FLASH_ERASE_SECTOR_SIZE]; uint8_t tries; size_t ilen; /* interim length per instruction */ uint32_t bufIndex = 0; uint8_t pageIterations; while (length > 0) { // first retrieve entire sector so it can be erased on the chip sectorBaseAddr = EXT_FLASH_SECTOR_BASE_ADDR(address); EXT_FLASH_read(sectorBaseAddr, temp, EXT_FLASH_ERASE_SECTOR_SIZE); // Erase the sector on the chip EXT_FLASH_erase(address, EXT_FLASH_ERASE_SECTOR_SIZE); ilen = EXT_FLASH_PROGRAM_PAGE_SIZE - (address % EXT_FLASH_PROGRAM_PAGE_SIZE); if (length < ilen) ilen = length; memcpy(temp + (address - sectorBaseAddr), buf + bufIndex, length); bufIndex += ilen; address += ilen; length -= ilen; tries = 0; if (EXT_FLASH_writeEnable() != 0) { if (tries == EXT_FLASH_MAX_TRIES) { return 1; } tries++; } tries = 0; while (EXT_FLASH_waitReady() != 2) { if (tries == EXT_FLASH_MAX_TRIES) { return 1; } EXT_FLASH_writeEnable(); tries++; } // programming the external flash can only be done in pages // so divide current sector into pages and write each page separately for (pageIterations = 0; pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE< EXT_FLASH_ERASE_SECTOR_SIZE; pageIterations++) { EXT_FLASH_select(); wbuf[0] = EXT_FLASH_CODE_PROGRAM; wbuf[1] = ((sectorBaseAddr+ (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) >> 16)& 0xff; wbuf[2] = ((sectorBaseAddr+ (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) >> 8)& 0xff; wbuf[3] = (sectorBaseAddr+ (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE)) & 0xff; // Configure the transaction transaction.count = sizeof(wbuf); transaction.txBuf = wbuf; transaction.rxBuf = NULL; if (!SPI_transfer(masterSpi, &transaction)) { /* failure */ EXT_FLASH_deselect(); return 1; } // Configure the transaction transaction.count = EXT_FLASH_PROGRAM_PAGE_SIZE; transaction.txBuf = temp+ (pageIterations * EXT_FLASH_PROGRAM_PAGE_SIZE); transaction.rxBuf = NULL; if (!SPI_transfer(masterSpi, &transaction)) { /* failure */ EXT_FLASH_deselect(); return 1; } EXT_FLASH_deselect(); } } return 0;}