14#if __has_include("at25040_version.h")
15#include "at25040_version.h"
17#define HF_AT25040_VERSION_STRING "1.0.0"
45template <
typename Spi>
48 explicit Device(Spi& spi) noexcept : spi_(spi) {}
69 [[nodiscard]] uint8_t
LastRdsr() const noexcept {
75 uint8_t rx[2] = {0xFF, 0xFF};
76 if (!spi_.transfer(tx, rx, 2, kTimeoutMs)) {
99 if (a != b || a == 0xFFu || a ==
kCmdRdsr) {
121 Status Read(uint16_t addr, uint8_t* dst, uint16_t len)
noexcept {
126 const Status ready = CheckReady();
135 tx[1] =
static_cast<uint8_t
>(addr & 0xFFu);
136 if (!spi_.transfer(tx, rx,
static_cast<std::size_t
>(2u + n), kTimeoutMs)) {
139 for (uint16_t i = 0; i < n; ++i) {
142 addr =
static_cast<uint16_t
>(addr + n);
144 len =
static_cast<uint16_t
>(len - n);
163 const uint32_t polls = kHasDelay ? (timeout_ms * 1000u) /
kPollIntervalUs + 1u
165 for (uint32_t i = 0; i < polls; ++i) {
170 if ((sr &
kSrWip) == 0u) {
173 if constexpr (kHasDelay) {
174 if (i + 1u < polls) {
189 const Status ready = CheckReady();
199 const Status ready = CheckReady();
215 const auto bits =
static_cast<uint8_t
>(level);
219 const Status ready = CheckReady();
226 const uint8_t tx[2] = {
kCmdWrsr,
static_cast<uint8_t
>(bits << 2)};
227 uint8_t rx[2] = {0xFF, 0xFF};
228 if (!spi_.transfer(tx, rx, 2, kTimeoutMs)) {
244 if ((sr &
kSrWip) != 0u) {
268 const uint16_t page_off =
static_cast<uint16_t
>(addr %
kPageSizeBytes);
275 const Status ready = CheckReady();
285 tx[1] =
static_cast<uint8_t
>(addr & 0xFFu);
286 for (uint16_t i = 0; i < len; ++i) {
289 if (!spi_.transfer(tx, rx,
static_cast<std::size_t
>(2u + len), kTimeoutMs)) {
303 Status Write(uint16_t addr,
const uint8_t* src, uint16_t len)
noexcept {
310 const uint16_t n = len < room ? len : room;
315 addr =
static_cast<uint16_t
>(addr + n);
317 len =
static_cast<uint16_t
>(len - n);
323 static constexpr uint32_t kTimeoutMs = 20;
326 static constexpr uint8_t Opcode(uint8_t cmd, uint16_t addr)
noexcept {
327 return ((addr & 0x100u) != 0u) ?
static_cast<uint8_t
>(cmd |
kAddrA8Mask) : cmd;
334 Status CheckReady() noexcept {
343 Status SendInstruction(uint8_t cmd)
noexcept {
349 uint8_t last_rdsr_{0xFF};
#define HF_AT25040_VERSION_STRING
Definition at25040.hpp:17
AT25010/020/040B SPI EEPROM opcodes and status bits (Microchip).
CRTP SPI contract for the AT25040 driver.
Definition at25040.hpp:46
Device(Spi &spi) noexcept
Definition at25040.hpp:48
static constexpr uint32_t kPollIntervalUs
Definition at25040.hpp:60
Status WritePage(uint16_t addr, const uint8_t *src, uint16_t len) noexcept
WREN + WRITE of 1 to 8 bytes inside one 8-byte page, then wait for the write cycle.
Definition at25040.hpp:264
static constexpr uint32_t kPollsPerMsWithoutDelay
Definition at25040.hpp:67
Status WaitReady(uint32_t timeout_ms=kWriteCycleTimeoutMs) noexcept
Poll RDSR until RDY (bit 0) reads 0: the internal write cycle has ended.
Definition at25040.hpp:161
static constexpr uint32_t kWriteCycleTimeoutMs
Definition at25040.hpp:57
Status WriteEnable() noexcept
WREN: set the write-enable latch (datasheet Table 6-1), before an instruction you send through your p...
Definition at25040.hpp:188
Status ReadStatus(uint8_t &sr) noexcept
Definition at25040.hpp:73
static constexpr uint16_t kReadChunkBytes
Definition at25040.hpp:54
Status WriteDisable() noexcept
WRDI: clear the write-enable latch (datasheet Table 6-1), so no WRITE or WRSR is accepted until the n...
Definition at25040.hpp:198
Device(const Device &)=delete
Status Write(uint16_t addr, const uint8_t *src, uint16_t len) noexcept
Write any range inside the array: split at 8-byte page boundaries, one WritePage() (and one write cyc...
Definition at25040.hpp:303
Device & operator=(const Device &)=delete
Status GetBlockProtection(BlockProtect &level) noexcept
RDSR, decoded: the current block protection level (datasheet Table 6-4).
Definition at25040.hpp:239
Status Probe() noexcept
Double RDSR. Present if both match, not 0xFF, not the 0x05 echo, and WIP is clear.
Definition at25040.hpp:89
Status SetBlockProtection(BlockProtect level) noexcept
WREN + WRSR: set BP1:BP0 (datasheet section 6, Write Status Register, Table 6-4), then wait for the w...
Definition at25040.hpp:214
uint8_t LastRdsr() const noexcept
Definition at25040.hpp:69
Status Read(uint16_t addr, uint8_t *dst, uint16_t len) noexcept
READ len bytes starting at addr (sequential read, any length).
Definition at25040.hpp:121
Definition at25040.hpp:23
constexpr uint8_t kSrBp1
Definition at25040_registers.hpp:23
constexpr uint8_t kSrBp0
Definition at25040_registers.hpp:22
constexpr uint8_t kCmdWren
Definition at25040_registers.hpp:10
Status
Definition at25040.hpp:25
const char * GetAt25040DriverVersion() noexcept
Definition at25040.hpp:352
constexpr uint8_t kAddrA8Mask
Definition at25040_registers.hpp:18
constexpr uint16_t kCapacityBytes
Definition at25040_registers.hpp:26
constexpr uint8_t kSrWip
Definition at25040_registers.hpp:20
constexpr uint8_t kCmdWrdi
Definition at25040_registers.hpp:11
BlockProtect
Block write protection level, BP1:BP0 in the status register (datasheet Table 6-4).
Definition at25040.hpp:38
@ UpperQuarter
01: 0x180-0x1FF read-only
@ None
BP1:BP0 = 00: nothing protected.
@ All
11: 0x000-0x1FF read-only
@ UpperHalf
10: 0x100-0x1FF read-only
constexpr uint8_t kCmdRead
Definition at25040_registers.hpp:14
constexpr uint8_t kCmdWrite
Definition at25040_registers.hpp:15
constexpr uint16_t kPageSizeBytes
Definition at25040_registers.hpp:27
constexpr uint8_t kCmdRdsr
Definition at25040_registers.hpp:12
constexpr uint8_t kCmdWrsr
Definition at25040_registers.hpp:13
Definition at25040_spi_interface.hpp:40