Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions firmware/logfs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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")

Expand All @@ -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)
Expand All @@ -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")
Expand All @@ -83,4 +101,3 @@ else ()
DEPENDS logfs_src)
endif ()
endif ()

59 changes: 59 additions & 0 deletions firmware/logfs/srcpp/logfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "logfs.hpp"

#include <algorithm>
#include <cassert>
#include <cstring>

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<BlockData*>(cfg.cache.data());
file.is_open = false;
file.flags = static_cast<uint32_t>(flags);

const auto path_len = std::min(cfg.path.size(), static_cast<size_t>(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<int>(cfg->block_size - sizeof(BlockFile)),
static_cast<int>(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
169 changes: 169 additions & 0 deletions firmware/logfs/srcpp/logfs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#pragma once

#include <cassert>
#include <cstdint>
#include <span>
#include <string_view>

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<std::byte> buf{};
};

struct FileCfg
{
std::string_view path{};
std::span<std::byte> cache{};
};

class BlockDevice
{
public:
struct Cfg
{
uint32_t block_size = 0;
uint32_t block_count = 0;
BlockDevice* device = nullptr;
std::span<std::byte> cache{};
uint32_t write_cycles = 0;
bool rd_only = false;
};

virtual ~BlockDevice() = default;
virtual ErrorCode read(uint32_t block, std::span<std::byte> buf) = 0;
virtual ErrorCode write(uint32_t block, std::span<const std::byte> 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
Loading