void flashfsEraseCompletely() { m25p16_eraseCompletely(); flashfsClearBuffer(); flashfsSetTailAddress(0); }
void flashfsEraseCompletely(void) { flashEraseCompletely(); flashfsClearBuffer(); flashfsSetTailAddress(0); }
/** * Called after bytes have been written from the buffer to advance the position of the tail by the given amount. */ static void flashfsAdvanceTailInBuffer(uint32_t delta) { bufferTail += delta; // Wrap tail around the end of the buffer if (bufferTail >= FLASHFS_WRITE_BUFFER_SIZE) { bufferTail -= FLASHFS_WRITE_BUFFER_SIZE; } if (flashfsBufferIsEmpty()) { flashfsClearBuffer(); // Bring buffer pointers back to the start to be tidier } }
/** * Wait for the flash to become ready and begin flushing any buffered data to flash. * * The flash will still be busy some time after this sync completes, but space will * be freed up to accept more writes in the write buffer. */ void flashfsFlushSync() { if (flashfsBufferIsEmpty()) { return; // Nothing to flush } uint8_t const * buffers[2]; uint32_t bufferSizes[2]; flashfsGetDirtyDataBuffers(buffers, bufferSizes); flashfsWriteBuffers(buffers, bufferSizes, 2, true); // We've written our entire buffer now: flashfsClearBuffer(); }
/** * Write the given buffer to the flash either synchronously or asynchronously depending on the 'sync' parameter. * * If writing asynchronously, data will be silently discarded if the buffer overflows. * If writing synchronously, the routine will block waiting for the flash to become ready so will never drop data. */ void flashfsWrite(const uint8_t *data, unsigned int len, bool sync) { uint8_t const * buffers[3]; uint32_t bufferSizes[3]; // There could be two dirty buffers to write out already: flashfsGetDirtyDataBuffers(buffers, bufferSizes); // Plus the buffer the user supplied: buffers[2] = data; bufferSizes[2] = len; /* * Would writing this data to our buffer cause our buffer to reach the flush threshold? If so try to write through * to the flash now */ if (bufferSizes[0] + bufferSizes[1] + bufferSizes[2] >= FLASHFS_WRITE_BUFFER_AUTO_FLUSH_LEN) { uint32_t bytesWritten; // Attempt to write all three buffers through to the flash asynchronously bytesWritten = flashfsWriteBuffers(buffers, bufferSizes, 3, false); if (bufferSizes[0] == 0 && bufferSizes[1] == 0) { // We wrote all the data that was previously buffered flashfsClearBuffer(); if (bufferSizes[2] == 0) { // And we wrote all the data the user supplied! Job done! return; } } else { // We only wrote a portion of the old data, so advance the tail to remove the bytes we did write from the buffer flashfsAdvanceTailInBuffer(bytesWritten); } // Is the remainder of the data to be written too big to fit in the buffers? if (bufferSizes[0] + bufferSizes[1] + bufferSizes[2] > FLASHFS_WRITE_BUFFER_USABLE) { if (sync) { // Write it through synchronously flashfsWriteBuffers(buffers, bufferSizes, 3, true); flashfsClearBuffer(); } else { /* * Silently drop the data the user asked to write (i.e. no-op) since we can't buffer it and they * requested async. */ } return; } // Fall through and add the remainder of the incoming data to our buffer data = buffers[2]; len = bufferSizes[2]; } // Buffer up the data the user supplied instead of writing it right away // First write the portion before we wrap around the end of the circular buffer unsigned int bufferBytesBeforeWrap = FLASHFS_WRITE_BUFFER_SIZE - bufferHead; unsigned int firstPortion = len < bufferBytesBeforeWrap ? len : bufferBytesBeforeWrap; memcpy(flashWriteBuffer + bufferHead, data, firstPortion); bufferHead += firstPortion; data += firstPortion; len -= firstPortion; // If we wrap the head around, write the remainder to the start of the buffer (if any) if (bufferHead == FLASHFS_WRITE_BUFFER_SIZE) { memcpy(flashWriteBuffer + 0, data, len); bufferHead = len; } }
/** * Write the given buffers to flash sequentially at the current tail address, advancing the tail address after * each write. * * In synchronous mode, waits for the flash to become ready before writing so that every byte requested can be written. * * In asynchronous mode, if the flash is busy, then the write is aborted and the routine returns immediately. * In this case the returned number of bytes written will be less than the total amount requested. * * Modifies the supplied buffer pointers and sizes to reflect how many bytes remain in each of them. * * bufferCount: the number of buffers provided * buffers: an array of pointers to the beginning of buffers * bufferSizes: an array of the sizes of those buffers * sync: true if we should wait for the device to be idle before writes, otherwise if the device is busy the * write will be aborted and this routine will return immediately. * * Returns the number of bytes written */ static uint32_t flashfsWriteBuffers(uint8_t const **buffers, uint32_t *bufferSizes, int bufferCount, bool sync) { uint32_t bytesTotal = 0; int i; for (i = 0; i < bufferCount; i++) { bytesTotal += bufferSizes[i]; } if (!sync && !m25p16_isReady()) { return 0; } uint32_t bytesTotalRemaining = bytesTotal; while (bytesTotalRemaining > 0) { uint32_t bytesTotalThisIteration; uint32_t bytesRemainThisIteration; /* * Each page needs to be saved in a separate program operation, so * if we would cross a page boundary, only write up to the boundary in this iteration: */ if (tailAddress % M25P16_PAGESIZE + bytesTotalRemaining > M25P16_PAGESIZE) { bytesTotalThisIteration = M25P16_PAGESIZE - tailAddress % M25P16_PAGESIZE; } else { bytesTotalThisIteration = bytesTotalRemaining; } // Are we at EOF already? Abort. if (flashfsIsEOF()) { // May as well throw away any buffered data flashfsClearBuffer(); break; } m25p16_pageProgramBegin(tailAddress); bytesRemainThisIteration = bytesTotalThisIteration; for (i = 0; i < bufferCount; i++) { if (bufferSizes[i] > 0) { // Is buffer larger than our write limit? Write our limit out of it if (bufferSizes[i] >= bytesRemainThisIteration) { m25p16_pageProgramContinue(buffers[i], bytesRemainThisIteration); buffers[i] += bytesRemainThisIteration; bufferSizes[i] -= bytesRemainThisIteration; bytesRemainThisIteration = 0; break; } else { // We'll still have more to write after finishing this buffer off m25p16_pageProgramContinue(buffers[i], bufferSizes[i]); bytesRemainThisIteration -= bufferSizes[i]; buffers[i] += bufferSizes[i]; bufferSizes[i] = 0; } } } m25p16_pageProgramFinish(); bytesTotalRemaining -= bytesTotalThisIteration; // Advance the cursor in the file system to match the bytes we wrote flashfsSetTailAddress(tailAddress + bytesTotalThisIteration); /* * We'll have to wait for that write to complete before we can issue the next one, so if * the user requested asynchronous writes, break now. */ if (!sync) break; } return bytesTotal - bytesTotalRemaining; }