diff --git a/firmware/logfs/CMakeLists.txt b/firmware/logfs/CMakeLists.txt index 606c804962..992600e347 100644 --- a/firmware/logfs/CMakeLists.txt +++ b/firmware/logfs/CMakeLists.txt @@ -1,9 +1,13 @@ set(LOGFS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src" + "${CMAKE_CURRENT_SOURCE_DIR}/srcpp" ) -file(GLOB_RECURSE LOGFS_SRCS +file(GLOB_RECURSE LOGFS_C_SRCS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" ) +file(GLOB_RECURSE LOGFS_CPP_SRCS CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/srcpp/*.cpp" +) message("") message("⚙️ Configuring LogFS") @@ -16,7 +20,7 @@ if (SKBUILD) find_package(Python3 REQUIRED COMPONENTS Interpreter Development) find_package(pybind11 CONFIG REQUIRED) - pybind11_add_module(logfs_src ${LOGFS_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/python/bindings.cpp) + pybind11_add_module(logfs_src ${LOGFS_CPP_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/python/bindings.cpp) target_include_directories(logfs_src PUBLIC "${LOGFS_INCLUDE_DIRS}") if (MSVC) @@ -43,21 +47,35 @@ else () message(FATAL_ERROR "❌ embedded.cmake must be included before logfs is subdirectoried") endif () embedded_library( - "logfs_cm7" - "${LOGFS_SRCS}" + "logfs_C" + "${LOGFS_C_SRCS}" + "${LOGFS_INCLUDE_DIRS}" + "cm7" + TRUE + ) + target_compile_options(logfs_C PRIVATE + -O3 + ) + embedded_library( + "logfs_CXX" + "${LOGFS_CPP_SRCS}" "${LOGFS_INCLUDE_DIRS}" "cm7" TRUE ) - target_compile_options(logfs_cm7 PRIVATE + target_compile_options(logfs_CXX PRIVATE -O3 ) elseif ("${TARGET}" STREQUAL "test") find_package(Python3 REQUIRED COMPONENTS Interpreter Development) find_package(pybind11 CONFIG) - # Create pybind11 module. - pybind11_add_module(logfs_src ${LOGFS_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/python/bindings.cpp) + # Create pybind11 module, imma make this js CPP when rewrite is done. + pybind11_add_module(logfs_src + ${LOGFS_C_SRCS} + ${LOGFS_CPP_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/python/bindings.cpp + ) target_include_directories(logfs_src PUBLIC "${LOGFS_INCLUDE_DIRS}") set(LOGFS_SRC_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/python") @@ -83,4 +101,3 @@ else () DEPENDS logfs_src) endif () endif () - diff --git a/firmware/logfs/srcpp/logfs.cpp b/firmware/logfs/srcpp/logfs.cpp new file mode 100644 index 0000000000..ee8eaf7ae4 --- /dev/null +++ b/firmware/logfs/srcpp/logfs.cpp @@ -0,0 +1,59 @@ +#include "logfs.hpp" + +#include +#include +#include + +namespace LogFs +{ + +[[maybe_unused]] static void initFile(File& file, const FileCfg& cfg, const OpenFlags flags) +{ + file.cache.cached_addr = INVALID_BLOCK; + file.cache.buf = cfg.cache; + file.cache_data = reinterpret_cast(cfg.cache.data()); + file.is_open = false; + file.flags = static_cast(flags); + + const auto path_len = std::min(cfg.path.size(), static_cast(PATH_BYTES - 1)); + std::memcpy(file.path, cfg.path.data(), path_len); + file.path[path_len] = '\0'; +} + +// File System +LogFs::FileSystem::FileSystem(const BlockDevice::Cfg& cfg_in) + : cfg(&cfg_in) +{ + assert(cfg != nullptr); + assert(cfg->block_size > sizeof(BlockFile)); + assert(cfg->block_size > sizeof(BlockMetadata)); + assert(cfg->block_size > sizeof(BlockData)); + + eff_block_size_bytes = cfg->block_size - (sizeof(BlockData) - 1); + max_path_len_bytes = std::min( + static_cast(cfg->block_size - sizeof(BlockFile)), + static_cast(PATH_BYTES) + ); +} + +ErrorCode FileSystem::mount() +{ + return ErrorCode::NOT_OPEN; //bs for now +} + +ErrorCode FileSystem::format() +{ + return ErrorCode::NOT_OPEN; +} + +ErrorCode FileSystem::open(File&, const FileCfg&, uint32_t) +{ + return ErrorCode::NOT_OPEN; +} + +ErrorCode FileSystem::close(File&) +{ + return ErrorCode::NOT_OPEN; +} + +} // namespace LogFs diff --git a/firmware/logfs/srcpp/logfs.hpp b/firmware/logfs/srcpp/logfs.hpp new file mode 100644 index 0000000000..9412e5a224 --- /dev/null +++ b/firmware/logfs/srcpp/logfs.hpp @@ -0,0 +1,169 @@ +#pragma once + +#include +#include +#include +#include + +namespace LogFs +{ + +inline constexpr uint16_t ORIGIN = 0; +inline constexpr uint32_t INVALID_BLOCK = 0xFFFFFFFFu; +inline constexpr uint16_t PATH_BYTES = 128; +inline constexpr uint16_t PAIR_SIZE = 2; + +enum class ErrorCode : int16_t +{ + OK = 0, + IO = -2, + CORRUPT = -3, + INVALID_ARG = -4, + INVALID_PATH = -5, + UNMOUNTED = -6, + NOMEM = -7, + NOT_OPEN = -8, + RD_ONLY = -9, + WR_ONLY = -10, + DNE = -11, + NO_MORE_FILES = -12, +}; + +enum class OpenFlags : uint8_t +{ + RD_ONLY = 0x01, + WR_ONLY = 0x02, + RD_WR = 0x03, + CREATE = 0x10, +}; + +enum class ReadFlags : uint8_t +{ + END, + ITER, +}; + +struct PairHeader +{ + uint32_t crc = 0; + uint8_t seq_num = 0; + uint32_t write_cycles = 0; + uint32_t replacement_addr = INVALID_BLOCK; +}; + +struct BlockFile +{ + PairHeader pair_hdr{}; + uint32_t next_file_addr = INVALID_BLOCK; + uint32_t metadata_addr = INVALID_BLOCK; + uint32_t head_data_addr = INVALID_BLOCK; + uint32_t prev_head_addr = INVALID_BLOCK; + uint32_t num_data_blocks = 0; + char path[1] = {}; +}; + +struct BlockMetadata +{ + PairHeader pair_hdr{}; + uint32_t num_bytes = 0; + uint8_t data = 0; +}; + +struct BlockData +{ + uint32_t crc = 0; + uint32_t prev_data_addr = INVALID_BLOCK; + uint32_t num_bytes = 0; + uint8_t data = 0; +}; + +struct Pair +{ + uint32_t addrs[PAIR_SIZE]; + uint8_t seq_num = 0; + bool seq_num_on_disk = false; +}; + +struct Cache +{ + uint32_t cached_addr = INVALID_BLOCK; + std::span buf{}; +}; + +struct FileCfg +{ + std::string_view path{}; + std::span cache{}; +}; + +class BlockDevice +{ +public: + struct Cfg + { + uint32_t block_size = 0; + uint32_t block_count = 0; + BlockDevice* device = nullptr; + std::span cache{}; + uint32_t write_cycles = 0; + bool rd_only = false; + }; + + virtual ~BlockDevice() = default; + virtual ErrorCode read(uint32_t block, std::span buf) = 0; + virtual ErrorCode write(uint32_t block, std::span buf) = 0; +}; + +class File +{ +public: + File(){}; + + Cache cache{}; + BlockData* cache_data = nullptr; + char path[PATH_BYTES] = {}; + uint32_t flags = 0; + + bool is_open = false; + Pair file_pair{}; + Pair metadata_pair{}; + uint32_t head_data_addr = INVALID_BLOCK; + + uint32_t read_iter_init = 0; + uint32_t read_iter_data_byte = 0; + uint32_t read_iter_data_addr = INVALID_BLOCK; +}; + +class FileSystem +{ +public: + explicit FileSystem(const BlockDevice::Cfg& cfg); + + ErrorCode mount(); + ErrorCode format(); + ErrorCode open(File& file, const FileCfg& cfg, uint32_t flags); + ErrorCode close(File& file); + +private: + const BlockDevice::Cfg* cfg = nullptr; + File root_file{}; + uint32_t head_file_addr = INVALID_BLOCK; + uint32_t head_addr = 0; + uint32_t eff_block_size_bytes = 0; + int max_path_len_bytes = 0; + bool mounted = false; + bool out_of_memory = false; + PairHeader* cache_pair_hdr = nullptr; + BlockFile* cache_file = nullptr; + BlockMetadata* cache_metadata = nullptr; + BlockData* cache_data = nullptr; +}; + +struct Path +{ + char path[PATH_BYTES] = {}; + uint32_t file_addr = INVALID_BLOCK; + uint32_t next_file_addr = INVALID_BLOCK; +}; + +} // namespace LogFs