From 839382790cfd4f5c60dda83d25c2cbd2229a3372 Mon Sep 17 00:00:00 2001 From: dario Date: Wed, 7 Feb 2024 23:50:06 +0100 Subject: [PATCH] Added first implementations --- include/sta/sensors/w25qxx.hpp | 76 ++++++++++++++++ include/sta/sensors/w25qxx_defs.hpp | 60 ++++++++++++ src/w25qxx.cpp | 136 ++++++++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 include/sta/sensors/w25qxx.hpp create mode 100644 include/sta/sensors/w25qxx_defs.hpp create mode 100644 src/w25qxx.cpp diff --git a/include/sta/sensors/w25qxx.hpp b/include/sta/sensors/w25qxx.hpp new file mode 100644 index 0000000..a22e459 --- /dev/null +++ b/include/sta/sensors/w25qxx.hpp @@ -0,0 +1,76 @@ +#ifndef STA_SENSORS_W25Q128_HPP +#define STA_SENSORS_W25Q128_HPP + +#include +#include + + +namespace sta +{ + class W25Qxx + { + public: + W25Qxx(SPIDevice * device); + + uint8_t init(); + + 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(); + + /** + * @brief Checks if the flash is write enabled. + * + * @return bool Returns true if the flash is write enabled, false otherwise. + */ + bool isWriteEnabled(); + + public: + + uint8_t readData(const uint8_t * addr, uint8_t * buffer, size_t length); + + uint8_t pageProgram(const uint8_t * addr, uint8_t * buffer, size_t length); + private: + uint8_t busWrite(uint8_t instruction, const uint8_t * data = nullptr, size_t length = 0); + + uint8_t busRead(uint8_t instruction, uint8_t * data, size_t length); + + uint8_t writeEnable(); + + uint8_t writeVolatileEnable(); + + uint8_t writeDisable(); + + SPIDevice * device_; + }; +} // namespace sta + + +#endif // STA_SENSORS_W25Q128_HPP \ No newline at end of file diff --git a/include/sta/sensors/w25qxx_defs.hpp b/include/sta/sensors/w25qxx_defs.hpp new file mode 100644 index 0000000..b647c5c --- /dev/null +++ b/include/sta/sensors/w25qxx_defs.hpp @@ -0,0 +1,60 @@ +#ifndef STA_SENSORS_W25QXX_DEFS_HPP +#define STA_SENSORS_W25QXX_DEFS_HPP + + +// W25Qxx-specific instructions +#define W25QXX_WRITE_ENABLE 0x06 +#define W25QXX_VOL_SR_WRITE_ENABLE 0x06 +#define W25QXX_WRITE_DISABLE 0x04 + +// Status register read/write instructions. +#define W25QXX_STATUS_REG_1_READ 0x05 +#define W25QXX_STATUS_REG_1_WRITE 0x01 +#define W25QXX_STATUS_REG_2_READ 0x35 +#define W25QXX_STATUS_REG_2_WRITE 0x31 +#define W25QXX_STATUS_REG_3_READ 0x15 +#define W25QXX_STATUS_REG_3_WRITE 0x11 + +// Erase memory +#define W25QXX_CHIP_ERASE 0xC7 +#define W25QXX_ERASE_SUSPEND_PROG 0x75 +#define W25QXX_ERASE_RESUME_PROG 0x7A + +// Power management +#define W25QXX_POWER_DOWN 0xB9 +#define W25QXX_RELEASE_POWER_DOWN 0xAB + +// ID reading +#define W25QXX_DEVICE_ID 0x90 +#define W25QXX_JEDEC_ID 0x9F +#define W25QXX_READ_UNIQUE_ID 0x4B + +#define W25QXX_GLOBAL_BLOCK_LOCK 0x7E +#define W25QXX_GLOBAL_BLOCK_UNLOCK 0x98 +#define W25QXX_QPI_MODE 0x38 +#define W25QXX_ENABLE_RESET 0x66 +#define W25QXX_RESET_DEVICE 0x99 + +#define W25QXX_PAGE_PROGAM 0x02 +#define W25QXX_QUAD_PAGE_PROGAM 0x32 + +#define W25QXX_SECTOR_ERASE 0x20 +#define W25QXX_BLOCK_ERASE 0xD8 + +#define W25QXX_FAST_READ 0x03 +#define W25QXX_FAST_READ_DUAL_OUT 0x3B +#define W25QXX_FAST_READ_QUAD_OUT 0x6B +#define W25QXX_SFDP_REG 0x5A + +#define W25QXX_ERASE_SEC_REG 0x44 +#define W25QXX_PROGRAM_SEC_REG 0x42 + +// Lock locking/unlocking/reading for individual blocks +#define W25QXX_INDIV_BLOCK_LOCK 0x36 +#define W25QXX_INDIV_BLOCK_UNLOCK 0x39 +#define W25QXX_READ_BLOCK_LOCK 0x3D + +#define W25QXX_FAST_READ_DUAL + + +#endif // STA_SENSORS_W25QXX_DEFS_HPP \ No newline at end of file diff --git a/src/w25qxx.cpp b/src/w25qxx.cpp new file mode 100644 index 0000000..73949b3 --- /dev/null +++ b/src/w25qxx.cpp @@ -0,0 +1,136 @@ +#include + + +namespace sta +{ + W25Qxx::W25Qxx(SPIDevice * device) + : device_{device} + { + + } + + uint8_t W25Qxx::init() + { + + + return 1; + } + + bool W25Qxx::isBusy() + { + uint8_t status = 0; + readStatusRegister(1, &status); + + return (0x01 & status) == 0x01; + } + + uint8_t + + uint8_t W25Qxx::readData(const uint8_t * addr, uint8_t * buffer, size_t length) + { + device_->beginTransmission(); + + const uint8_t instruction = W25QXX_FAST_READ; + device_->transfer(&instruction, 1); + device_->transfer(addr, 3); + device_->receive(buffer, length); + + return 1; + } + + uint8_t W25Qxx::busWrite(uint8_t instruction, const uint8_t * data /* = nullptr */, size_t length /* = 0 */) + { + return 1; + } + + uint8_t W25Qxx::busRead(uint8_t instruction, uint8_t * data, size_t length) + { + return 1; + } + + uint8_t W25Qxx::writeEnable() + { + return busWrite(W25QXX_WRITE_ENABLE); + } + + uint8_t W25Qxx::writeVolatileEnable() + { + return busWrite(W25QXX_VOL_SR_WRITE_ENABLE); + } + + uint8_t W25Qxx::writeDisable() + { + return busWrite(W25QXX_WRITE_DISABLE); + } + + uint8_t W25Qxx::readStatusRegister(uint8_t regID, uint8_t * status_byte) + { + if (regID == 1) + { + return busRead(W25QXX_STATUS_REG_1_READ, status_byte, 1); + } + + if (regID == 2) + { + return busRead(W25QXX_STATUS_REG_2_READ, status_byte, 1); + } + + if (regID == 3) + { + return busRead(W25QXX_STATUS_REG_3_READ, status_byte, 1); + } + + return 0; + } + + uint8_t W25Qxx::writeStatusRegister(uint8_t regID, uint8_t * status_byte, bool nonvolatile /* = false */) + { + if (!writeEnable()) + { + return 0; + } + + if (!nonvolatile) + { + uint8_t rslt = writeVolatileEnable(); + + if (rslt == 0) + { + return 0; + } + } + + if (regID == 1) + { + return busRead(W25QXX_STATUS_REG_1_READ, status_byte, 1); + } + + if (regID == 2) + { + return busRead(W25QXX_STATUS_REG_2_READ, status_byte, 1); + } + + if (regID == 3) + { + return busRead(W25QXX_STATUS_REG_3_READ, status_byte, 1); + } + + return 0; + } + + uint8_t W25Qxx::pageProgram(const uint8_t * addr, uint8_t * buffer, size_t length) + { + if (!writeEnable()) + { + return 0; + } + + device_->beginTransmission(); + uint8_t instruction = W25QXX_PAGE_PROGAM; + device_->transfer(&instruction, 1); + device_->transfer(buffer, length); + device_->endTransmission(); + + return 1; + } +} // namespace sta \ No newline at end of file