mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-03-31 03:55:46 +00:00
146 lines
5.0 KiB
C++
146 lines
5.0 KiB
C++
/*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019 hathach for Adafruit Industries
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
#include "InternalFileSystem.h"
|
|
|
|
//--------------------------------------------------------------------+
|
|
// LFS Disk IO
|
|
//--------------------------------------------------------------------+
|
|
static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
|
|
{
|
|
if (!buffer || !size) return LFS_ERR_INVAL;
|
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE + off);
|
|
memcpy(buffer, (void *)address, size);
|
|
return LFS_ERR_OK;
|
|
}
|
|
|
|
// Program a region in a block. The block must have previously
|
|
// been erased. Negative error codes are propogated to the user.
|
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
|
|
{
|
|
HAL_StatusTypeDef hal_rc = HAL_OK;
|
|
lfs_block_t addr = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE + off);
|
|
uint64_t *bufp = (uint64_t *) buffer;
|
|
|
|
if (HAL_FLASH_Unlock() != HAL_OK) return LFS_ERR_IO;
|
|
for (uint32_t i = 0; i < size/8; i++) {
|
|
if ((addr < LFS_FLASH_ADDR_BASE) || (addr > FLASH_END_ADDR)) {
|
|
HAL_FLASH_Lock();
|
|
return LFS_ERR_INVAL;
|
|
}
|
|
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, *bufp);
|
|
addr += 8;
|
|
bufp += 1;
|
|
}
|
|
if (HAL_FLASH_Lock() != HAL_OK) return LFS_ERR_IO;
|
|
|
|
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO;
|
|
}
|
|
|
|
// Erase a block. A block must be erased before being programmed.
|
|
// The state of an erased block is undefined. Negative error codes
|
|
// are propogated to the user.
|
|
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
|
{
|
|
HAL_StatusTypeDef hal_rc;
|
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * FLASH_PAGE_SIZE);
|
|
uint32_t pageError = 0;
|
|
FLASH_EraseInitTypeDef EraseInitStruct = {
|
|
.TypeErase = FLASH_TYPEERASE_PAGES,
|
|
.Page = 0,
|
|
.NbPages = 1
|
|
};
|
|
|
|
if ((address < LFS_FLASH_ADDR_BASE) || (address > FLASH_END_ADDR)) {
|
|
return LFS_ERR_INVAL;
|
|
}
|
|
EraseInitStruct.Page = (address - FLASH_BASE) / FLASH_PAGE_SIZE;
|
|
HAL_FLASH_Unlock();
|
|
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &pageError);
|
|
HAL_FLASH_Lock();
|
|
|
|
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO;
|
|
}
|
|
|
|
// Sync the state of the underlying block device. Negative error codes
|
|
// are propogated to the user.
|
|
static int _internal_flash_sync(const struct lfs_config *c)
|
|
{
|
|
return LFS_ERR_OK; // don't need sync
|
|
}
|
|
|
|
struct lfs_config _InternalFSConfig = {
|
|
.context = NULL,
|
|
.read = _internal_flash_read,
|
|
.prog = _internal_flash_prog,
|
|
.erase = _internal_flash_erase,
|
|
.sync = _internal_flash_sync,
|
|
|
|
.read_size = LFS_BLOCK_SIZE,
|
|
.prog_size = LFS_BLOCK_SIZE,
|
|
.block_size = LFS_BLOCK_SIZE,
|
|
.block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE,
|
|
.lookahead = 128,
|
|
|
|
.read_buffer = NULL,
|
|
.prog_buffer = NULL,
|
|
.lookahead_buffer = NULL,
|
|
.file_buffer = NULL
|
|
};
|
|
|
|
InternalFileSystem InternalFS;
|
|
|
|
//--------------------------------------------------------------------+
|
|
//
|
|
//--------------------------------------------------------------------+
|
|
|
|
InternalFileSystem::InternalFileSystem(void)
|
|
: Adafruit_LittleFS(&_InternalFSConfig)
|
|
{
|
|
|
|
}
|
|
|
|
bool InternalFileSystem::begin(void)
|
|
{
|
|
volatile bool format_fs;
|
|
#ifdef FORMAT_FS
|
|
format_fs = true;
|
|
#else
|
|
format_fs = false; // you can always use debugger to force formatting ;)
|
|
#endif
|
|
// failed to mount, erase all sector then format and mount again
|
|
if ( format_fs || !Adafruit_LittleFS::begin() )
|
|
{
|
|
// lfs format
|
|
this->format();
|
|
// mount again if still failed, give up
|
|
if ( !Adafruit_LittleFS::begin() ) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|