11#include "MB85RS64V.hpp"
27 : _spi(hspi), _csPort(csPort), _csPin(csPin), _timeoutMs(timeoutMs),
28 _maxAttempts(maxAttempts == 0 ? 1 : maxAttempts) {
34void MB85RS64V::csLow() {
35 HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET);
41void MB85RS64V::csHigh() {
42 HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET);
50bool MB85RS64V::spiConfigOk()
const {
51 const SPI_InitTypeDef &i = _spi->Init;
52 const bool mode0 = (i.CLKPolarity == SPI_POLARITY_LOW) && (i.CLKPhase == SPI_PHASE_1EDGE);
53 const bool mode3 = (i.CLKPolarity == SPI_POLARITY_HIGH) && (i.CLKPhase == SPI_PHASE_2EDGE);
54 return i.Mode == SPI_MODE_MASTER && i.Direction == SPI_DIRECTION_2LINES
55 && i.DataSize == SPI_DATASIZE_8BIT && i.FirstBit == SPI_FIRSTBIT_MSB
56 && i.NSS == SPI_NSS_SOFT && (mode0 || mode3);
66bool MB85RS64V::isTransient(HAL_StatusTypeDef status)
const {
67 if (status == HAL_BUSY || status == HAL_TIMEOUT) {
70 if (status != HAL_ERROR) {
75 uint32_t transfer = 0;
76#ifdef HAL_SPI_ERROR_MODF
77 transfer |= HAL_SPI_ERROR_MODF;
79#ifdef HAL_SPI_ERROR_CRC
80 transfer |= HAL_SPI_ERROR_CRC;
82#ifdef HAL_SPI_ERROR_OVR
83 transfer |= HAL_SPI_ERROR_OVR;
85#ifdef HAL_SPI_ERROR_FRE
86 transfer |= HAL_SPI_ERROR_FRE;
88#ifdef HAL_SPI_ERROR_DMA
89 transfer |= HAL_SPI_ERROR_DMA;
91#ifdef HAL_SPI_ERROR_FLAG
92 transfer |= HAL_SPI_ERROR_FLAG;
94 return (HAL_SPI_GetError(_spi) & transfer) != 0;
104bool MB85RS64V::transmit(
const uint8_t *data, uint16_t length) {
106 _lastStatus = HAL_SPI_Transmit(_spi,
const_cast<uint8_t *
>(data), length, _timeoutMs);
107 _lastRetryable = (_lastStatus != HAL_OK) && isTransient(_lastStatus);
108 return _lastStatus == HAL_OK;
118bool MB85RS64V::receive(uint8_t *data, uint16_t length) {
119 _lastStatus = HAL_SPI_Receive(_spi, data, length, _timeoutMs);
120 _lastRetryable = (_lastStatus != HAL_OK) && isTransient(_lastStatus);
121 return _lastStatus == HAL_OK;
129bool MB85RS64V::sendCommand(uint8_t opcode) {
132 const bool ok = transmit(&opcode, 1);
147 if (!spiConfigOk()) {
154 if (
id[0] != 0x04 ||
id[1] != 0x7F ||
id[2] != 0x03 ||
id[3] != 0x02) {
170 const uint8_t op = OP_RDID;
173 const bool ok = transmit(&op, 1) && receive(
id,
ID_LENGTH);
187 if (buffer ==
nullptr || length == 0 || address >=
SIZE_BYTES || length >
static_cast<size_t>(
SIZE_BYTES - address)) {
190 const uint8_t header[3] = { OP_READ,
static_cast<uint8_t
>(address >> 8),
static_cast<uint8_t
>(address & 0xFF) };
193 const bool ok = transmit(header,
sizeof(header)) && receive(buffer,
static_cast<uint16_t
>(length));
211 if (data ==
nullptr || length == 0 || address >=
SIZE_BYTES || length >
static_cast<size_t>(
SIZE_BYTES - address)) {
214 const uint8_t header[3] = { OP_WRITE,
static_cast<uint8_t
>(address >> 8),
static_cast<uint8_t
>(address & 0xFF) };
217 uint8_t wren = OP_WREN;
219 bool ok = transmit(&wren, 1);
225 ok = transmit(header,
sizeof(header)) && transmit(data,
static_cast<uint16_t
>(length));
236 return sendCommand(OP_WREN);
244 return sendCommand(OP_WRDI);
253 if (status ==
nullptr) {
256 const uint8_t op = OP_RDSR;
259 const bool ok = transmit(&op, 1) && receive(status, 1);
272 const uint8_t frame[2] = { OP_WRSR, status };
274 uint8_t wren = OP_WREN;
276 bool ok = transmit(&wren, 1);
282 ok = transmit(frame,
sizeof(frame));
299 status =
static_cast<uint8_t
>((status & ~(
STATUS_BP1 |
STATUS_BP0)) |
static_cast<uint8_t
>(area));
bool writeDisable()
Clears the write enable latch (WRDI, 04h).
bool writeStatus(uint8_t status)
Writes the status register (WREN, then WRSR, 01h); a retry repeats both steps.
bool read(uint16_t address, uint8_t *buffer, size_t length)
Reads bytes from the FRAM array (READ, 03h).
BlockProtect
Areas of the array that the block-protect bits can lock against writes.
static constexpr uint16_t SIZE_BYTES
Capacity in bytes (8192; addresses 0x0000 to 0x1FFF).
static constexpr size_t ID_LENGTH
Number of bytes returned by readId().
bool readStatus(uint8_t *status)
Reads the status register (RDSR, 05h).
bool setBlockProtect(BlockProtect area)
Sets which part of the array the block-protect bits lock against writes, keeping the other writable s...
bool write(uint16_t address, const uint8_t *data, size_t length)
Writes bytes to the FRAM array (WREN, then WRITE, 02h); a retry repeats both steps.
static constexpr uint8_t STATUS_BP1
Block protect bit 1.
bool begin()
Checks the SPI setup and the chip's identity, and leaves writes disabled.
MB85RS64V(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, uint32_t timeoutMs=100, uint8_t maxAttempts=3)
Creates the driver object; does not touch the hardware (call begin() for that).
bool writeEnable()
Sets the write enable latch (WREN, 06h). Normally not needed; write() does it.
static constexpr uint8_t STATUS_BP0
Block protect bit 0.
bool readId(uint8_t *id)
Reads the four-byte device ID (RDID, 9Fh).