void flashfsClose(void) { switch(flashfsGetGeometry()->flashType) { case FLASH_TYPE_NOR: break; case FLASH_TYPE_NAND: flashFlush(); // Advance tailAddress to next page boundary. uint32_t pageSize = flashfsGetGeometry()->pageSize; flashfsSetTailAddress((tailAddress + pageSize - 1) & ~(pageSize - 1)); break; } }
static void osdGetBlackboxStatusString(char * buff) { bool storageDeviceIsWorking = false; uint32_t storageUsed = 0; uint32_t storageTotal = 0; switch (blackboxConfig()->device) { #ifdef USE_SDCARD case BLACKBOX_DEVICE_SDCARD: storageDeviceIsWorking = sdcard_isInserted() && sdcard_isFunctional() && (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_READY); if (storageDeviceIsWorking) { storageTotal = sdcard_getMetadata()->numBlocks / 2000; storageUsed = storageTotal - (afatfs_getContiguousFreeSpace() / 1024000); } break; #endif #ifdef USE_FLASHFS case BLACKBOX_DEVICE_FLASH: storageDeviceIsWorking = flashfsIsReady(); if (storageDeviceIsWorking) { const flashGeometry_t *geometry = flashfsGetGeometry(); storageTotal = geometry->totalSize / 1024; storageUsed = flashfsGetOffset() / 1024; } break; #endif default: break; } if (storageDeviceIsWorking) { const uint16_t storageUsedPercent = (storageUsed * 100) / storageTotal; tfp_sprintf(buff, "%d%%", storageUsedPercent); } else { tfp_sprintf(buff, "FAULT"); } }
/** * 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 && !flashIsReady()) { return 0; } uint32_t bytesTotalRemaining = bytesTotal; uint16_t pageSize = flashfsGetGeometry()->pageSize; 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 % pageSize + bytesTotalRemaining > pageSize) { bytesTotalThisIteration = pageSize - tailAddress % pageSize; } else { bytesTotalThisIteration = bytesTotalRemaining; } // Are we at EOF already? Abort. if (flashfsIsEOF()) { // May as well throw away any buffered data flashfsClearBuffer(); break; } flashPageProgramBegin(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) { flashPageProgramContinue(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 flashPageProgramContinue(buffers[i], bufferSizes[i]); bytesRemainThisIteration -= bufferSizes[i]; buffers[i] += bufferSizes[i]; bufferSizes[i] = 0; } } } flashPageProgramFinish(); 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; }