greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.08k stars 506 forks source link

A mutex doesn't work with dual core in a rp2040 #493

Open pedrorovi opened 1 month ago

pedrorovi commented 1 month ago

initialize@0x10015244 (Unknown Source:0) ticker_read_us@0x100153e8 (/ticker_read_us.dbgasm:4) ticker_read@0x10015408 (/ticker_read.dbgasm:3) wait_us@0x10016876 (/wait_us.dbgasm:9) mbed_die@0x10015b38 (/mbed_die.dbgasm:13) mbed_halt_system@0x10015c98 (Unknown Source:0) mbed_error@0x10015f38 (/mbed_error.dbgasm:21) trap_rtx_error@0x10012532 (Unknown Source:0) EvrRtxMutexError@0x100125f8 (/EvrRtxMutexError.dbgasm:4) osMutexAcquire@0x100114fe (/osMutexAcquire.dbgasm:11) rtos::Mutex::lock()@0x10016972 (Unknown Source:0) mbed::SPI::lock()@0x10012d8e (Unknown Source:0) mbed::SPI::select()@0x10012cf0 (Unknown Source:0) mbed::SPI::write(char const, int, char, int)@0x10012d5c (Unknown Source:0) arduino::MbedSPI::transfer@0x10005f66 (//.platformio/packages/framework-arduino-mbed/libraries/SPI/SPI.cpp:47) SdSpiArduinoDriver::receive@0x1000a66c (.pio/libdeps/pico/SdFat/src/SpiDriver/SdSpiLibDriver.h:55) SharedSpiCard::spiReceive@0x1000a66c (.pio/libdeps/pico/SdFat/src/SdCard/SdSpiCard.h:315) SharedSpiCard::readData@0x1000a66c (.pio/libdeps/pico/SdFat/src/SdCard/SdSpiCard.cpp:363) SharedSpiCard::readData@0x1000a6dc (.pio/libdeps/pico/SdFat/src/SdCard/SdSpiCard.cpp:354) DedicatedSpiCard::readSectors@0x1000aca4 (.pio/libdeps/pico/SdFat/src/SdCard/SdSpiCard.cpp:726) DedicatedSpiCard::readSector@0x1000acd4 (.pio/libdeps/pico/SdFat/src/SdCard/SdSpiCard.cpp:715)

pedrorovi commented 1 month ago

Using a custom SPI driver works:


class SPICustom {
   public:
    SPICustom() {}

    void begin(SdSpiConfig config) {
        gpio_set_function(PICO_DEFAULT_SPI_RX_PIN, GPIO_FUNC_SPI);
        gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI);
        gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI);
        gpio_set_function(PICO_DEFAULT_SPI_CSN_PIN, GPIO_FUNC_SPI);
        gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0);

        // activate();
        _spi_init(spi0, SD_MAX_INIT_RATE_KHZ);
        spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, (spi_order_t)1);
        spi_set_baudrate(spi0, config.maxSck);
    }
    void end() { spi_deinit(spi0); }

    void beginTransaction(const SPISettings spi_settings) {
        // ModeAndCpol modeAndCpol = extractModeAndCpol(spi_settings.getDataMode());
        // spi_set_format(spi0, 8, (spi_cpol_t)spi_settings.getBitOrder(), (spi_cpha_t)modeAndCpol.cpol,
        //                (spi_order_t)modeAndCpol.mode);
        spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, (spi_order_t)1);
        spi_set_baudrate(spi0, spi_settings.getClockFreq());
    }
    void endTransaction() {}
    bool isBusy() { return spi_is_busy(spi0); }
    uint8_t transfer(const uint8_t data) {
        uint8_t dst{0};
        int size = spi_write_read_blocking(spi0, &data, &dst, 1);
        return dst;
    }
};

static SPICustom spi_hal;

class MySpiClass : public SdSpiBaseClass {
   public:
    // Initialize the SPI bus.
    void begin(SdSpiConfig config) override {
        (void)config;
        spi_hal.begin(config);

        sleep_ms(1);
    }

    // Activate SPI hardware with correct speed and mode.
    void activate() override {
        while (spi_hal.isBusy()) {
        }
        // spi_hal->begin();
        spi_hal.beginTransaction(m_spiSettings);
    }

    // Deactivate SPI hardware.
    void deactivate() override {
        while (spi_hal.isBusy()) {
        }
        spi_hal.endTransaction();
        // spi_hal->end();
    }

    void end() override {
        sleep_ms(1);

        while (spi_hal.isBusy()) {
        }
        spi_hal.end();
    }

    // Receive a byte.
    uint8_t receive() override { return spi_hal.transfer(0XFF); }
    // Receive multiple bytes.
    // Replace this function if your board has multiple byte receive.
    uint8_t receive(uint8_t* buf, size_t count) override {
        for (size_t i = 0; i < count; i++) {
            buf[i] = spi_hal.transfer(0XFF);
        }
        return 0;
    }
    // Send a byte.
    void send(uint8_t data) override { spi_hal.transfer(data); }
    // Send multiple bytes.
    // Replace this function if your board has multiple byte send.
    void send(const uint8_t* buf, size_t count) override {
        for (size_t i = 0; i < count; i++) {
            spi_hal.transfer(buf[i]);
        }
    }
    // Save SPISettings for new max SCK frequency
    void setSckSpeed(uint32_t maxSck) { m_spiSettings = SPISettings(maxSck, MSBFIRST, SPI_MODE0); }

   private:
    SPISettings m_spiSettings;
};

static MySpiClass my_defined_spi;

#endif

static const uint32_t max_speed = SPI_FULL_SPEED;

#define SD_CONFIG SdSpiConfig(SPI_CS_PIN, DEDICATED_SPI, max_speed, &my_defined_spi)