-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from SpaceTeam/cobc-fs
COBC File System
- Loading branch information
Showing
10 changed files
with
400 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.