File locking refactored (#631)
Remove FileMutex and wire locking into driver subsystems.
This commit is contained in:
committed by
GitHub
parent
92ca046681
commit
020aa471e2
@@ -3,6 +3,9 @@
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_sdcard.h>
|
||||
#include <tactility/drivers/esp32_sdspi.h>
|
||||
#include <tactility/drivers/spi_controller.h>
|
||||
|
||||
#include <sdmmc_cmd.h>
|
||||
|
||||
#include <soc/soc_caps.h>
|
||||
#if SOC_SDMMC_HOST_SUPPORTED
|
||||
@@ -24,4 +27,78 @@ sdmmc_card_t* esp32_sdcard_get_card(Device* device) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// No board in the tree has more than one SD-over-SPI card.
|
||||
static constexpr size_t MAX_BUS_LOCKS = 2;
|
||||
|
||||
struct SdcardBusLock {
|
||||
Device* sdcard = nullptr; // owner, for removal
|
||||
Device* controller = nullptr; // parent SPI controller
|
||||
int slot = 0; // sdspi_dev_handle_t, read back from card->host.slot
|
||||
esp_err_t (*inner)(int, sdmmc_command_t*) = nullptr;
|
||||
};
|
||||
|
||||
static SdcardBusLock bus_locks[MAX_BUS_LOCKS];
|
||||
|
||||
static SdcardBusLock* find_by_slot(int slot) {
|
||||
for (auto& entry : bus_locks) {
|
||||
if (entry.sdcard != nullptr && entry.slot == slot) {
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static esp_err_t locked_do_transaction(int slot, sdmmc_command_t* cmd) {
|
||||
const SdcardBusLock* entry = find_by_slot(slot);
|
||||
if (entry == nullptr) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
spi_controller_lock(entry->controller);
|
||||
esp_err_t result = entry->inner(slot, cmd);
|
||||
spi_controller_unlock(entry->controller);
|
||||
return result;
|
||||
}
|
||||
|
||||
error_t esp32_sdcard_install_bus_lock(Device* device, sdmmc_card_t* card) {
|
||||
auto* parent = device_get_parent(device);
|
||||
if (parent == nullptr || device_get_type(parent) != &SPI_CONTROLLER_TYPE) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
if (card == nullptr) {
|
||||
return ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
SdcardBusLock* slot_entry = nullptr;
|
||||
for (auto& entry : bus_locks) {
|
||||
if (entry.sdcard == nullptr) {
|
||||
slot_entry = &entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slot_entry == nullptr) {
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
slot_entry->sdcard = device;
|
||||
slot_entry->controller = parent;
|
||||
slot_entry->slot = card->host.slot;
|
||||
slot_entry->inner = card->host.do_transaction;
|
||||
card->host.do_transaction = locked_do_transaction;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
void esp32_sdcard_remove_bus_lock(Device* device) {
|
||||
for (auto& entry : bus_locks) {
|
||||
if (entry.sdcard == device) {
|
||||
auto* card = esp32_sdcard_get_card(device);
|
||||
if (card != nullptr) {
|
||||
card->host.do_transaction = entry.inner;
|
||||
}
|
||||
entry = SdcardBusLock{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_gpio_helpers.h>
|
||||
#include <tactility/drivers/esp32_sdcard.h>
|
||||
#include <tactility/drivers/esp32_sdspi.h>
|
||||
#include <tactility/drivers/esp32_sdspi_fs.h>
|
||||
#include <tactility/drivers/esp32_spi.h>
|
||||
@@ -92,6 +93,12 @@ static error_t start(Device* device) {
|
||||
|
||||
auto* spi_config = static_cast<const Esp32SpiConfig*>(parent->config);
|
||||
|
||||
// Card init below runs through the SD host driver's own do_transaction, which is not yet
|
||||
// patched to take the bus lock (that only happens once esp32_sdcard_install_bus_lock() runs,
|
||||
// after a successful mount) - so this whole window, from CS bit-banging through mount, needs
|
||||
// the coarse controller lock instead.
|
||||
spi_controller_lock(parent);
|
||||
|
||||
// Lower all CS pins
|
||||
esp32_spi_deselect_all_cs(parent);
|
||||
// Manually set the CS pin fo
|
||||
@@ -100,6 +107,7 @@ static error_t start(Device* device) {
|
||||
|
||||
data->fs_handle = esp32_sdspi_fs_alloc(config, spi_config->host, cs_pin_spec.pin, "/sdcard");
|
||||
if (!data->fs_handle) {
|
||||
spi_controller_unlock(parent);
|
||||
data->cleanup_pins();
|
||||
device_set_driver_data(device, nullptr);
|
||||
data->unlock();
|
||||
@@ -111,8 +119,18 @@ static error_t start(Device* device) {
|
||||
file_system_set_owner(data->file_system, device);
|
||||
if (file_system_mount(data->file_system) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to mount SD card filesystem");
|
||||
} else {
|
||||
// Pass the card straight from the just-succeeded mount, not via esp32_sdcard_get_card():
|
||||
// that getter gates on device_is_ready(), which is still false here -- device_start()
|
||||
// only flips it after this start_device callback returns. Going through the gated getter
|
||||
// silently no-ops the lock install here every time, leaving the card's do_transaction
|
||||
// unwrapped and racing the display for the device's entire lifetime.
|
||||
if (esp32_sdcard_install_bus_lock(device, esp32_sdspi_fs_get_card(data->fs_handle)) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to install SD card bus lock");
|
||||
}
|
||||
}
|
||||
|
||||
spi_controller_unlock(parent);
|
||||
data->unlock();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
@@ -130,6 +148,7 @@ static error_t stop(Device* device) {
|
||||
data->unlock();
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
esp32_sdcard_remove_bus_lock(device);
|
||||
}
|
||||
|
||||
file_system_remove(data->file_system);
|
||||
|
||||
Reference in New Issue
Block a user