AT25040 Driver
API reference
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | List of all members
at25040::Device< Spi > Class Template Reference

#include <at25040.hpp>

Public Member Functions

 Device (Spi &spi) noexcept
 
 Device (const Device &)=delete
 
Device & operator= (const Device &)=delete
 
uint8_t LastRdsr () const noexcept
 
Status ReadStatus (uint8_t &sr) noexcept
 
Status Probe () noexcept
 Double RDSR. Present if both match, not 0xFF, not the 0x05 echo, and WIP is clear.
 
Status Read (uint16_t addr, uint8_t *dst, uint16_t len) noexcept
 READ len bytes starting at addr (sequential read, any length).
 
Status WaitReady (uint32_t timeout_ms=kWriteCycleTimeoutMs) noexcept
 Poll RDSR until RDY (bit 0) reads 0: the internal write cycle has ended.
 
Status WriteEnable () noexcept
 WREN: set the write-enable latch (datasheet Table 6-1), before an instruction you send through your port. WritePage(), Write() and SetBlockProtection() send it themselves.
 
Status WriteDisable () noexcept
 WRDI: clear the write-enable latch (datasheet Table 6-1), so no WRITE or WRSR is accepted until the next WREN. Independent of the WP pin.
 
Status SetBlockProtection (BlockProtect level) noexcept
 WREN + WRSR: set BP1:BP0 (datasheet section 6, Write Status Register, Table 6-4), then wait for the write cycle: the bits are non-volatile and take tWC like a WRITE.
 
Status GetBlockProtection (BlockProtect &level) noexcept
 RDSR, decoded: the current block protection level (datasheet Table 6-4).
 
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.
 
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 cycle) per page.
 

Static Public Attributes

static constexpr uint16_t kReadChunkBytes = 16
 
static constexpr uint32_t kWriteCycleTimeoutMs = 10
 
static constexpr uint32_t kPollIntervalUs = 100
 
static constexpr uint32_t kPollsPerMsWithoutDelay = 1112
 

Constructor & Destructor Documentation

◆ Device() [1/2]

template<typename Spi >
at25040::Device< Spi >::Device ( Spi &  spi)
inlineexplicitnoexcept

◆ Device() [2/2]

template<typename Spi >
at25040::Device< Spi >::Device ( const Device< Spi > &  )
delete

Member Function Documentation

◆ GetBlockProtection()

template<typename Spi >
Status at25040::Device< Spi >::GetBlockProtection ( BlockProtect &  level)
inlinenoexcept

RDSR, decoded: the current block protection level (datasheet Table 6-4).

Returns
Status::Busy during a write cycle (the status reads 0xFF; level is not changed), Status::Timeout if the transfer failed.

◆ LastRdsr()

template<typename Spi >
uint8_t at25040::Device< Spi >::LastRdsr ( ) const
inlinenoexcept

◆ operator=()

template<typename Spi >
Device & at25040::Device< Spi >::operator= ( const Device< Spi > &  )
delete

◆ Probe()

template<typename Spi >
Status at25040::Device< Spi >::Probe ( )
inlinenoexcept

Double RDSR. Present if both match, not 0xFF, not the 0x05 echo, and WIP is clear.

◆ Read()

template<typename Spi >
Status at25040::Device< Spi >::Read ( uint16_t  addr,
uint8_t *  dst,
uint16_t  len 
)
inlinenoexcept

READ len bytes starting at addr (sequential read, any length).

The chip increments the address after every byte (datasheet 8707F, section 6, "Read Sequence"), so one READ can stream the whole array. The driver splits the request into READ transactions of at most kReadChunkBytes data bytes, so a port never sees more than 2 + kReadChunkBytes bytes, and recomputes A8 for each one.

Returns
Status::Arg for a null dst, len == 0 or a range past 0x1FF (no transfer is made; the chip would roll over to 0x000). Status::Busy if RDSR shows a write cycle in progress (the chip would ignore the READ; nothing is read). Status::Timeout if a transfer failed: the bytes of the chunks before it are in dst.

◆ ReadStatus()

template<typename Spi >
Status at25040::Device< Spi >::ReadStatus ( uint8_t &  sr)
inlinenoexcept

◆ SetBlockProtection()

template<typename Spi >
Status at25040::Device< Spi >::SetBlockProtection ( BlockProtect  level)
inlinenoexcept

WREN + WRSR: set BP1:BP0 (datasheet section 6, Write Status Register, Table 6-4), then wait for the write cycle: the bits are non-volatile and take tWC like a WRITE.

WP must be high; the chip ignores WRSR otherwise. Read the level back with GetBlockProtection() if it matters.

Returns
Status::Arg for a value outside BlockProtect, Status::Busy if a write cycle was already running, Status::Timeout if a transfer failed or the write cycle did not end in time.

◆ WaitReady()

template<typename Spi >
Status at25040::Device< Spi >::WaitReady ( uint32_t  timeout_ms = kWriteCycleTimeoutMs)
inlinenoexcept

Poll RDSR until RDY (bit 0) reads 0: the internal write cycle has ended.

The chip ignores every instruction except RDSR during a write cycle, and RDY = 1 while it runs (datasheet section 6, Write Sequence, and Table 6-3). If the port has an optional void delay_us(uint32_t us) member, the driver waits kPollIntervalUs between polls; otherwise it polls back to back, kPollsPerMsWithoutDelay times per millisecond of timeout_ms.

Parameters
timeout_msBudget; the default covers the 5 ms maximum tWC with margin.
Returns
Status::Ok when ready, Status::Timeout if a transfer failed or RDY was still 1 (also what a floating MISO, which reads 0xFF, looks like) at the end of the budget.

◆ Write()

template<typename Spi >
Status at25040::Device< Spi >::Write ( uint16_t  addr,
const uint8_t *  src,
uint16_t  len 
)
inlinenoexcept

Write any range inside the array: split at 8-byte page boundaries, one WritePage() (and one write cycle) per page.

Returns
Status::Arg for a null src, len == 0 or a range past 0x1FF (nothing is sent); otherwise the first non-Ok status of a page write (Status::Busy, Status::Timeout). Pages before it are written.

◆ WriteDisable()

template<typename Spi >
Status at25040::Device< Spi >::WriteDisable ( )
inlinenoexcept

WRDI: clear the write-enable latch (datasheet Table 6-1), so no WRITE or WRSR is accepted until the next WREN. Independent of the WP pin.

Returns
Status::Busy during a write cycle, Status::Timeout if a transfer failed.

◆ WriteEnable()

template<typename Spi >
Status at25040::Device< Spi >::WriteEnable ( )
inlinenoexcept

WREN: set the write-enable latch (datasheet Table 6-1), before an instruction you send through your port. WritePage(), Write() and SetBlockProtection() send it themselves.

Returns
Status::Busy during a write cycle (the chip would ignore it), Status::Timeout if a transfer failed.

◆ WritePage()

template<typename Spi >
Status at25040::Device< Spi >::WritePage ( uint16_t  addr,
const uint8_t *  src,
uint16_t  len 
)
inlinenoexcept

WREN + WRITE of 1 to 8 bytes inside one 8-byte page, then wait for the write cycle.

Only the three low address bits increment during a WRITE, so bytes past the end of a page would wrap to its start (datasheet section 6, Write Sequence, p. 9): a range that crosses a page is refused. Programming starts when CS goes high; the call then polls RDSR (WaitReady()) and returns when the chip is ready again, so the next call is not ignored.

Returns
Status::Arg for a null src, a length of 0 or above kPageSizeBytes, a page crossing or a range past the array (nothing is sent). Status::Busy if RDSR shows a write cycle already in progress (nothing is written). Status::Timeout if a transfer failed or the write cycle did not end within kWriteCycleTimeoutMs.

Member Data Documentation

◆ kPollIntervalUs

template<typename Spi >
constexpr uint32_t at25040::Device< Spi >::kPollIntervalUs = 100
staticconstexpr

Delay between two RDSR polls in WaitReady() when the port has delay_us().

◆ kPollsPerMsWithoutDelay

template<typename Spi >
constexpr uint32_t at25040::Device< Spi >::kPollsPerMsWithoutDelay = 1112
staticconstexpr

RDSR polls per millisecond of WaitReady() budget when the port has no delay_us(). One RDSR is 16 SCK periods plus tCS: 0.9 us at the 20 MHz maximum clock (datasheet Table 4-3), so this many polls last at least 1 ms on any legal bus; on a slower bus the wait is proportionally longer.

◆ kReadChunkBytes

template<typename Spi >
constexpr uint16_t at25040::Device< Spi >::kReadChunkBytes = 16
staticconstexpr

Data bytes per READ transaction; Read() splits longer requests into chunks of this size.

◆ kWriteCycleTimeoutMs

template<typename Spi >
constexpr uint32_t at25040::Device< Spi >::kWriteCycleTimeoutMs = 10
staticconstexpr

Default WaitReady() budget: twice the 5 ms maximum tWC (datasheet Table 4-3).


The documentation for this class was generated from the following file: