From a15b2398ab507c5199fba61e0f034f05d7cff793 Mon Sep 17 00:00:00 2001 From: dario Date: Tue, 4 Jun 2024 16:00:18 +0200 Subject: [PATCH] Added mutex protection and re-arranged some methods --- include/sta/drivers/w25qxx.hpp | 78 ++++++++++++++++++---------------- src/w25qxx.cpp | 29 +++++++++++-- 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/include/sta/drivers/w25qxx.hpp b/include/sta/drivers/w25qxx.hpp index 7031b7e..4682f02 100644 --- a/include/sta/drivers/w25qxx.hpp +++ b/include/sta/drivers/w25qxx.hpp @@ -78,18 +78,38 @@ namespace sta */ uint8_t init(); + /** + * @brief Checks if the flash is busy writing or erasing. + * + * @return bool Returns true if the flash is busy, false otherwise. + */ + bool isBusy(); + uint32_t getChunkBytes(ChunkSize size); + /** + * @brief + * + * @note + * + * @param criterion + * @param size + * @return uint32_t + */ + + /** * @brief Find the first memory section not satisfying a given criterion using a binary search. * - * @note This function assume that there is a page n such that every page before n satisfies the criterion, while every page after that doesn't + * @note This function assumes that there is a page n such that every page before n satisfies the criterion, while every page after that doesn't. * * @param criterion A function evaluating the criterion on a page. * @param size The size of the memory section. Has to be one of the predefined sizes. + * @param startAddr The start address of the segment to search. Defaults to the chip's start address. + * @param endAddr The end address of the segment to search. Defaults to the chip's end address. * @return uint32_t The last address such that the criterion is satisfied. */ - uint32_t findLast(std::function criterion, ChunkSize size); + uint32_t findLast(std::function criterion, ChunkSize size, uint32_t startAddr = 0, uint32_t endAddr = W25QXX_32B_MEM_SIZE); /** * @brief Set the Address Mode object @@ -150,41 +170,7 @@ namespace sta // reset device - // Extended address register read / write? - - // Enter 4-Byte address mode - - // Exit 4-Byte address mode - public: - /* - * Status registers. - */ - - /** - * @brief Read one of the flash's status registers. - * - * @param regID The ID of the status register. Can only be 1, 2 or 3. - * @param status_byte A pointer to the variable to write the state into. - * @return uint8_t Returns 1 if successful, 0 otherwise. - */ - uint8_t readStatusRegister(uint8_t regID, uint8_t * status_byte); - - /** - * @brief Write into one of the chip's status registers. - * - * @param regID The ID of the status register. Can only be 1, 2 or 3. - * @param status_byte The byte to write into the status register. - * @param nonvolatile If set to true, this setting will be restored after power off. - * @return uint8_t Returns 1 if successful, 0 otherwise. - */ - uint8_t writeStatusRegister(uint8_t regID, uint8_t * status_byte, bool nonvolatile = false); - - /** - * @brief Checks if the flash is busy writing or erasing. - * - * @return bool Returns true if the flash is busy, false otherwise. - */ - bool isBusy(); + // Extended address register read / write? public: /* * Read / Write operations @@ -319,6 +305,24 @@ namespace sta uint8_t writeVolatileEnable(); + /** + * @brief Read one of the flash's status registers. + * + * @param regID The ID of the status register. Can only be 1, 2 or 3. + * @param status_byte A pointer to the variable to write the state into. + * @return uint8_t Returns 1 if successful, 0 otherwise. + */ + uint8_t readStatusRegister(uint8_t regID, uint8_t * status_byte); + + /** + * @brief Write into one of the chip's status registers. + * + * @param regID The ID of the status register. Can only be 1, 2 or 3. + * @param status_byte The byte to write into the status register. + * @param nonvolatile If set to true, this setting will be restored after power off. + * @return uint8_t Returns 1 if successful, 0 otherwise. + */ + uint8_t writeStatusRegister(uint8_t regID, uint8_t * status_byte, bool nonvolatile = false); private: SPIDevice * device_; DelayUsFunc delay_; diff --git a/src/w25qxx.cpp b/src/w25qxx.cpp index f8654d2..1518bae 100644 --- a/src/w25qxx.cpp +++ b/src/w25qxx.cpp @@ -22,6 +22,8 @@ namespace sta uint8_t W25Qxx::init() { + lock_guard(*mutex_); + powerDown(); delay_(5); @@ -70,12 +72,15 @@ namespace sta } } - uint32_t W25Qxx::findLast(std::function criterion, ChunkSize size) + uint32_t W25Qxx::findLast(std::function criterion, ChunkSize size, uint32_t startAddr /*= 0 */, uint32_t endAddr /* = W25QXX_32B_MEM_SIZE */) { + STA_ASSERT(startAddr <= endAddr); + + lock_guard(*mutex_); uint32_t bytes = getChunkBytes(size); - uint32_t left = 0; - uint32_t right = (addrMode_ == AddressMode::_32BIT ? W25QXX_32B_MEM_SIZE : W25QXX_24B_MEM_SIZE) / bytes; + uint32_t left = startAddr / bytes; + uint32_t right = endAddr / bytes; // (addrMode_ == AddressMode::_32BIT ? W25QXX_32B_MEM_SIZE : W25QXX_24B_MEM_SIZE) / bytes; uint32_t middle; uint8_t * buffer = new uint8_t[bytes]; @@ -83,7 +88,6 @@ namespace sta while (left < right) { middle = (left + right) / 2; - STA_DEBUG_PRINTF("left=%d, middle=%d, right=%d", left, middle, right); readData(middle * bytes, buffer, bytes); if (criterion(buffer)) @@ -111,6 +115,7 @@ namespace sta uint8_t W25Qxx::setAddressMode(AddressMode addrMode) { + lock_guard(*mutex_); busWrite(W25QXX_4_BYTE_ADDR_ENABLE); while (isBusy()) {} @@ -120,6 +125,8 @@ namespace sta AddressMode W25Qxx::getAddressMode() { + lock_guard(*mutex_); + uint8_t status; readStatusRegister(3, &status); @@ -128,6 +135,8 @@ namespace sta uint8_t W25Qxx::getChipID() { + lock_guard(*mutex_); + uint8_t buffer[4]; busRead(W25QXX_RELEASE_POWER_DOWN, buffer, 3); @@ -136,6 +145,8 @@ namespace sta uint8_t W25Qxx::getManufacturerID() { + lock_guard(*mutex_); + uint8_t dummy[3] = {0, 0, 0}; uint8_t id[2] = {0, 0}; @@ -146,6 +157,8 @@ namespace sta uint64_t W25Qxx::getUniqueID() { + lock_guard(*mutex_); + uint8_t dummy[4]; uint8_t id[8]; @@ -163,6 +176,8 @@ namespace sta bool W25Qxx::isBusy() { + lock_guard(*mutex_); + uint8_t status = 0; readStatusRegister(1, &status); @@ -171,6 +186,8 @@ namespace sta uint8_t W25Qxx::readData(uint32_t address, uint8_t * buffer, size_t length, bool fast /* = true */) { + lock_guard(*mutex_); + uint8_t instruction = fast ? W25QXX_FAST_READ : W25QXX_READ; // In fast mode we have to send a 8 dummy clock cycles first. @@ -221,6 +238,8 @@ namespace sta uint8_t W25Qxx::pageProgram(uint32_t address, uint8_t * buffer, size_t length) { + lock_guard(*mutex_); + STA_ASSERT(length <= W25QXX_PAGE_SIZE); while (isBusy()) {} @@ -256,6 +275,8 @@ namespace sta uint8_t W25Qxx::sectorProgram(uint32_t address, uint8_t * buffer, size_t length) { + lock_guard(*mutex_); + STA_ASSERT(length <= W25QXX_SECTOR_SIZE); uint32_t nPages = length / W25QXX_PAGE_SIZE;