M25Q driver works over QSPI.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9568 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
f8f2ea1763
commit
ec871b0ef1
|
@ -53,33 +53,33 @@
|
|||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static const uint8_t manufacturer_ids[] = M25Q_SUPPORTED_MANUFACTURE_IDS;
|
||||
static const uint8_t memory_type_ids[] = M25Q_SUPPORTED_MEMORY_TYPE_IDS;
|
||||
|
||||
static const flash_descriptor_t *get_descriptor(void *instance);
|
||||
static flash_error_t read(void *instance, flash_address_t addr,
|
||||
static const flash_descriptor_t *m25q_get_descriptor(void *instance);
|
||||
static flash_error_t m25q_read(void *instance, flash_address_t addr,
|
||||
uint8_t *rp, size_t n);
|
||||
static flash_error_t program(void *instance, flash_address_t addr,
|
||||
static flash_error_t m25q_program(void *instance, flash_address_t addr,
|
||||
const uint8_t *pp, size_t n);
|
||||
static flash_error_t start_erase_all(void *instance);
|
||||
static flash_error_t start_erase_sector(void *instance, flash_sector_t sector);
|
||||
static flash_error_t query_erase(void *instance, uint32_t *msec);
|
||||
static flash_error_t verify_erase(void *instance, flash_sector_t sector);
|
||||
static flash_error_t read_id(void *instance, uint8_t *rp, size_t n);
|
||||
static flash_error_t m25q_start_erase_all(void *instance);
|
||||
static flash_error_t m25q_start_erase_sector(void *instance,
|
||||
flash_sector_t sector);
|
||||
static flash_error_t m25q_query_erase(void *instance, uint32_t *msec);
|
||||
static flash_error_t m25q_verify_erase(void *instance, flash_sector_t sector);
|
||||
static flash_error_t m25q_read_sfdp(void *instance, uint8_t *rp,
|
||||
flash_address_t addr, size_t n);
|
||||
|
||||
/**
|
||||
* @brief Virtual methods table.
|
||||
*/
|
||||
static const struct M25QDriverVMT m25q_vmt = {
|
||||
get_descriptor, read, program,
|
||||
start_erase_all, start_erase_sector, query_erase, verify_erase,
|
||||
read_id
|
||||
m25q_get_descriptor, m25q_read, m25q_program,
|
||||
m25q_start_erase_all, m25q_start_erase_sector,
|
||||
m25q_query_erase, m25q_verify_erase,
|
||||
m25q_read_sfdp
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief N25Q128 descriptor.
|
||||
*/
|
||||
static flash_descriptor_t descriptor = {
|
||||
static flash_descriptor_t m25q_descriptor = {
|
||||
.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
|
||||
FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
|
||||
.page_size = 256U,
|
||||
|
@ -89,18 +89,18 @@ static flash_descriptor_t descriptor = {
|
|||
.address = 0U
|
||||
};
|
||||
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
/* Initial M25Q_CMD_READ_ID command.*/
|
||||
static const qspi_command_t cmd_read_id = {
|
||||
static const qspi_command_t m25q_cmd_read_id = {
|
||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_READ_ID) |
|
||||
#if M25Q_SWITCH_WIDTH == TRUE
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE,
|
||||
#else
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE,
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES,
|
||||
#else
|
||||
|
@ -113,16 +113,16 @@ static const qspi_command_t cmd_read_id = {
|
|||
};
|
||||
|
||||
/* Initial M25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER command.*/
|
||||
static const qspi_command_t cmd_write_evconf = {
|
||||
static const qspi_command_t m25q_cmd_write_evconf = {
|
||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER) |
|
||||
#if M25Q_SWITCH_WIDTH == TRUE
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE,
|
||||
#else
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE,
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES,
|
||||
#else
|
||||
|
@ -135,14 +135,14 @@ static const qspi_command_t cmd_write_evconf = {
|
|||
};
|
||||
|
||||
/* Initial M25Q_CMD_WRITE_ENABLE command.*/
|
||||
static const qspi_command_t cmd_write_enable = {
|
||||
static const qspi_command_t m25q_cmd_write_enable = {
|
||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_WRITE_ENABLE) |
|
||||
#if M25Q_SWITCH_WIDTH == TRUE
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE,
|
||||
#else
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE,
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES,
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES,
|
||||
|
@ -153,20 +153,23 @@ static const qspi_command_t cmd_write_enable = {
|
|||
};
|
||||
|
||||
/* Bus width initialization.*/
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
static const uint8_t evconf_value[1] = {0xCF};
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
static const uint8_t evconf_value[1] = {0x8F};
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
static const uint8_t m25q_evconf_value[1] = {0xCF};
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
static const uint8_t m25q_evconf_value[1] = {0x8F};
|
||||
#else
|
||||
static const uint8_t evconf_value[1] = {0x4F};
|
||||
static const uint8_t m25q_evconf_value[1] = {0x4F};
|
||||
#endif
|
||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
|
||||
static const uint8_t m25q_manufacturer_ids[] = M25Q_SUPPORTED_MANUFACTURE_IDS;
|
||||
static const uint8_t m25q_memory_type_ids[] = M25Q_SUPPORTED_MEMORY_TYPE_IDS;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static bool find_id(const uint8_t *set, size_t size, uint8_t element) {
|
||||
static bool m25q_find_id(const uint8_t *set, size_t size, uint8_t element) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
|
@ -177,282 +180,8 @@ static bool find_id(const uint8_t *set, size_t size, uint8_t element) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if ((M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) && (M25Q_SHARED_BUS == TRUE)) || \
|
||||
defined(__DOXYGEN__)
|
||||
static void flash_bus_acquire(M25QDriver *devp) {
|
||||
|
||||
qspiAcquireBus(devp->config->qspip);
|
||||
}
|
||||
|
||||
static void flash_bus_release(M25QDriver *devp) {
|
||||
|
||||
qspiReleaseBus(devp->config->qspip);
|
||||
}
|
||||
#elif (M25Q_BUS_MODE == M25Q_BUS_MODE_SPI) && (M25Q_SHARED_BUS == TRUE)
|
||||
static void flash_bus_acquire(M25QDriver *devp) {
|
||||
|
||||
spiAcquireBus(devp->config->spip);
|
||||
spiStart(devp->config->spip, devp->config->spicfg);
|
||||
}
|
||||
|
||||
static void flash_bus_release(M25QDriver *devp) {
|
||||
|
||||
spiReleaseBus(devp->config->spip);
|
||||
}
|
||||
#else
|
||||
#define flash_bus_acquire(devp)
|
||||
#define flash_bus_release(devp)
|
||||
#endif
|
||||
|
||||
static void flash_cmd(M25QDriver *devp, uint8_t cmd) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES;
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiCommand(devp->config->qspip, &mode);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
spiSend(devp->config->spip, 1, buf);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void flash_cmd_receive(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(devp->config->qspip, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
spiSend(devp->config->spip, 1, buf);
|
||||
spiReceive(devp->config->spip, n, p);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void flash_cmd_send(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
size_t n,
|
||||
const uint8_t *p) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiSend(devp->config->qspip, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
spiSend(devp->config->spip, 1, buf);
|
||||
spiSend(devp->config->spip, n, p);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void flash_cmd_addr(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiCommand(devp->config->qspip, &mode);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(devp->config->spip, 4, buf);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void flash_cmd_addr_send(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
size_t n,
|
||||
const uint8_t *p) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiSend(devp->config->qspip, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(devp->config->spip, 4, buf);
|
||||
spiSend(devp->config->spip, n, p);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void flash_cmd_addr_receive(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(devp->config->qspip, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(devp->config->spip);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(devp->config->spip, 4, buf);
|
||||
spiReceive(devp->config->spip, n, p);
|
||||
spiUnselect(devp->config->spip);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
static void flash_cmd_addr_dummy_receive(M25QDriver *devp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
uint8_t dummy,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(devp->config->qspip, &mode, n, p);
|
||||
}
|
||||
|
||||
void flash_reset_xip(M25QDriver *devp) {
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
void m25q_reset_xip(M25QDriver *devp) {
|
||||
static const uint8_t flash_conf[1] = {
|
||||
(M25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU
|
||||
};
|
||||
|
@ -464,10 +193,10 @@ void flash_reset_xip(M25QDriver *devp) {
|
|||
cmd.addr = 0;
|
||||
cmd.cfg = QSPI_CFG_CMD_MODE_NONE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES |
|
||||
#else
|
||||
|
@ -477,17 +206,17 @@ void flash_reset_xip(M25QDriver *devp) {
|
|||
QSPI_CFG_ALT_MODE_FOUR_LINES | /* Always 4 lines, note.*/
|
||||
QSPI_CFG_ALT_SIZE_8 |
|
||||
QSPI_CFG_DUMMY_CYCLES(M25Q_READ_DUMMY_CYCLES - 2);
|
||||
qspiReceive(devp->config->qspip, &cmd, 1, buf);
|
||||
qspiReceive(devp->config->busp, &cmd, 1, buf);
|
||||
|
||||
/* Enabling write operation.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
|
||||
/* Rewriting volatile configuration register.*/
|
||||
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER, 1, flash_conf);
|
||||
|
||||
jesd216_cmd_send(devp->config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||
1, flash_conf);
|
||||
}
|
||||
|
||||
void flash_reset_memory(M25QDriver *devp) {
|
||||
void m25q_reset_memory(M25QDriver *devp) {
|
||||
|
||||
/* 1x M25Q_CMD_RESET_ENABLE command.*/
|
||||
static const qspi_command_t cmd_reset_enable_1 = {
|
||||
|
@ -509,7 +238,7 @@ void flash_reset_memory(M25QDriver *devp) {
|
|||
rejected because shorter than 8 bits. If the device is in multiple
|
||||
bits mode then the commands are accepted and the device is reset to
|
||||
one bit mode.*/
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI4L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI4L
|
||||
/* 4x M25Q_CMD_RESET_ENABLE command.*/
|
||||
static const qspi_command_t cmd_reset_enable_4 = {
|
||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
||||
|
@ -526,8 +255,8 @@ void flash_reset_memory(M25QDriver *devp) {
|
|||
.alt = 0
|
||||
};
|
||||
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_4);
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_4);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_enable_4);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_memory_4);
|
||||
#else
|
||||
/* 2x M25Q_CMD_RESET_ENABLE command.*/
|
||||
static const qspi_command_t cmd_reset_enable_2 = {
|
||||
|
@ -545,18 +274,18 @@ void flash_reset_memory(M25QDriver *devp) {
|
|||
.alt = 0
|
||||
};
|
||||
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_2);
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_2);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_enable_2);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_memory_2);
|
||||
#endif
|
||||
|
||||
/* Now the device should be in one bit mode for sure and we perform a
|
||||
device reset.*/
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_1);
|
||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_1);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_enable_1);
|
||||
qspiCommand(devp->config->busp, &cmd_reset_memory_1);
|
||||
}
|
||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
|
||||
static flash_error_t flash_poll_status(M25QDriver *devp) {
|
||||
static flash_error_t m25q_poll_status(M25QDriver *devp) {
|
||||
uint8_t sts;
|
||||
|
||||
do {
|
||||
|
@ -564,13 +293,14 @@ static flash_error_t flash_poll_status(M25QDriver *devp) {
|
|||
osalThreadSleepMilliseconds(1);
|
||||
#endif
|
||||
/* Read status command.*/
|
||||
flash_cmd_receive(devp, M25Q_CMD_READ_FLAG_STATUS_REGISTER, 1, &sts);
|
||||
jesd216_cmd_receive(devp->config->busp, M25Q_CMD_READ_FLAG_STATUS_REGISTER,
|
||||
1, &sts);
|
||||
} while ((sts & M25Q_FLAGS_PROGRAM_ERASE) == 0U);
|
||||
|
||||
/* Checking for errors.*/
|
||||
if ((sts & M25Q_FLAGS_ALL_ERRORS) != 0U) {
|
||||
/* Clearing status register.*/
|
||||
flash_cmd(devp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
|
||||
|
||||
/* Program operation failed.*/
|
||||
return FLASH_ERROR_PROGRAM;
|
||||
|
@ -579,23 +309,23 @@ static flash_error_t flash_poll_status(M25QDriver *devp) {
|
|||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static const flash_descriptor_t *get_descriptor(void *instance) {
|
||||
static const flash_descriptor_t *m25q_get_descriptor(void *instance) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
|
||||
osalDbgCheck(instance != NULL);
|
||||
osalDbgAssert((devp->state != FLASH_UNINIT) && (devp->state != FLASH_STOP),
|
||||
"invalid state");
|
||||
|
||||
return &descriptor;
|
||||
return &m25q_descriptor;
|
||||
}
|
||||
|
||||
static flash_error_t read(void *instance, flash_address_t addr,
|
||||
static flash_error_t m25q_read(void *instance, flash_address_t addr,
|
||||
uint8_t *rp, size_t n) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
|
||||
osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
|
||||
osalDbgCheck((size_t)addr + n <= (size_t)descriptor.sectors_count *
|
||||
(size_t)descriptor.sectors_size);
|
||||
osalDbgCheck((size_t)addr + n <= (size_t)m25q_descriptor.sectors_count *
|
||||
(size_t)m25q_descriptor.sectors_size);
|
||||
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
|
||||
"invalid state");
|
||||
|
||||
|
@ -604,16 +334,15 @@ static flash_error_t read(void *instance, flash_address_t addr,
|
|||
}
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* FLASH_READY state while the operation is performed.*/
|
||||
devp->state = FLASH_READ;
|
||||
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
/* Fast read command in QSPI mode.*/
|
||||
flash_cmd_addr_dummy_receive(devp, M25Q_CMD_FAST_READ,
|
||||
addr, M25Q_READ_DUMMY_CYCLES,
|
||||
n, rp);
|
||||
jesd216_cmd_addr_dummy_receive(devp->config->busp, M25Q_CMD_FAST_READ,
|
||||
addr, M25Q_READ_DUMMY_CYCLES, n, rp);
|
||||
#else
|
||||
/* Normal read command in SPI mode.*/
|
||||
#endif
|
||||
|
@ -622,18 +351,18 @@ static flash_error_t read(void *instance, flash_address_t addr,
|
|||
devp->state = FLASH_READY;
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t program(void *instance, flash_address_t addr,
|
||||
static flash_error_t m25q_program(void *instance, flash_address_t addr,
|
||||
const uint8_t *pp, size_t n) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
|
||||
osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
|
||||
osalDbgCheck((size_t)addr + n <= (size_t)descriptor.sectors_count *
|
||||
(size_t)descriptor.sectors_size);
|
||||
osalDbgCheck((size_t)addr + n <= (size_t)m25q_descriptor.sectors_count *
|
||||
(size_t)m25q_descriptor.sectors_size);
|
||||
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
|
||||
"invalid state");
|
||||
|
||||
|
@ -642,7 +371,7 @@ static flash_error_t program(void *instance, flash_address_t addr,
|
|||
}
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* FLASH_PGM state while the operation is performed.*/
|
||||
devp->state = FLASH_PGM;
|
||||
|
@ -658,17 +387,18 @@ static flash_error_t program(void *instance, flash_address_t addr,
|
|||
}
|
||||
|
||||
/* Enabling write operation.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
|
||||
/* Page program command.*/
|
||||
flash_cmd_addr_send(devp, M25Q_CMD_PAGE_PROGRAM, addr, chunk, pp);
|
||||
jesd216_cmd_addr_send(devp->config->busp, M25Q_CMD_PAGE_PROGRAM, addr,
|
||||
chunk, pp);
|
||||
|
||||
/* Wait for status and check errors.*/
|
||||
err = flash_poll_status(devp);
|
||||
err = m25q_poll_status(devp);
|
||||
if (err != FLASH_NO_ERROR) {
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -683,12 +413,12 @@ static flash_error_t program(void *instance, flash_address_t addr,
|
|||
devp->state = FLASH_READY;
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t start_erase_all(void *instance) {
|
||||
static flash_error_t m25q_start_erase_all(void *instance) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
|
||||
osalDbgCheck(instance != NULL);
|
||||
|
@ -700,29 +430,30 @@ static flash_error_t start_erase_all(void *instance) {
|
|||
}
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* FLASH_ERASE state while the operation is performed.*/
|
||||
devp->state = FLASH_ERASE;
|
||||
|
||||
/* Enabling write operation.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
|
||||
/* Bulk erase command.*/
|
||||
flash_cmd(devp, M25Q_CMD_BULK_ERASE);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_BULK_ERASE);
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t start_erase_sector(void *instance, flash_sector_t sector) {
|
||||
static flash_error_t m25q_start_erase_sector(void *instance,
|
||||
flash_sector_t sector) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
flash_address_t addr = (flash_address_t)(sector * SECTOR_SIZE);
|
||||
|
||||
osalDbgCheck(instance != NULL);
|
||||
osalDbgCheck(sector < descriptor.sectors_count);
|
||||
osalDbgCheck(sector < m25q_descriptor.sectors_count);
|
||||
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
|
||||
"invalid state");
|
||||
|
||||
|
@ -731,31 +462,32 @@ static flash_error_t start_erase_sector(void *instance, flash_sector_t sector) {
|
|||
}
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* FLASH_ERASE state while the operation is performed.*/
|
||||
devp->state = FLASH_ERASE;
|
||||
|
||||
/* Enabling write operation.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
|
||||
/* Sector erase command.*/
|
||||
flash_cmd_addr(devp, M25Q_CMD_SECTOR_ERASE, addr);
|
||||
jesd216_cmd_addr(devp->config->busp, M25Q_CMD_SECTOR_ERASE, addr);
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t verify_erase(void *instance, flash_sector_t sector) {
|
||||
static flash_error_t m25q_verify_erase(void *instance,
|
||||
flash_sector_t sector) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
uint8_t cmpbuf[M25Q_COMPARE_BUFFER_SIZE];
|
||||
flash_address_t addr;
|
||||
size_t n;
|
||||
|
||||
osalDbgCheck(instance != NULL);
|
||||
osalDbgCheck(sector < descriptor.sectors_count);
|
||||
osalDbgCheck(sector < m25q_descriptor.sectors_count);
|
||||
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
|
||||
"invalid state");
|
||||
|
||||
|
@ -764,7 +496,7 @@ static flash_error_t verify_erase(void *instance, flash_sector_t sector) {
|
|||
}
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* FLASH_READY state while the operation is performed.*/
|
||||
devp->state = FLASH_READ;
|
||||
|
@ -775,8 +507,8 @@ static flash_error_t verify_erase(void *instance, flash_sector_t sector) {
|
|||
while (n > 0U) {
|
||||
uint8_t *p;
|
||||
|
||||
#if M25Q_BUS_MODE != M25Q_BUS_MODE_SPI
|
||||
flash_cmd_addr_dummy_receive(devp, M25Q_CMD_FAST_READ,
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
jesd216_cmd_addr_dummy_receive(devp->config->busp, M25Q_CMD_FAST_READ,
|
||||
addr, M25Q_READ_DUMMY_CYCLES,
|
||||
sizeof cmpbuf, cmpbuf);
|
||||
#else
|
||||
|
@ -790,7 +522,7 @@ static flash_error_t verify_erase(void *instance, flash_sector_t sector) {
|
|||
devp->state = FLASH_READY;
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_ERROR_VERIFY;
|
||||
}
|
||||
|
@ -804,12 +536,12 @@ static flash_error_t verify_erase(void *instance, flash_sector_t sector) {
|
|||
devp->state = FLASH_READY;
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t query_erase(void *instance, uint32_t *msec) {
|
||||
static flash_error_t m25q_query_erase(void *instance, uint32_t *msec) {
|
||||
M25QDriver *devp = (M25QDriver *)instance;
|
||||
uint8_t sts;
|
||||
|
||||
|
@ -821,10 +553,11 @@ static flash_error_t query_erase(void *instance, uint32_t *msec) {
|
|||
if (devp->state == FLASH_ERASE) {
|
||||
|
||||
/* Bus acquired.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* Read status command.*/
|
||||
flash_cmd_receive(devp, M25Q_CMD_READ_FLAG_STATUS_REGISTER, 1, &sts);
|
||||
jesd216_cmd_receive(devp->config->busp, M25Q_CMD_READ_FLAG_STATUS_REGISTER,
|
||||
1, &sts);
|
||||
|
||||
/* If the P/E bit is zero (busy) or the flash in a suspended state then
|
||||
report that the operation is still in progress.*/
|
||||
|
@ -832,7 +565,7 @@ static flash_error_t query_erase(void *instance, uint32_t *msec) {
|
|||
((sts & M25Q_FLAGS_ERASE_SUSPEND) != 0U)) {
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
|
||||
/* Recommended time before polling again, this is a simplified
|
||||
implementation.*/
|
||||
|
@ -850,23 +583,26 @@ static flash_error_t query_erase(void *instance, uint32_t *msec) {
|
|||
if ((sts & M25Q_FLAGS_ALL_ERRORS) != 0U) {
|
||||
|
||||
/* Clearing status register.*/
|
||||
flash_cmd(devp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
|
||||
|
||||
/* Erase operation failed.*/
|
||||
return FLASH_ERROR_ERASE;
|
||||
}
|
||||
|
||||
/* Bus released.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
}
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
static flash_error_t read_id(void *instance, uint8_t *rp, size_t n) {
|
||||
static flash_error_t m25q_read_sfdp(void *instance, uint8_t *rp,
|
||||
flash_address_t addr,
|
||||
size_t n) {
|
||||
|
||||
(void)instance;
|
||||
(void)rp;
|
||||
(void)addr;
|
||||
(void)n;
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
|
@ -892,18 +628,6 @@ void m25qObjectInit(M25QDriver *devp) {
|
|||
devp->config = NULL;
|
||||
}
|
||||
|
||||
static const qspi_command_t cmd_test_reset_enable_4 = {
|
||||
.cfg = QSPI_CFG_ALT_MODE_FOUR_LINES,
|
||||
.addr = 0,
|
||||
.alt = M25Q_CMD_RESET_ENABLE
|
||||
};
|
||||
|
||||
static const qspi_command_t cmd_test_reset_memory_4 = {
|
||||
.cfg = QSPI_CFG_ALT_MODE_FOUR_LINES,
|
||||
.addr = 0,
|
||||
.alt = M25Q_CMD_RESET_MEMORY
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configures and activates N25Q128 driver.
|
||||
*
|
||||
|
@ -922,50 +646,51 @@ void m25qStart(M25QDriver *devp, const M25QConfig *config) {
|
|||
if (devp->state == FLASH_STOP) {
|
||||
|
||||
/* Bus acquisition.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_SPI
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
|
||||
/* SPI initialization.*/
|
||||
spiStart(devp->config->spip, devp->config->spicfg);
|
||||
spiStart(devp->config->busp, devp->config->buscfg);
|
||||
|
||||
/* Reading device ID.*/
|
||||
#else /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#else /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
/* QSPI initialization.*/
|
||||
qspiStart(devp->config->qspip, devp->config->qspicfg);
|
||||
qspiStart(devp->config->busp, devp->config->buscfg);
|
||||
|
||||
/* Attempting a reset of the XIP mode, it could be in an unexpected state
|
||||
because a CPU reset does not reset the memory too.*/
|
||||
flash_reset_xip(devp);
|
||||
m25q_reset_xip(devp);
|
||||
|
||||
/* Attempting a eeset of the device, it could be in an unexpected state
|
||||
because a CPU reset does not reset the memory too.*/
|
||||
flash_reset_memory(devp);
|
||||
m25q_reset_memory(devp);
|
||||
|
||||
/* Reading device ID and unique ID.*/
|
||||
qspiReceive(devp->config->qspip, &cmd_read_id,
|
||||
qspiReceive(devp->config->busp, &m25q_cmd_read_id,
|
||||
sizeof devp->device_id, devp->device_id);
|
||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
|
||||
/* Checking if the device is white listed.*/
|
||||
osalDbgAssert(find_id(manufacturer_ids,
|
||||
sizeof manufacturer_ids,
|
||||
osalDbgAssert(m25q_find_id(m25q_manufacturer_ids,
|
||||
sizeof m25q_manufacturer_ids,
|
||||
devp->device_id[0]),
|
||||
"invalid manufacturer id");
|
||||
osalDbgAssert(find_id(memory_type_ids,
|
||||
sizeof memory_type_ids,
|
||||
osalDbgAssert(m25q_find_id(m25q_memory_type_ids,
|
||||
sizeof m25q_memory_type_ids,
|
||||
devp->device_id[1]),
|
||||
"invalid memory type id");
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) && (M25Q_SWITCH_WIDTH == TRUE)
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (M25Q_SWITCH_WIDTH == TRUE)
|
||||
/* Setting up final bus width.*/
|
||||
qspiCommand(devp->config->qspip, &cmd_write_enable);
|
||||
qspiSend(devp->config->qspip, &cmd_write_evconf, 1, evconf_value);
|
||||
qspiCommand(devp->config->busp, &m25q_cmd_write_enable);
|
||||
qspiSend(devp->config->busp, &m25q_cmd_write_evconf, 1, m25q_evconf_value);
|
||||
|
||||
{
|
||||
uint8_t id[3];
|
||||
|
||||
/* Reading ID again for confirmation.*/
|
||||
flash_cmd_receive(devp, M25Q_CMD_MULTIPLE_IO_READ_ID, 3, id);
|
||||
jesd216_cmd_receive(devp->config->busp, M25Q_CMD_MULTIPLE_IO_READ_ID,
|
||||
3, id);
|
||||
|
||||
/* Checking if the device is white listed.*/
|
||||
osalDbgAssert(memcmp(id, devp->device_id, 3) == 0,
|
||||
|
@ -974,17 +699,18 @@ void m25qStart(M25QDriver *devp, const M25QConfig *config) {
|
|||
#endif
|
||||
|
||||
/* Setting up the device size.*/
|
||||
descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) / SECTOR_SIZE;
|
||||
m25q_descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) /
|
||||
SECTOR_SIZE;
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI)
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI)
|
||||
{
|
||||
static const uint8_t flash_conf[1] = {
|
||||
(M25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU
|
||||
};
|
||||
|
||||
/* Setting up the dummy cycles to be used for fast read operations.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd_send(devp->config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||
1, flash_conf);
|
||||
}
|
||||
#endif
|
||||
|
@ -993,7 +719,7 @@ void m25qStart(M25QDriver *devp, const M25QConfig *config) {
|
|||
devp->state = FLASH_READY;
|
||||
|
||||
/* Bus release.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1012,12 +738,12 @@ void m25qStop(M25QDriver *devp) {
|
|||
if (devp->state != FLASH_STOP) {
|
||||
|
||||
/* Bus acquisition.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_SPI
|
||||
spiStop(devp->config->spip);
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
|
||||
spiStop(devp->config->busp);
|
||||
#else
|
||||
qspiStop(devp->config->qspip);
|
||||
qspiStop(devp->config->busp);
|
||||
#endif
|
||||
|
||||
devp->config = NULL;
|
||||
|
@ -1026,11 +752,11 @@ void m25qStop(M25QDriver *devp) {
|
|||
devp->state = FLASH_STOP;
|
||||
|
||||
/* Bus release.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
}
|
||||
}
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
#if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Enters the memory Mapping mode.
|
||||
|
@ -1051,21 +777,21 @@ void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
|||
qspi_command_t cmd;
|
||||
|
||||
/* Bus acquisition.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
/* Activating XIP mode in the device.*/
|
||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||
jesd216_cmd(devp->config->busp, M25Q_CMD_WRITE_ENABLE);
|
||||
jesd216_cmd_send(devp->config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||
1, flash_status_xip);
|
||||
|
||||
/* Putting the QSPI driver in memory mapped mode.*/
|
||||
cmd.cfg = QSPI_CFG_CMD(M25Q_CMD_FAST_READ) |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES |
|
||||
|
@ -1079,10 +805,10 @@ void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
|||
QSPI_CFG_SIOO |
|
||||
QSPI_CFG_DUMMY_CYCLES(M25Q_READ_DUMMY_CYCLES - 2);
|
||||
|
||||
qspiMapFlash(devp->config->qspip, &cmd, addrp);
|
||||
qspiMapFlash(devp->config->busp, &cmd, addrp);
|
||||
|
||||
/* Bus release.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1095,16 +821,16 @@ void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
|||
void m25qMemoryUnmap(M25QDriver *devp) {
|
||||
|
||||
/* Bus acquisition.*/
|
||||
flash_bus_acquire(devp);
|
||||
jesd216_bus_acquire(devp->config->busp);
|
||||
|
||||
qspiUnmapFlash(devp->config->qspip);
|
||||
qspiUnmapFlash(devp->config->busp);
|
||||
|
||||
flash_reset_xip(devp);
|
||||
m25q_reset_xip(devp);
|
||||
|
||||
/* Bus release.*/
|
||||
flash_bus_release(devp);
|
||||
jesd216_bus_release(devp->config->busp);
|
||||
}
|
||||
#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
|
||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -87,16 +87,6 @@
|
|||
M25Q_FLAGS_PROTECTION_ERROR)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Bus interface.
|
||||
* @{
|
||||
*/
|
||||
#define M25Q_BUS_MODE_SPI 0
|
||||
#define M25Q_BUS_MODE_QSPI1L 1
|
||||
#define M25Q_BUS_MODE_QSPI2L 2
|
||||
#define M25Q_BUS_MODE_QSPI4L 4
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
@ -105,13 +95,6 @@
|
|||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Physical transport interface.
|
||||
*/
|
||||
#if !defined(M25Q_USE_SPI) || defined(__DOXYGEN__)
|
||||
#define M25Q_BUS_MODE M25Q_BUS_MODE_QSPI4L
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of dummy cycles for fast read (1..15).
|
||||
* @details This is the number of dummy cycles to be used for fast read
|
||||
|
@ -133,17 +116,6 @@
|
|||
#define M25Q_SWITCH_WIDTH TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Shared bus switch.
|
||||
* @details If set to @p TRUE the device acquires bus ownership
|
||||
* on each transaction.
|
||||
* @note Requires @p SPI_USE_MUTUAL_EXCLUSION or
|
||||
* @p SPI_USE_MUTUAL_EXCLUSION.
|
||||
*/
|
||||
#if !defined(M25Q_SHARED_BUS) || defined(__DOXYGEN__)
|
||||
#define M25Q_SHARED_BUS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the flash waiting
|
||||
|
@ -191,27 +163,6 @@
|
|||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (M25Q_BUS_MODE == M25Q_BUS_MODE_SPI) && (HAL_USE_SPI == FALSE)
|
||||
#error "M25Q_BUS_MODE_SPI requires HAL_USE_SPI"
|
||||
#endif
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) && (HAL_USE_QSPI == FALSE)
|
||||
#error "M25Q_BUS_MODE_QSPIxL requires HAL_USE_QSPI"
|
||||
#endif
|
||||
|
||||
#if (M25Q_BUS_MODE == M25Q_BUS_MODE_SPI) && \
|
||||
(M25Q_SHARED_SPI == TRUE) && \
|
||||
(SPI_USE_MUTUAL_EXCLUSION == FALSE)
|
||||
#error "M25Q_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
|
||||
#endif
|
||||
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) && \
|
||||
(M25Q_BUS_MODE != M25Q_BUS_MODE_QSPI1L) && \
|
||||
(M25Q_BUS_MODE != M25Q_BUS_MODE_QSPI2L) && \
|
||||
(M25Q_BUS_MODE != M25Q_BUS_MODE_QSPI4L)
|
||||
#error "invalid M25Q_BUS_MODE selected"
|
||||
#endif
|
||||
|
||||
#if (M25Q_READ_DUMMY_CYCLES < 1) || (M25Q_READ_DUMMY_CYCLES > 15)
|
||||
#error "invalid M25Q_READ_DUMMY_CYCLES value (1..15)"
|
||||
#endif
|
||||
|
@ -228,25 +179,7 @@
|
|||
* @brief Type of a M25Q configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief QSPI driver associated to this instance.
|
||||
*/
|
||||
QSPIDriver *qspip;
|
||||
/**
|
||||
* @brief QSPI configuration associated to this instance.
|
||||
*/
|
||||
const QSPIConfig *qspicfg;
|
||||
#else
|
||||
/**
|
||||
* @brief SPI driver associated to this instance.
|
||||
*/
|
||||
SPIDriver *spip;
|
||||
/**
|
||||
* @brief SPI configuration associated to this instance.
|
||||
*/
|
||||
const SPIConfig *spicfg;
|
||||
#endif
|
||||
_jesd216_config
|
||||
} M25QConfig;
|
||||
|
||||
/**
|
||||
|
@ -299,12 +232,12 @@ extern "C" {
|
|||
void m25qObjectInit(M25QDriver *devp);
|
||||
void m25qStart(M25QDriver *devp, const M25QConfig *config);
|
||||
void m25qStop(M25QDriver *devp);
|
||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
#if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
|
||||
void m25qMemoryMap(M25QDriver *devp, uint8_t ** addrp);
|
||||
void m25qMemoryUnmap(M25QDriver *devp);
|
||||
#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
|
||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -46,4 +46,281 @@
|
|||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
void jesd216_cmd(BUSDriver *busp, uint8_t cmd) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES;
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiCommand(busp, &mode);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
spiSend(busp, 1, buf);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void jesd216_cmd_receive(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(busp, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
spiSend(busp, 1, buf);
|
||||
spiReceive(busp, n, p);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void jesd216_cmd_send(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
size_t n,
|
||||
const uint8_t *p) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
qspiSend(busp, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[1];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
spiSend(busp, 1, buf);
|
||||
spiSend(busp, n, p);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void jesd216_cmd_addr(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiCommand(busp, &mode);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(busp, 4, buf);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void jesd216_cmd_addr_send(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
size_t n,
|
||||
const uint8_t *p) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiSend(busp, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(busp, 4, buf);
|
||||
spiSend(busp, n, p);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void jesd216_cmd_addr_receive(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(busp, &mode, n, p);
|
||||
#else
|
||||
uint8_t buf[4];
|
||||
|
||||
spiSelect(busp);
|
||||
buf[0] = cmd;
|
||||
buf[1] = (uint8_t)(addr >> 16);
|
||||
buf[2] = (uint8_t)(addr >> 8);
|
||||
buf[3] = (uint8_t)(addr >> 0);
|
||||
spiSend(busp, 4, buf);
|
||||
spiReceive(busp, n, p);
|
||||
spiUnselect(busp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
void jesd216_cmd_addr_dummy_receive(BUSDriver *busp,
|
||||
uint8_t cmd,
|
||||
flash_address_t addr,
|
||||
uint8_t dummy,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
qspi_command_t mode;
|
||||
|
||||
mode.cfg = QSPI_CFG_CMD(cmd) |
|
||||
#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
|
||||
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_ONE_LINE;
|
||||
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
|
||||
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_TWO_LINES;
|
||||
#else
|
||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
QSPI_CFG_ADDR_SIZE_24 |
|
||||
QSPI_CFG_DUMMY_CYCLES(dummy) |
|
||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
||||
#endif
|
||||
mode.addr = addr;
|
||||
mode.alt = 0U;
|
||||
qspiReceive(busp, &mode, n, p);
|
||||
}
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
|
||||
#if ((JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \
|
||||
(JESD216_SHARED_BUS == TRUE)) || defined(__DOXYGEN__)
|
||||
void jesd216_bus_acquire(BUSDriver *busp) {
|
||||
|
||||
qspiAcquireBus(busp);
|
||||
}
|
||||
|
||||
void jesd216_bus_release(BUSDriver *busp) {
|
||||
|
||||
qspiReleaseBus(busp);
|
||||
}
|
||||
#elif (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
|
||||
(JESD216_SHARED_BUS == TRUE)
|
||||
static void jesd216_bus_acquire(BUSDriver *busp) {
|
||||
|
||||
spiAcquireBus(busp);
|
||||
spiStart(busp, busp->config->spicfg);
|
||||
}
|
||||
|
||||
static void jesd216_bus_release(BUSDriver *busp) {
|
||||
|
||||
spiReleaseBus(busp);
|
||||
}
|
||||
#else
|
||||
#define jesd216_bus_acquire(busp)
|
||||
#define jesd216_bus_release(busp)
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -50,25 +50,93 @@
|
|||
#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Bus interface.
|
||||
* @{
|
||||
*/
|
||||
#define JESD216_BUS_MODE_SPI 0
|
||||
#define JESD216_BUS_MODE_QSPI1L 1
|
||||
#define JESD216_BUS_MODE_QSPI2L 2
|
||||
#define JESD216_BUS_MODE_QSPI4L 4
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Physical transport interface.
|
||||
*/
|
||||
#if !defined(JESD216_USE_SPI) || defined(__DOXYGEN__)
|
||||
#define JESD216_BUS_MODE JESD216_BUS_MODE_QSPI4L
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Shared bus switch.
|
||||
* @details If set to @p TRUE the device acquires bus ownership
|
||||
* on each transaction.
|
||||
* @note Requires @p SPI_USE_MUTUAL_EXCLUSION or
|
||||
* @p SPI_USE_MUTUAL_EXCLUSION.
|
||||
*/
|
||||
#if !defined(JESD216_SHARED_BUS) || defined(__DOXYGEN__)
|
||||
#define JESD216_SHARED_BUS TRUE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && (HAL_USE_SPI == FALSE)
|
||||
#error "JESD216_BUS_MODE_SPI requires HAL_USE_SPI"
|
||||
#endif
|
||||
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (HAL_USE_QSPI == FALSE)
|
||||
#error "JESD216_BUS_MODE_QSPIxL requires HAL_USE_QSPI"
|
||||
#endif
|
||||
|
||||
#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
|
||||
(JESD216_SHARED_SPI == TRUE) && \
|
||||
(SPI_USE_MUTUAL_EXCLUSION == FALSE)
|
||||
#error "JESD216_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
|
||||
#endif
|
||||
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \
|
||||
(JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI1L) && \
|
||||
(JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI2L) && \
|
||||
(JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI4L)
|
||||
#error "invalid JESD216_BUS_MODE selected"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
|
||||
#define BUSConfig QSPIConfig
|
||||
#define BUSDriver QSPIDriver
|
||||
#else
|
||||
#define BUSConfig SPIConfig
|
||||
#define BUSDriver SPIDriver
|
||||
#endif
|
||||
|
||||
#define _jesd216_config \
|
||||
BUSDriver *busp; \
|
||||
const BUSConfig *buscfg;
|
||||
|
||||
/**
|
||||
* @brief @p JESD215Flash specific methods.
|
||||
* @note No methods so far, just a common ancestor interface.
|
||||
*/
|
||||
#define _jesd216_flash_methods_alone \
|
||||
/* Read SFDP.*/ \
|
||||
flash_error_t (*read_id)(void *instance, uint8_t *rp, size_t max);
|
||||
flash_error_t (*read_sfdp)(void *instance, uint8_t *rp, \
|
||||
flash_address_t addr, \
|
||||
size_t n);
|
||||
|
||||
/**
|
||||
* @brief @p JESD215Flash specific methods with inherited ones.
|
||||
|
@ -116,7 +184,22 @@ typedef struct {
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void jesd216_cmd(BUSDriver *busp, uint8_t cmd);
|
||||
void jesd216_cmd_receive(BUSDriver *busp, uint8_t cmd, size_t n, uint8_t *p);
|
||||
void jesd216_cmd_send(BUSDriver *busp, uint8_t cmd, size_t n, const uint8_t *p);
|
||||
void jesd216_cmd_addr(BUSDriver *busp, uint8_t cmd, flash_address_t addr);
|
||||
void jesd216_cmd_addr_send(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
|
||||
size_t n, const uint8_t *p);
|
||||
void jesd216_cmd_addr_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
|
||||
size_t n, uint8_t *p);
|
||||
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
|
||||
void jesd216_cmd_addr_dummy_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
|
||||
uint8_t dummy, size_t n, uint8_t *p);
|
||||
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
|
||||
#if JESD216_SHARED_BUS == TRUE
|
||||
void jesd216_bus_acquire(BUSDriver *busp);
|
||||
void jesd216_bus_release(BUSDriver *busp);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
* find the details in the data sheet.
|
||||
*/
|
||||
#if !defined(STM32_QSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
|
||||
#define STM32_QSPI_QUADSPI1_PRESCALER_VALUE 16
|
||||
#define STM32_QSPI_QUADSPI1_PRESCALER_VALUE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
*****************************************************************************
|
||||
|
||||
*** Next ***
|
||||
- EX: Added flash implementation for Micron M25Qxxx devices.
|
||||
- HAL: Added base flash class and JESD216 flash class.
|
||||
- HAL: Extended PLLI2S for STM32F4xx subfamily.
|
||||
- HAL: Added QSPI driver implementation for STM32.
|
||||
- HAL: Added QSPI driver model.
|
||||
|
@ -111,6 +113,7 @@
|
|||
Shell files are now located under ./os/various/shell and have a
|
||||
dedicated shell.mk file.
|
||||
- ALL: Reorganized source tree, now ports are shared between RT and NIL.
|
||||
- EX: New EX subsystem.
|
||||
- RT: Merged RT4.
|
||||
- NIL: Merged NIL2.
|
||||
- NIL: Added STM32F7 demo.
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue