76#define LockIfExists(l) int error_omitted_mutex_lock_variable[-1]
80 spiFd_ = ::open(dev_name, O_RDWR);
96 struct spi_ioc_transfer xfer[2] = {0, 0};
99 xfer[1].rx_buf = (uintptr_t)id_out;
101 xfer[1].cs_change =
true;
108 struct spi_ioc_transfer xfer[2] = {0, 0};
111 rdreq[1] = (addr >> 16) & 0xff;
112 rdreq[2] = (addr >> 8) & 0xff;
113 rdreq[3] = (addr)&0xff;
115 xfer[0].tx_buf = (uintptr_t)rdreq;
117 xfer[1].rx_buf = (uintptr_t)buf;
119 xfer[1].cs_change =
true;
122 auto db = (
const uint8_t *)buf;
123 LOG(
INFO,
"read [%x]=%02x%02x%02x%02x, %u bytes success", (
unsigned)addr,
124 db[0], db[1], db[2], db[3], len);
130 const size_t page_size = (~cfg_->pageSizeMask_) + 1;
131 const uint8_t *d = (
const uint8_t *)buf;
134 size_t len = std::min(page_size, size_bytes);
145 struct spi_ioc_transfer xfer[3] = {0, 0, 0};
148 wreq[1] = (addr >> 16) & 0xff;
149 wreq[2] = (addr >> 8) & 0xff;
150 wreq[3] = addr & 0xff;
153 xfer[0].cs_change =
true;
154 xfer[1].tx_buf = (uintptr_t)wreq;
156 xfer[2].tx_buf = (uintptr_t)d;
158 xfer[2].cs_change =
true;
163 "write [%x]=%02x%02x%02x%02x, %u bytes success after %u iter",
164 (
unsigned)addr, d[0], d[1], d[2], d[3], len, waitcount);
175 unsigned waitcount = 0;
178 struct spi_ioc_transfer sxfer = {0};
182 sxfer.tx_buf = (uintptr_t)streq;
183 sxfer.rx_buf = (uintptr_t)streq;
185 sxfer.cs_change =
true;
198 size_t end = addr + len;
201 struct spi_ioc_transfer xfer[2] = {0, 0};
204 ereq[1] = (addr >> 16) & 0xff;
205 ereq[2] = (addr >> 8) & 0xff;
206 ereq[3] = (addr)&0xff;
209 xfer[0].cs_change =
true;
210 xfer[1].tx_buf = (uintptr_t)ereq;
212 xfer[1].cs_change =
true;
217 LOG(
INFO,
"erase at %x, success after %u iter", (
unsigned)addr,
226 struct spi_ioc_transfer xfer[2] = {0, 0};
229 xfer[0].cs_change =
true;
232 xfer[1].cs_change =
true;
237 LOG(
INFO,
"chip-erase, success after %u iter", waitcount);
int ioctl(int fd, unsigned long int key,...)
Request and ioctl transaction.
Conditional OSMutexLock which can handle a nullptr as mutex (in which case it does not lock anything)...
This class provides a mutex API.
void unlock()
Unlock a mutex.
void write(uint32_t addr, const void *buf, size_t len)
Performs write to the device.
void init(const char *dev_name)
Opens the SPI bus.
void chip_erase()
Erases the entire device.
void get_id(char id_out[3])
Fetches the identification bytes form the SPIFlash.
void read(uint32_t addr, void *buf, size_t len)
Reads data from the device.
void erase(uint32_t addr, size_t len)
Erases sector(s) of the device.
OSMutex * lock_
Lock that protects accesses to the flash chip.
int spiFd_
File descriptor for the opened SPI bus.
const SPIFlashConfig * cfg_
Configuration.
unsigned wait_for_write()
Waits until write is complete.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
static const int INFO
Loglevel that is printed by default, reporting some status information.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
uint8_t statusReadCommand_
Command to use for status register read.
uint8_t chipEraseCommand_
Command to use for chip erase.
uint8_t spiMode_
SPI mode to use.
uint32_t pageSizeMask_
A page program operation might wrap around a page.
uint8_t readNeedsStuffing_
Set this to 1 if the read command needs a dummy byte after the address.
uint8_t statusWritePendingBit_
Which bit to check in the status register for write complete.
uint32_t speedHz_
Use this frequency to talk to SPI.
uint8_t writeCommand_
Command to use for writes.
uint32_t sectorSize_
How many bytes is an erase sector.
uint8_t idCommand_
Command to use for get identification bytes.
uint8_t readCommand_
Command to use for reads.
uint8_t writeEnableCommand_
Command sent out before each write/erase command.
uint8_t eraseCommand_
Command to use for sector erases.