SdFat's SdSpiCard tracks SPI bus state with an unsynchronized m_spiActive bool. When two tasks call into SdFat concurrently they can confuse that state machine, ending with one task calling SPIClass::endTransaction() against a paramLock the other task holds. That trips FreeRTOS's xTaskPriorityDisinherit assert (tasks.c:5156, pxTCB == pxCurrentTCBs[0]) and panics the system. HalStorage already serialized every explicit method call via storageMutex, but HalFile's destructor was `= default`, which let the underlying SdFat FsFile destructor run close() outside any lock (DESTRUCTOR_CLOSES_FILE=1). Any task that destructed a HalFile while another task was mid-SD-op would race the unsynchronized state. Move the locking discipline into HalFile::Impl::~Impl: an explicit close() under StorageLock, then the FsFile member destructor's redundant close() is a no-op. HalFile's special members can stay = default. Switch storageMutex to xSemaphoreCreateRecursiveMutex so openFileForRead and openFileForWrite can hold the lock while assigning to a HalFile& out-param whose prior Impl needs locked teardown. Priority inheritance still applies to recursive mutexes. Also documented the no-bypass rule in CLAUDE.md: never call SdFat / SdSpiCard / FsBaseFile / SDCardManager directly, never define HAL_STORAGE_IMPL outside HalStorage.cpp. Addresses my admittedly synthetic repro for #2047 Did you use AI tools to help write this code? partial
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html