openFPGALoader/src/bpiFlash.hpp

141 lines
3.6 KiB
C++
Raw Normal View History

2026-02-09 16:28:42 +01:00
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2024 openFPGALoader contributors
* BPI (Parallel NOR) Flash support via JTAG bridge
*/
#ifndef SRC_BPIFLASH_HPP_
#define SRC_BPIFLASH_HPP_
#include <cstdint>
#include <string>
#include "jtag.hpp"
/*!
* \class BPIFlash
* \brief Intel CFI parallel NOR flash programming via JTAG bridge
*/
class BPIFlash {
public:
BPIFlash(Jtag *jtag, int8_t verbose);
~BPIFlash();
/*!
* \brief Read device ID and manufacturer info
* \return true if device detected
*/
bool detect();
/*!
* \brief Read flash content
* \param[out] data: buffer to store read data
* \param[in] addr: start address (word address)
* \param[in] len: number of bytes to read
* \return true on success
*/
bool read(uint8_t *data, uint32_t addr, uint32_t len);
/*!
* \brief Write data to flash (handles erase internally)
* \param[in] addr: start address (word address)
* \param[in] data: data to write
* \param[in] len: number of bytes to write
* \return true on success
*/
bool write(uint32_t addr, const uint8_t *data, uint32_t len);
/*!
* \brief Erase a block
* \param[in] addr: address within the block to erase
* \return true on success
*/
bool erase_block(uint32_t addr);
/*!
* \brief Bulk erase entire flash
* \return true on success
*/
bool bulk_erase();
/*!
* \brief Get flash capacity in bytes
*/
uint32_t capacity() const { return _capacity; }
/*!
* \brief Get block size in bytes
*/
uint32_t block_size() const { return _block_size; }
private:
/* BPI bridge command codes (match bpiOverJtag_core.v) */
2026-02-09 17:58:24 +01:00
static const uint8_t CMD_WRITE = 0x1;
static const uint8_t CMD_READ = 0x2;
static const uint8_t CMD_NOP = 0x3;
static const uint8_t CMD_BURST_WRITE = 0x4;
2026-02-09 16:28:42 +01:00
/* Intel CFI flash commands */
static const uint16_t FLASH_CMD_READ_ARRAY = 0x00FF;
static const uint16_t FLASH_CMD_READ_ID = 0x0090;
static const uint16_t FLASH_CMD_READ_CFI = 0x0098;
static const uint16_t FLASH_CMD_READ_STATUS = 0x0070;
static const uint16_t FLASH_CMD_CLEAR_STATUS = 0x0050;
static const uint16_t FLASH_CMD_PROGRAM = 0x0041; /* Single-word program (MT28GU512AAA) */
static const uint16_t FLASH_CMD_BUFFERED_PRG = 0x00E9;
static const uint16_t FLASH_CMD_CONFIRM = 0x00D0;
static const uint16_t FLASH_CMD_BLOCK_ERASE = 0x0020;
static const uint16_t FLASH_CMD_UNLOCK_BLOCK = 0x0060;
static const uint16_t FLASH_CMD_UNLOCK_CONF = 0x00D0;
/* Status register bits */
static const uint16_t SR_READY = 0x0080;
static const uint16_t SR_ERASE_ERR = 0x0020;
static const uint16_t SR_PROG_ERR = 0x0010;
static const uint16_t SR_VPP_ERR = 0x0008;
static const uint16_t SR_BLOCK_LOCK = 0x0002;
/*!
* \brief Read a 16-bit word from flash at word address
*/
uint16_t bpi_read(uint32_t word_addr);
/*!
* \brief Write a 16-bit word to flash at word address
*/
void bpi_write(uint32_t word_addr, uint16_t data);
2026-02-09 17:58:24 +01:00
/*!
* \brief Write a 16-bit word without IR shift or flush (for batched writes)
*/
void bpi_write_no_flush(uint32_t word_addr, uint16_t data);
/*!
* \brief Burst write multiple 16-bit words in a single DR shift
*/
void bpi_burst_write(uint32_t word_addr, const uint16_t *data,
uint32_t count);
2026-02-09 16:28:42 +01:00
/*!
* \brief Wait for operation to complete
* \return true if completed successfully
*/
bool wait_ready(uint32_t timeout_ms = 10000);
/*!
* \brief Unlock a block for programming/erase
*/
bool unlock_block(uint32_t word_addr);
Jtag *_jtag;
int8_t _verbose;
int _irlen;
uint32_t _capacity;
uint32_t _block_size;
uint16_t _manufacturer_id;
uint16_t _device_id;
2026-02-09 17:58:24 +01:00
bool _has_burst;
2026-02-09 16:28:42 +01:00
};
#endif // SRC_BPIFLASH_HPP_