Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow writing of data to the data partition as blocks #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions module_flash/include/flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,25 @@ unsigned fl_getWriteScratchSize(unsigned offset, unsigned size);
int fl_writeData(unsigned offset, unsigned size, const unsigned char src[],
unsigned char buffer[]);

/* Block level functions */

/**
* Write data to the data partition as blocks. A buffer is used to save
* the current data inside blocks that will be erased. The minimum size
* of the required buffer should be the same size as data being written, plus
* the size of 2 blocks. This function is used to minimize the regions of
* memory that need to be erased during data editing. Since not all memories
* support this feature, this function can be used on memories that have the
* sector erase size defined.
* \param offset The offset from the start of the data partition in bytes.
* \param size The number of bytes to write.
* \param src The data to write.
* \param buffer
* \return 0 on success, non zero on failure.
*/
int fl_writeDataAsBlocks(unsigned int offset, unsigned int size,
const unsigned char src[], unsigned char buffer[]);

/* Page level functions. */

/**
Expand Down
55 changes: 55 additions & 0 deletions module_flash/src/flashlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,61 @@ int fl_writeData(unsigned int offset, unsigned int size,
return( 0 );
}

/* Write and arbitrary number of bytes to the store (endangers data sharing pages/sectors),
* block by block.
*/
int fl_writeDataAsBlocks(unsigned int offset, unsigned int size,
const unsigned char src[], unsigned char buffer[]) {
unsigned blockSize = g_flashAccess->sectorEraseSize;
if (blockSize == 0) {
return 1; // Used memory type cannot erase individual blocks
}

unsigned startAddress = fl_getDataPartitionBase() + offset;

// Remember the address of the first block thet needs to be buffered.
// If block remainder is zero, then the address is the start address.
unsigned firstBlockDataStartAddress = startAddress % blockSize;
unsigned blockStartAddress = startAddress - firstBlockDataStartAddress;
unsigned firstBlockRemainder = blockSize - firstBlockDataStartAddress;

unsigned totalBlocksUsed = 1;
if (size > firstBlockRemainder) {
totalBlocksUsed += (size - firstBlockRemainder) / blockSize;
if ((size - firstBlockRemainder) % blockSize != 0) {
totalBlocksUsed++;
}
}

// Store all of the blocks that will be erased into a buffer
if (fl_int_readBytes(g_flashAccess, blockStartAddress, buffer, totalBlocksUsed * blockSize) != 0) {
return 1;
}

// Overwrite the old data with new
memcpy(buffer + firstBlockDataStartAddress, src, size);

// Erase blocks
for (int i = 0; i < totalBlocksUsed; i++) {
fl_int_waitWhileWriting(g_flashAccess);
fl_setWritability(1);
fl_int_issueShortCommand(g_flashAccess->sectorEraseCommand, blockStartAddress + i * blockSize, 3, 0, 0);
}

fl_int_waitWhileWriting(g_flashAccess);
fl_setWritability(0);

// Write the new blocks into memory page by page
int totalPagesToWriteBack = totalBlocksUsed * (blockSize / fl_getPageSize());
for (int i = 0; i < totalPagesToWriteBack; i++) {
if (fl_writePage(blockStartAddress + i * 256, buffer + i * 256) != 0) {
return 1;
}
}

return 0;
}

int fl_int_copySpec( fl_DeviceSpec* dest )
{
if( NULL == g_flashAccess )
Expand Down