Merge develop into main (#304)

## New

- Read property files with `PropertiesFile`
- Support `boot.properties` so the user can specify the launcher app and an optional app to start after the launcher finishes. (see `BootProperties.cpp`)
- Create registry for CPU affinity and update code to make use of it
- `AppRegistration` and `ServiceRegistration` now also ensure that the `/data` directories always exist for all apps
- `Notes` is now the default app for opening text files. `TextViewer` is removed entirely. Created `tt::app::notes::start(path)` function.
- WiFi settings moved from NVS to properties file.
- Specify `*.ap.properties` file on the SD card for automatic WiFi settings import on start-up.
- Added `file::getLock(path)` and `file::withLock(path, function)` to do safe file operations on SD cards

## Improvements

- Update TinyUSB to `1.7.6~1`
- Improved `Boot.cpp` code. General code quality fixes and some restructuring to improve readability.
- `tt::string` functionality improvements
- Rename `AppRegistry` to `AppRegistration`
- Rename `ServiceRegistry` to `ServiceRegistration`
- Cleanup in `Notes.cpp`
- `FileTest.cpp` fix for PC
- Created `TestFile` helper class for tests, which automatically deletes files after the test.
- Renamed `Partitions.h` to `MountPoints.h`
- Created `std::string getMountPoints()` function for easy re-use
- Other code quality improvements
- `SdCardDevice`'s `getState()` and `isMounted()` now have a timeout argument

## Fixes

- ELF loading now has a lock so to avoid a bug when 2 ELF apps are loaded in parallel
This commit is contained in:
Ken Van Hoeylandt
2025-08-23 17:10:18 +02:00
committed by GitHub
parent fbaff8cbac
commit ee5a5a7181
109 changed files with 1396 additions and 744 deletions
@@ -14,7 +14,7 @@ public:
Mounted,
Unmounted,
Error,
Unknown
Timeout // Failed to retrieve state due to timeout
};
enum class MountBehaviour {
@@ -35,32 +35,28 @@ public:
virtual bool mount(const std::string& mountPath) = 0;
virtual bool unmount() = 0;
virtual State getState() const = 0;
virtual State getState(TickType_t timeout = portMAX_DELAY) const = 0;
/** Return empty string when not mounted or the mount path if mounted */
virtual std::string getMountPath() const = 0;
virtual Lock& getLock() const = 0;
/** Non-null lock */
virtual std::shared_ptr<Lock> getLock() const = 0;
virtual MountBehaviour getMountBehaviour() const { return mountBehaviour; }
bool isMounted() const { return getState() == State::Mounted; }
/** @return true if the SD card was mounted, returns false when it was not or when a timeout happened. */
bool isMounted(TickType_t timeout = portMAX_DELAY) const { return getState(timeout) == State::Mounted; }
};
/** Return the SdCard device if the path is within the SdCard mounted path (path std::string::starts_with() check)*/
std::shared_ptr<SdCardDevice> _Nullable find(const std::string& path);
/**
* Acquires an SD card lock if the path is an SD card path.
* Always calls the function, but doesn't lock if the path is not an SD card path.
* Attempt to find an SD card that the specified belongs to,
* and returns its lock if the SD card is mounted. Otherwise it returns nullptr.
* @param[in] a path on a file system (e.g. file, directory, etc.)
* @return the lock of a mounted SD card or otherwise null
*/
template<typename ReturnType>
ReturnType withSdCardLock(const std::string& path, std::function<ReturnType()> fn) {
auto sdcard = find(path);
if (sdcard != nullptr) {
auto scoped_lockable = sdcard->getLock().asScopedLock();
scoped_lockable.lock(portMAX_DELAY);
}
return fn();
}
std::shared_ptr<Lock> findSdCardLock(const std::string& path);
} // namespace tt::hal
@@ -28,7 +28,7 @@ public:
gpio_num_t spiPinWp,
gpio_num_t spiPinInt,
MountBehaviour mountBehaviourAtBoot,
/** When custom lock is nullptr, use the SPI default one */
/** When customLock is a nullptr, use the SPI default one */
std::shared_ptr<Lock> _Nullable customLock = nullptr,
std::vector<gpio_num_t> csPinWorkAround = std::vector<gpio_num_t>(),
spi_host_device_t spiHost = SPI2_HOST,
@@ -49,7 +49,7 @@ public:
gpio_num_t spiPinCd; // Card detect
gpio_num_t spiPinWp; // Write-protect
gpio_num_t spiPinInt; // Interrupt
SdCardDevice::MountBehaviour mountBehaviourAtBoot;
MountBehaviour mountBehaviourAtBoot;
std::shared_ptr<Lock> _Nullable customLock;
std::vector<gpio_num_t> csPinWorkAround;
spi_host_device_t spiHost;
@@ -74,22 +74,22 @@ public:
config(std::move(config))
{}
std::string getName() const final { return "SD Card"; }
std::string getDescription() const final { return "SD card via SPI interface"; }
std::string getName() const override { return "SD Card"; }
std::string getDescription() const override { return "SD card via SPI interface"; }
bool mount(const std::string& mountPath) final;
bool unmount() final;
std::string getMountPath() const final { return mountPath; }
bool mount(const std::string& mountPath) override;
bool unmount() override;
std::string getMountPath() const override { return mountPath; }
Lock& getLock() const final {
if (config->customLock) {
return *config->customLock;
std::shared_ptr<Lock> getLock() const override {
if (config->customLock != nullptr) {
return config->customLock;
} else {
return *spi::getLock(config->spiHost);
return spi::getLock(config->spiHost);
}
}
State getState() const override;
State getState(TickType_t timeout) const override;
sdmmc_card_t* _Nullable getCard() { return card; }
};