Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COBC File System #12

Merged
merged 10 commits into from
Nov 13, 2022
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ include(cmake/custom-commands.cmake)
find_package_and_notify(etl)
find_package_and_notify(type_safe)
find_rodos()
if(CMAKE_SYSTEM_NAME STREQUAL Generic)
find_package_and_notify(littlefs)
endif()

# ---- Declare targets ----

Expand All @@ -28,6 +31,7 @@ add_library(Sts1CobcSw_Utility OBJECT)
add_program(HelloDummy)

if(CMAKE_SYSTEM_NAME STREQUAL Generic)
add_library(Sts1CobcSw_FileSystem OBJECT)
add_library(Sts1CobcSw_Hal INTERFACE)
add_library(Sts1CobcSw_Periphery OBJECT)
add_program(CobcSw)
Expand Down
1 change: 1 addition & 0 deletions Sts1CobcSw/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
if(CMAKE_SYSTEM_NAME STREQUAL Generic)
add_subdirectory(FileSystem)
add_subdirectory(Hal)
add_subdirectory(Periphery)
endif()
Expand Down
3 changes: 3 additions & 0 deletions Sts1CobcSw/FileSystem/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target_sources(Sts1CobcSw_FileSystem PRIVATE FileSystem.cpp)
target_link_libraries(Sts1CobcSw_FileSystem PUBLIC littlefs::littlefs)
target_link_libraries(Sts1CobcSw_FileSystem PRIVATE Sts1CobcSw_Periphery Sts1CobcSw_Serial)
234 changes: 234 additions & 0 deletions Sts1CobcSw/FileSystem/FileSystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
#include <Sts1CobcSw/FileSystem/FileSystem.hpp>
#include <Sts1CobcSw/Periphery/Flash.hpp>
#include <Sts1CobcSw/Serial/Byte.hpp>

#include <rodos_no_using_namespace.h>

#include <algorithm>
#include <array>
#include <span>


namespace sts1cobcsw::fs
{
using periphery::flash::pageSize;
using serial::Byte;


// --- Private function declarations

auto Read(lfs_config const * config,
lfs_block_t blockNo,
lfs_off_t offset,
void * buffer,
lfs_size_t size) -> int;
auto Program(lfs_config const * config,
lfs_block_t blockNo,
lfs_off_t offset,
void const * buffer,
lfs_size_t size) -> int;
auto Erase(lfs_config const * config, lfs_block_t blockNo) -> int;
auto Sync(lfs_config const * config) -> int;


// --- Globals ---

auto readBuffer = std::array<serial::Byte, pageSize>{};
auto programBuffer = std::array<serial::Byte, pageSize>{};
auto lookaheadBuffer = std::array<serial::Byte, pageSize>{};

// TODO: Check if they need to be global
lfs_t lfs{};
lfs_file_t lfsFile{};
// TODO: Maybe add a conifg header to set things like NAME_MAX or whatever. That could safe a bit of
// RAM.
const lfs_config lfsConfig{.read = &Read,
.prog = &Program,
.erase = &Erase,
.sync = &Sync,

.read_size = pageSize,
.prog_size = pageSize,
.block_size = periphery::flash::sectorSize,
.block_count = periphery::flash::nSectors,
.block_cycles = 200,
.cache_size = pageSize,
.lookahead_size = pageSize,

.read_buffer = data(readBuffer),
.prog_buffer = data(programBuffer),
.lookahead_buffer = data(lookaheadBuffer)};


// --- Public function definitions

auto Initialize() -> void
{
[[maybe_unused]] auto errorCode = periphery::flash::Initialize();
}


auto Format() -> int
{
return lfs_format(&lfs, &lfsConfig);
}


// Must be called before using the file system
auto Mount() -> int
{
return lfs_mount(&lfs, &lfsConfig);
}


// TODO: This begs for a destructor
// Must be called to release all the resources of the file system
auto Unmount() -> int
{
return lfs_unmount(&lfs);
}


auto OpenFile(char const * path, int flags) -> int
{
return lfs_file_open(&lfs, &lfsFile, path, flags);
}


auto CloseFile() -> int
{
return lfs_file_close(&lfs, &lfsFile);
}


//! @brief Return the size of the currently open file.
auto FileSize() -> int
{
return lfs_file_size(&lfs, &lfsFile);
}


auto CreateDirectory(char const * path) -> int
{
return lfs_mkdir(&lfs, path);
}


//! @brief Remove a file or an empty directory.
auto Remove(char const * path) -> int
{
return lfs_remove(&lfs, path);
}


//! @brief List information (type, size, name) about the files under the given path.
auto Ls(char const * path) -> int
{
using RODOS::PRINTF;

PRINTF("$ ls %s\n", path);

auto directory = lfs_dir_t{};
int errorCode = lfs_dir_open(&lfs, &directory, path);
if(errorCode != 0)
{
return errorCode;
}

auto info = lfs_info{};
while(true)
{
int result = lfs_dir_read(&lfs, &directory, &info);
if(result < 0)
{
// An error occurred
return result;
}
if(result == 0)
{
// We are at the end of the directory
break;
}

switch(info.type)
{
case LFS_TYPE_REG:
{
PRINTF(" reg ");
break;
}
case LFS_TYPE_DIR:
{
PRINTF(" dir ");
break;
}
default:
{
PRINTF(" ? ");
break;
}
}

PRINTF(" %8d B %s\n", static_cast<int>(info.size), &(info.name[0]));
}

return lfs_dir_close(&lfs, &directory);
}


// --- Private function definitions

auto Read(lfs_config const * config,
lfs_block_t blockNo,
lfs_off_t offset,
void * buffer,
lfs_size_t size) -> int
{
// The following only works if read_size == pageSize
auto startAddress = blockNo * config->block_size + offset;
for(auto i = 0U; i < size; i += config->read_size)
{
auto page = periphery::flash::ReadPage(startAddress + i);
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
std::copy(begin(page), end(page), (static_cast<Byte *>(buffer) + i));
}

return 0;
}


auto Program(lfs_config const * config,
lfs_block_t blockNo,
lfs_off_t offset,
void const * buffer,
lfs_size_t size) -> int
{
// The following only works if prog_size == pageSize
auto startAddress = blockNo * config->block_size + offset;
for(auto i = 0U; i < size; i += config->prog_size)
{
auto page = periphery::flash::Page{};
std::copy((static_cast<Byte const *>(buffer) + i), // NOLINT
(static_cast<Byte const *>(buffer) + i + config->prog_size), // NOLINT
begin(page));
periphery::flash::ProgramPage(startAddress + i, std::span(page));
periphery::flash::WaitWhileBusy();
}
return 0;
}


auto Erase(lfs_config const * config, lfs_block_t blockNo) -> int
{
periphery::flash::EraseSector(blockNo * config->block_size);
periphery::flash::WaitWhileBusy();
return 0;
}


auto Sync([[maybe_unused]] lfs_config const * config) -> int
{
periphery::flash::WaitWhileBusy();
return 0;
}
}
52 changes: 52 additions & 0 deletions Sts1CobcSw/FileSystem/FileSystem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once


#include <littlefs/lfs.h>


namespace sts1cobcsw::fs
{
extern lfs_t lfs;
extern lfs_file_t lfsFile;
extern const lfs_config lfsConfig;

// Must be called once in a thread's init() function
auto Initialize() -> void;
auto Format() -> int;
auto Mount() -> int;
auto Unmount() -> int;

// File stuff
auto OpenFile(char const * path, int flags) -> int;
auto CloseFile() -> int;
auto FileSize() -> int;
template<typename T>
auto ReadFromFile(T * t) -> int;
template<typename T>
auto WriteToFile(T const & t) -> int;

// Directory stuff
auto CreateDirectory(char const * path) -> int;

// Other stuff
auto Remove(char const * path) -> int;
auto Ls(char const * path) -> int;
// TODO: Implement cat
// TODO: Implement simple hexdump


// --- Function template definitions ---

template<typename T>
inline auto ReadFromFile(T * t) -> int
{
return lfs_file_read(&lfs, &lfsFile, t, sizeof(T));
}


template<typename T>
inline auto WriteToFile(T const & t) -> int
{
return lfs_file_write(&lfs, &lfsFile, &t, sizeof(T));
}
}
4 changes: 3 additions & 1 deletion Sts1CobcSw/Periphery/Flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ auto DeserializeFrom(Byte * source, JedecId * jedecId) -> Byte *;
writeProtectionGpioPin.Set();

constexpr auto baudrate = 1'000'000;
return spi.init(baudrate, /*slave=*/false, /*tiMode=*/false);
auto errorCode = spi.init(baudrate, /*slave=*/false, /*tiMode=*/false);

periphery::flash::Enter4ByteAdressMode();

return errorCode;
}


Expand Down
12 changes: 8 additions & 4 deletions Sts1CobcSw/Periphery/Flash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@

namespace sts1cobcsw::periphery::flash
{
[[maybe_unused]] constexpr std::size_t pageSize = 256; // bytes
[[maybe_unused]] constexpr std::size_t sectorSize = 4 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t smallBlockSize = 32 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t largeBlockSize = 64 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t pageSize = 256; // bytes
[[maybe_unused]] constexpr std::size_t sectorSize = 4 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t smallBlockSize = 32 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t largeBlockSize = 64 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t flashSize = 128 * 1024 * 1024; // bytes
[[maybe_unused]] constexpr std::size_t nSectors = flashSize / sectorSize;
[[maybe_unused]] constexpr std::size_t nSmallBlocks = flashSize / smallBlockSize;
[[maybe_unused]] constexpr std::size_t nLargeBlocks = flashSize / largeBlockSize;


using serial::Byte;
Expand Down
6 changes: 2 additions & 4 deletions Sts1CobcSw/Serial/Serial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ template<typename T>
using SerialBuffer = std::array<Byte, serialSize<T>>;


// Function declarations
// ---------------------
// --- Function declarations ---

// TODO: Rename data -> t or variable
// Must be overloaded for user-defined types to be serializable
Expand All @@ -81,8 +80,7 @@ template<typename T>
[[nodiscard]] constexpr auto Deserialize(std::span<Byte, serialSize<T>> source) -> T;


// Function template definitions
// -----------------------------
// --- Function template definitions ---

template<TriviallySerializable T>
inline constexpr auto SerializeTo(Byte * destination, T const & data) -> Byte *
Expand Down
6 changes: 6 additions & 0 deletions Tests/HardwareTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ add_subdirectory(EduCommandTests)
add_program(Crc32 Crc32.test.cpp)
target_link_libraries(Sts1CobcSwTests_Crc32 PRIVATE rodos::rodos)

add_program(FileSystem FileSystem.test.cpp)
target_link_libraries(
Sts1CobcSwTests_FileSystem PRIVATE rodos::rodos littlefs::littlefs Sts1CobcSw_FileSystem
Sts1CobcSw_Periphery
)

add_program(Flash Flash.test.cpp)
target_link_libraries(
Sts1CobcSwTests_Flash PRIVATE rodos::rodos Sts1CobcSw_Periphery Sts1CobcSw_Serial
Expand Down
Loading