/** * Write bytes to a flash page. Address must not cross a page boundary. * * Bits can only be set to zero, not from zero back to one again. In order to set bits to 1, use the erase command. * * Length must be smaller than the page size. * * This will wait for the flash to become ready before writing begins. * * Datasheet indicates typical programming time is 0.8ms for 256 bytes, 0.2ms for 64 bytes, 0.05ms for 16 bytes. * (Although the maximum possible write time is noted as 5ms). * * If you want to write multiple buffers (whose sum of sizes is still not more than the page size) then you can * break this operation up into one beginProgram call, one or more continueProgram calls, and one finishProgram call. */ void m25p16_pageProgram(uint32_t address, const uint8_t *data, int length) { m25p16_pageProgramBegin(address); m25p16_pageProgramContinue(data, length); m25p16_pageProgramFinish(); }
/** * 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; }