Flash working, not complete yet.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12322 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
Giovanni Di Sirio 2018-10-05 12:59:24 +00:00
parent 57a173c178
commit 6d92e3242e
6 changed files with 632 additions and 737 deletions

View File

@ -64,7 +64,7 @@ flash_descriptor_t snor_descriptor = {
/* Driver local variables and types. */
/*===========================================================================*/
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
/* Initial N25Q_CMD_READ_ID command.*/
static const wspi_command_t n25q_cmd_read_id = {
.cmd = N25Q_CMD_READ_ID,
@ -73,13 +73,13 @@ static const wspi_command_t n25q_cmd_read_id = {
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE,
#else
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES,
#else
@ -100,13 +100,13 @@ static const wspi_command_t n25q_cmd_write_evconf = {
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE,
#else
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES,
#else
@ -126,11 +126,11 @@ static const wspi_command_t n25q_cmd_write_enable = {
#if SNOR_SWITCH_WIDTH == TRUE
WSPI_CFG_CMD_MODE_ONE_LINE,
#else
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES,
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES,
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES,
@ -142,14 +142,14 @@ static const wspi_command_t n25q_cmd_write_enable = {
};
/* Bus width initialization.*/
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
static const uint8_t n25q_evconf_value[1] = {0xCF};
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
static const uint8_t n25q_evconf_value[1] = {0x8F};
#else
static const uint8_t n25q_evconf_value[1] = {0x4F};
#endif
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/*===========================================================================*/
/* Driver local functions. */
@ -174,14 +174,14 @@ static flash_error_t n25q_poll_status(SNORDriver *devp) {
osalThreadSleepMilliseconds(1);
#endif
/* Read status command.*/
jesd216_cmd_receive(devp->config->busp, N25Q_CMD_READ_FLAG_STATUS_REGISTER,
1, &sts);
bus_cmd_receive(devp->config->busp, N25Q_CMD_READ_FLAG_STATUS_REGISTER,
1, &sts);
} while ((sts & N25Q_FLAGS_PROGRAM_ERASE) == 0U);
/* Checking for errors.*/
if ((sts & N25Q_FLAGS_ALL_ERRORS) != 0U) {
/* Clearing status register.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
bus_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
/* Program operation failed.*/
return FLASH_ERROR_PROGRAM;
@ -190,7 +190,7 @@ static flash_error_t n25q_poll_status(SNORDriver *devp) {
return FLASH_NO_ERROR;
}
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
static void n25q_reset_memory(SNORDriver *devp) {
/* 1x N25Q_CMD_RESET_ENABLE command.*/
@ -215,7 +215,7 @@ static void n25q_reset_memory(SNORDriver *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 JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
/* 4x N25Q_CMD_RESET_ENABLE command.*/
static const wspi_command_t cmd_reset_enable_4 = {
.cmd = N25Q_CMD_RESET_ENABLE,
@ -264,7 +264,7 @@ static void n25q_reset_memory(SNORDriver *devp) {
wspiCommand(devp->config->busp, &cmd_reset_enable_1);
wspiCommand(devp->config->busp, &cmd_reset_memory_1);
}
#endif /* #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* #if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
static const uint8_t n25q_manufacturer_ids[] = N25Q_SUPPORTED_MANUFACTURE_IDS;
static const uint8_t n25q_memory_type_ids[] = N25Q_SUPPORTED_MEMORY_TYPE_IDS;
@ -275,12 +275,12 @@ static const uint8_t n25q_memory_type_ids[] = N25Q_SUPPORTED_MEMORY_TYPE_IDS;
void snor_device_init(SNORDriver *devp) {
#if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
#if SNOR_BUS_MODE == SNOR_BUS_MODE_SPI
/* Reading device ID.*/
jesd216_cmd_receive(devp->config->busp, N25Q_CMD_READ_ID,
sizeof devp->device_id, devp->device_id);
bus_cmd_receive(devp->config->busp, N25Q_CMD_READ_ID,
sizeof devp->device_id, devp->device_id);
#else /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#else /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/* Attempting a reset of the XIP mode, it could be in an unexpected state
because a CPU reset does not reset the memory too.*/
snor_reset_xip(devp);
@ -292,7 +292,7 @@ void snor_device_init(SNORDriver *devp) {
/* Reading device ID and unique ID.*/
wspiReceive(devp->config->busp, &n25q_cmd_read_id,
sizeof devp->device_id, devp->device_id);
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/* Checking if the device is white listed.*/
osalDbgAssert(n25q_find_id(n25q_manufacturer_ids,
@ -304,7 +304,7 @@ void snor_device_init(SNORDriver *devp) {
devp->device_id[1]),
"invalid memory type id");
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (SNOR_SWITCH_WIDTH == TRUE)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) && (SNOR_SWITCH_WIDTH == TRUE)
/* Setting up final bus width.*/
wspiCommand(devp->config->busp, &n25q_cmd_write_enable);
wspiSend(devp->config->busp, &n25q_cmd_write_evconf, 1, n25q_evconf_value);
@ -313,8 +313,7 @@ void snor_device_init(SNORDriver *devp) {
uint8_t id[3];
/* Reading ID again for confirmation.*/
jesd216_cmd_receive(devp->config->busp, N25Q_CMD_MULTIPLE_IO_READ_ID,
3, id);
bus_cmd_receive(devp->config->busp, N25Q_CMD_MULTIPLE_IO_READ_ID, 3, id);
/* Checking if the device is white listed.*/
osalDbgAssert(memcmp(id, devp->device_id, 3) == 0,
@ -326,16 +325,16 @@ void snor_device_init(SNORDriver *devp) {
snor_descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) /
SECTOR_SIZE;
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI)
{
static const uint8_t flash_conf[1] = {
(SNOR_READ_DUMMY_CYCLES << 4U) | 0x0FU
};
/* Setting up the dummy cycles to be used for fast read operations.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
jesd216_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_conf);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_conf);
}
#endif
}
@ -353,14 +352,14 @@ const flash_descriptor_t *snor_get_descriptor(void *instance) {
flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
size_t n, uint8_t *rp) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
/* Fast read command in WSPI mode.*/
jesd216_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
offset, SNOR_READ_DUMMY_CYCLES, n, rp);
bus_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
offset, SNOR_READ_DUMMY_CYCLES, n, rp);
#else
/* Normal read command in SPI mode.*/
jesd216_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
offset, n, rp);
bus_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
offset, n, rp);
#endif
return FLASH_NO_ERROR;
@ -380,19 +379,16 @@ flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
}
/* Enabling write operation.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
/* Page program command.*/
jesd216_cmd_addr_send(devp->config->busp, N25Q_CMD_PAGE_PROGRAM, offset,
chunk, pp);
bus_cmd_addr_send(devp->config->busp, N25Q_CMD_PAGE_PROGRAM, offset,
chunk, pp);
/* Wait for status and check errors.*/
err = n25q_poll_status(devp);
if (err != FLASH_NO_ERROR) {
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
return err;
}
@ -408,10 +404,10 @@ flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
flash_error_t snor_device_start_erase_all(SNORDriver *devp) {
/* Enabling write operation.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
/* Bulk erase command.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_BULK_ERASE);
bus_cmd(devp->config->busp, N25Q_CMD_BULK_ERASE);
return FLASH_NO_ERROR;
}
@ -421,10 +417,10 @@ flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
flash_offset_t offset = (flash_offset_t)(sector * SECTOR_SIZE);
/* Enabling write operation.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
/* Sector erase command.*/
jesd216_cmd_addr(devp->config->busp, N25Q_CMD_SECTOR_ERASE, offset);
bus_cmd_addr(devp->config->busp, N25Q_CMD_SECTOR_ERASE, offset);
return FLASH_NO_ERROR;
}
@ -441,14 +437,14 @@ flash_error_t snor_device_verify_erase(SNORDriver *devp,
while (n > 0U) {
uint8_t *p;
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
jesd216_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
offset, SNOR_READ_DUMMY_CYCLES,
sizeof cmpbuf, cmpbuf);
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
bus_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
offset, SNOR_READ_DUMMY_CYCLES,
sizeof cmpbuf, cmpbuf);
#else
/* Normal read command in SPI mode.*/
jesd216_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
offset, sizeof cmpbuf, cmpbuf);
bus_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
offset, sizeof cmpbuf, cmpbuf);
#endif
/* Checking for erased state of current buffer.*/
@ -472,8 +468,8 @@ flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
uint8_t sts;
/* Read status command.*/
jesd216_cmd_receive(devp->config->busp, N25Q_CMD_READ_FLAG_STATUS_REGISTER,
1, &sts);
bus_cmd_receive(devp->config->busp, N25Q_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.*/
@ -493,7 +489,7 @@ flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
if ((sts & N25Q_FLAGS_ALL_ERRORS) != 0U) {
/* Clearing status register.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
bus_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
/* Erase operation failed.*/
return FLASH_ERROR_ERASE;
@ -513,16 +509,16 @@ flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
return FLASH_NO_ERROR;
}
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
void snor_activate_xip(SNORDriver *devp) {
static const uint8_t flash_status_xip[1] = {
(SNOR_READ_DUMMY_CYCLES << 4U) | 0x07U
};
/* Activating XIP mode in the device.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
jesd216_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_status_xip);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_status_xip);
}
void snor_reset_xip(SNORDriver *devp) {
@ -538,13 +534,13 @@ void snor_reset_xip(SNORDriver *devp) {
cmd.dummy = SNOR_READ_DUMMY_CYCLES - 2;
cmd.cfg = WSPI_CFG_CMD_MODE_NONE |
WSPI_CFG_ADDR_SIZE_24 |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE |
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES |
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES |
#else
@ -556,12 +552,12 @@ void snor_reset_xip(SNORDriver *devp) {
wspiReceive(devp->config->busp, &cmd, 1, buf);
/* Enabling write operation.*/
jesd216_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
/* Rewriting volatile configuration register.*/
jesd216_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_conf);
bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
1, flash_conf);
}
#endif /* #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/** @} */

View File

@ -1,6 +1,5 @@
# List of all the Micron N25Q device files.
N25QSRC := $(CHIBIOS)/os/hal/lib/peripherals/flash/hal_flash.c \
$(CHIBIOS)/os/hal/lib/complex/serial_nor/hal_jesd216_flash.c \
$(CHIBIOS)/os/hal/lib/complex/serial_nor/serial_nor.c \
$(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/micron_n25q/flash_device.c

View File

@ -1,402 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_jesd216_flash.c
* @brief JESD216 compliant flash driver class code.
*
* @addtogroup HAL_JESD216_FLASH
* @{
*/
#include "hal.h"
#include "hal_jesd216_flash.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void jesd216_start(BUSDriver *busp, const BUSConfig *config) {
#if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
spiStart(busp, config);
#else
wspiStart(busp, config);
#endif
}
void jesd216_stop(BUSDriver *busp) {
#if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI
spiStop(busp);
#else
wspiStop(busp);
#endif
}
void jesd216_cmd(BUSDriver *busp, uint32_t cmd) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiCommand(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,
uint32_t cmd,
size_t n,
uint8_t *p) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiReceive(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,
uint32_t cmd,
size_t n,
const uint8_t *p) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiSend(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,
uint32_t cmd,
flash_offset_t offset) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_ADDR_SIZE_24;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_ADDR_SIZE_24;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_ADDR_SIZE_24;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_SIZE_24;
#endif
mode.addr = offset;
mode.alt = 0U;
wspiCommand(busp, &mode);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 0);
spiSend(busp, 4, buf);
spiUnselect(busp);
#endif
}
void jesd216_cmd_addr_send(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
const uint8_t *p) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
mode.cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode.cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiSend(busp, &mode, n, p);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 0);
spiSend(busp, 4, buf);
spiSend(busp, n, p);
spiUnselect(busp);
#endif
}
void jesd216_cmd_addr_receive(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
uint8_t *p) {
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
mode .cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode .cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiReceive(busp, &mode, n, p);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 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,
uint32_t cmd,
flash_offset_t offset,
uint32_t dummy,
size_t n,
uint8_t *p) {
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = dummy;
mode.cfg = 0U |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & JESD216_CMD_EXTENDED_ADDRESSING) == 0) {
mode .cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode .cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiReceive(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, const BUSConfig *config) {
(void)config;
wspiAcquireBus(busp);
if (busp->config != config) {
wspiStart(busp, config);
}
}
void jesd216_bus_release(BUSDriver *busp) {
wspiReleaseBus(busp);
}
#elif (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
(JESD216_SHARED_BUS == TRUE)
void jesd216_bus_acquire(BUSDriver *busp, const BUSConfig *config) {
spiAcquireBus(busp);
if (busp->config != config) {
spiStart(busp, config);
}
}
void jesd216_bus_release(BUSDriver *busp) {
spiReleaseBus(busp);
}
#else
#define jesd216_bus_acquire(busp)
#define jesd216_bus_release(busp)
#endif
/** @} */

View File

@ -1,223 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_jesd216_flash.h
* @brief JESD216 compliant flash driver class header.
*
* @addtogroup HAL_JESD216_FLASH
* @{
*/
#ifndef HAL_JESD216_FLASH_H
#define HAL_JESD216_FLASH_H
#include "hal_flash.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Common command codes
* @{
*/
#define JESD216_CMD_READ_ID 0x9FU
#define JESD216_CMD_READ 0x03U
#define JESD216_CMD_WRITE_ENABLE 0x06U
#define JESD216_CMD_WRITE_DISABLE 0x04U
#define JESD216_CMD_READ_STATUS_REGISTER 0x05U
#define JESD216_CMD_WRITE_STATUS_REGISTER 0x01U
#define JESD216_CMD_PAGE_PROGRAM 0x02U
#define JESD216_CMD_ERASE_4K 0x20U
#define JESD216_CMD_ERASE_BULK 0xC7U
#define JESD216_CMD_PROGRAM_ERASE_RESUME 0x7AU
#define JESD216_CMD_PROGRAM_ERASE_SUSPEND 0x75U
#define JESD216_CMD_READ_OTP_ARRAY 0x4BU
#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42U
/** @} */
/**
* @name Command options
* @{
*/
#define JESD216_CMD_EXTENDED_ADDRESSING 0x80000000U
/** @} */
/**
* @name Bus interface.
* @{
*/
#define JESD216_BUS_MODE_SPI 0U
#define JESD216_BUS_MODE_WSPI1L 1U
#define JESD216_BUS_MODE_WSPI2L 2U
#define JESD216_BUS_MODE_WSPI4L 4U
#define JESD216_BUS_MODE_WSPI8L 8U
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief Physical transport interface.
*/
#if !defined(JESD216_BUS_MODE) || defined(__DOXYGEN__)
#define JESD216_BUS_MODE JESD216_BUS_MODE_WSPI4L
#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_WSPI == FALSE)
#error "JESD216_BUS_MODE_WSPIxL requires HAL_USE_WSPI"
#endif
#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
(JESD216_SHARED_BUS == 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_WSPI1L) && \
(JESD216_BUS_MODE != JESD216_BUS_MODE_WSPI2L) && \
(JESD216_BUS_MODE != JESD216_BUS_MODE_WSPI4L) && \
(JESD216_BUS_MODE != JESD216_BUS_MODE_WSPI8L)
#error "invalid JESD216_BUS_MODE selected"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
#define BUSConfig WSPIConfig
#define BUSDriver WSPIDriver
#else
#define BUSConfig SPIConfig
#define BUSDriver SPIDriver
#endif
#define _jesd216_config \
BUSDriver *busp; \
const BUSConfig *buscfg;
/**
* @brief @p JESD215Flash specific methods.
*/
#define _jesd216_flash_methods_alone \
/* Read SFDP.*/ \
flash_error_t (*read_sfdp)(void *instance, \
flash_offset_t offset, \
size_t n, \
uint8_t *rp);
/**
* @brief @p JESD215Flash specific methods with inherited ones.
*/
#define _jesd216_flash_methods \
_base_flash_methods \
_jesd216_flash_methods_alone
/**
* @brief @p JESD215Flash virtual methods table.
*/
struct JESD215FlashVMT {
_jesd216_flash_methods
};
/**
* @brief @p JESD215Flash specific data.
*/
#define _jesd216_flash_data \
_base_flash_data
/**
* @brief Base flash class.
*/
typedef struct {
/** @brief Virtual Methods Table.*/
const struct JESD215FlashVMT *vmt;
_jesd216_flash_data
} JESD215Flash;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @name Macro Functions (BaseFlash)
* @{
*/
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void jesd216_start(BUSDriver *busp, const BUSConfig *config);
void jesd216_stop(BUSDriver *busp);
void jesd216_cmd(BUSDriver *busp, uint32_t cmd);
void jesd216_cmd_receive(BUSDriver *busp, uint32_t cmd,
size_t n, uint8_t *p);
void jesd216_cmd_send(BUSDriver *busp, uint32_t cmd,
size_t n, const uint8_t *p);
void jesd216_cmd_addr(BUSDriver *busp, uint32_t cmd, flash_offset_t offset);
void jesd216_cmd_addr_send(BUSDriver *busp, uint32_t cmd,
flash_offset_t offset, size_t n, const uint8_t *p);
void jesd216_cmd_addr_receive(BUSDriver *busp, uint32_t cmd,
flash_offset_t offset, size_t n, uint8_t *p);
#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
void jesd216_cmd_addr_dummy_receive(BUSDriver *busp, uint32_t cmd,
flash_offset_t offset, uint32_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, const BUSConfig *config);
void jesd216_bus_release(BUSDriver *busp);
#endif
#ifdef __cplusplus
}
#endif
#endif /* HAL_JESD216_FLASH_H */
/** @} */

View File

@ -66,6 +66,56 @@ static const struct SNORDriverVMT snor_vmt = {
/* Driver local functions. */
/*===========================================================================*/
#if ((SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) && \
(SNOR_SHARED_BUS == TRUE)) || defined(__DOXYGEN__)
/**
* @brief Bus acquisition and lock.
*
* @param[in] busp pointer to the bus driver
* @param[in] config bus configuration
*
* @notapi
*/
static void bus_acquire(BUSDriver *busp, const BUSConfig *config) {
(void)config;
wspiAcquireBus(busp);
if (busp->config != config) {
wspiStart(busp, config);
}
}
/**
* @brief Bus release.
*
* @param[in] busp pointer to the bus driver
*
* @notapi
*/
static void bus_release(BUSDriver *busp) {
wspiReleaseBus(busp);
}
#elif (SNOR_BUS_MODE == SNOR_BUS_MODE_SPI) && \
(SNOR_SHARED_BUS == TRUE)
void bus_acquire(BUSDriver *busp, const BUSConfig *config) {
spiAcquireBus(busp);
if (busp->config != config) {
spiStart(busp, config);
}
}
void bus_release(BUSDriver *busp) {
spiReleaseBus(busp);
}
#else
#define bus_acquire(busp)
#define bus_release(busp)
#endif
static flash_error_t snor_read(void *instance, flash_offset_t offset,
size_t n, uint8_t *rp) {
SNORDriver *devp = (SNORDriver *)instance;
@ -82,7 +132,7 @@ static flash_error_t snor_read(void *instance, flash_offset_t offset,
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* FLASH_READY state while the operation is performed.*/
devp->state = FLASH_READ;
@ -94,7 +144,7 @@ static flash_error_t snor_read(void *instance, flash_offset_t offset,
devp->state = FLASH_READY;
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -115,7 +165,7 @@ static flash_error_t snor_program(void *instance, flash_offset_t offset,
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* FLASH_PGM state while the operation is performed.*/
devp->state = FLASH_PGM;
@ -127,7 +177,7 @@ static flash_error_t snor_program(void *instance, flash_offset_t offset,
devp->state = FLASH_READY;
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -145,7 +195,7 @@ static flash_error_t snor_start_erase_all(void *instance) {
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* FLASH_ERASE state while the operation is performed.*/
devp->state = FLASH_ERASE;
@ -157,7 +207,7 @@ static flash_error_t snor_start_erase_all(void *instance) {
devp->state = FLASH_READY;
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -177,7 +227,7 @@ static flash_error_t snor_start_erase_sector(void *instance,
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* FLASH_ERASE state while the operation is performed.*/
devp->state = FLASH_ERASE;
@ -186,7 +236,7 @@ static flash_error_t snor_start_erase_sector(void *instance,
err = snor_device_start_erase_sector(devp, sector);
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -206,7 +256,7 @@ static flash_error_t snor_verify_erase(void *instance,
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* FLASH_READY state while the operation is performed.*/
devp->state = FLASH_READ;
@ -218,7 +268,7 @@ static flash_error_t snor_verify_erase(void *instance,
devp->state = FLASH_READY;
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -235,7 +285,7 @@ static flash_error_t snor_query_erase(void *instance, uint32_t *msec) {
if (devp->state == FLASH_ERASE) {
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Actual query erase implementation.*/
err = snor_device_query_erase(devp, msec);
@ -246,7 +296,7 @@ static flash_error_t snor_query_erase(void *instance, uint32_t *msec) {
}
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
}
else {
err = FLASH_NO_ERROR;
@ -269,7 +319,7 @@ static flash_error_t snor_read_sfdp(void *instance, flash_offset_t offset,
}
/* Bus acquired.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Actual read SFDP implementation.*/
err = snor_device_read_sfdp(devp, offset, n, rp);
@ -280,7 +330,7 @@ static flash_error_t snor_read_sfdp(void *instance, flash_offset_t offset,
}
/* Bus released.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
return err;
}
@ -289,6 +339,401 @@ static flash_error_t snor_read_sfdp(void *instance, flash_offset_t offset,
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Stops the underlying bus driver.
*
* @param[in] busp pointer to the bus driver
*
* @notapi
*/
void bus_stop(BUSDriver *busp) {
#if SNOR_BUS_MODE == SNOR_BUS_MODE_SPI
spiStop(busp);
#else
wspiStop(busp);
#endif
}
/**
* @brief Sends a naked command.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
*
* @notapi
*/
void bus_cmd(BUSDriver *busp, uint32_t cmd) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiCommand(busp, &mode);
#else
uint8_t buf[1];
spiSelect(busp);
buf[0] = cmd;
spiSend(busp, 1, buf);
spiUnselect(busp);
#endif
}
/**
* @brief Sends a command followed by a data transmit phase.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] n number of bytes to receive
* @param[in] p data buffer
*
* @notapi
*/
void bus_cmd_send(BUSDriver *busp, uint32_t cmd, size_t n, const uint8_t *p) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiSend(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
}
/**
* @brief Sends a command followed by a data receive phase.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] n number of bytes to receive
* @param[out] p data buffer
*
* @notapi
*/
void bus_cmd_receive(BUSDriver *busp,
uint32_t cmd,
size_t n,
uint8_t *p) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
mode.addr = 0U;
mode.alt = 0U;
wspiReceive(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
}
/**
* @brief Sends a command followed by a flash address.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] offset flash offset
*
* @notapi
*/
void bus_cmd_addr(BUSDriver *busp, uint32_t cmd, flash_offset_t offset) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_ADDR_SIZE_24;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_ADDR_SIZE_24;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_ADDR_SIZE_24;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_SIZE_24;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & SNOR_BUS_CMD_EXTENDED_ADDRESSING) == 0) {
mode.cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode.cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiCommand(busp, &mode);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 0);
spiSend(busp, 4, buf);
spiUnselect(busp);
#endif
}
/**
* @brief Sends a command followed by a flash address and a data transmit
* phase.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] offset flash offset
* @param[in] n number of bytes to receive
* @param[in] p data buffer
*
* @notapi
*/
void bus_cmd_addr_send(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
const uint8_t *p) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & SNOR_BUS_CMD_EXTENDED_ADDRESSING) == 0) {
mode.cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode.cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiSend(busp, &mode, n, p);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 0);
spiSend(busp, 4, buf);
spiSend(busp, n, p);
spiUnselect(busp);
#endif
}
/**
* @brief Sends a command followed by a flash address and a data receive
* phase.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] offset flash offset
* @param[in] n number of bytes to receive
* @param[out] p data buffer
*
* @notapi
*/
void bus_cmd_addr_receive(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
uint8_t *p) {
#if SNOR_BUS_MODE != SNOR_BUS_MODE_SPI
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = 0U;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & SNOR_BUS_CMD_EXTENDED_ADDRESSING) == 0) {
mode .cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode .cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiReceive(busp, &mode, n, p);
#else
uint8_t buf[4];
spiSelect(busp);
buf[0] = cmd;
buf[1] = (uint8_t)(offset >> 16);
buf[2] = (uint8_t)(offset >> 8);
buf[3] = (uint8_t)(offset >> 0);
spiSend(busp, 4, buf);
spiReceive(busp, n, p);
spiUnselect(busp);
#endif
}
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
/**
* @brief Sends a command followed by a flash address, dummy cycles and a
* data receive phase.
*
* @param[in] busp pointer to the bus driver
* @param[in] cmd instruction code
* @param[in] offset flash offset
* @param[in] dummy number of dummy cycles
* @param[in] n number of bytes to receive
* @param[out] p data buffer
*
* @notapi
*/
void bus_cmd_addr_dummy_receive(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
uint32_t dummy,
size_t n,
uint8_t *p) {
wspi_command_t mode;
mode.cmd = cmd;
mode.dummy = dummy;
mode.cfg = 0U |
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES;
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI4L
WSPI_CFG_CMD_MODE_FOUR_LINES |
WSPI_CFG_ADDR_MODE_FOUR_LINES |
WSPI_CFG_DATA_MODE_FOUR_LINES;
#else
WSPI_CFG_CMD_MODE_EIGHT_LINES |
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
WSPI_CFG_DATA_MODE_EIGHT_LINES;
#endif
/* Handling 32 bits addressing.
TODO: Address size should come from upper levels.*/
if ((cmd & SNOR_BUS_CMD_EXTENDED_ADDRESSING) == 0) {
mode .cfg |= WSPI_CFG_ADDR_SIZE_24;
}
else {
mode .cfg |= WSPI_CFG_ADDR_SIZE_32;
}
mode.addr = offset;
mode.alt = 0U;
wspiReceive(busp, &mode, n, p);
}
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/**
* @brief Initializes an instance.
*
@ -323,7 +768,7 @@ void snorStart(SNORDriver *devp, const SNORConfig *config) {
if (devp->state == FLASH_STOP) {
/* Bus acquisition.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Device identification and initialization.*/
snor_device_init(devp);
@ -332,7 +777,7 @@ void snorStart(SNORDriver *devp, const SNORConfig *config) {
devp->state = FLASH_READY;
/* Bus release.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
}
}
@ -351,7 +796,7 @@ void snorStop(SNORDriver *devp) {
if (devp->state != FLASH_STOP) {
/* Bus acquisition.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Stopping bus device.*/
jesd216_stop(devp->config->busp);
@ -363,11 +808,11 @@ void snorStop(SNORDriver *devp) {
devp->state = FLASH_STOP;
/* Bus release.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
}
}
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
/**
* @brief Enters the memory Mapping mode.
@ -385,7 +830,7 @@ void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
wspi_command_t cmd;
/* Bus acquisition.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Activating XIP mode in the device.*/
snor_activate_xip(devp);
@ -395,11 +840,11 @@ void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
cmd.cmd = N25Q_CMD_FAST_READ;
cmd.dummy = SNOR_READ_DUMMY_CYCLES - 2;
cmd.cfg = WSPI_CFG_ADDR_SIZE_24 |
#if JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI1L
#if SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI1L
WSPI_CFG_CMD_MODE_ONE_LINE |
WSPI_CFG_ADDR_MODE_ONE_LINE |
WSPI_CFG_DATA_MODE_ONE_LINE |
#elif JESD216_BUS_MODE == JESD216_BUS_MODE_WSPI2L
#elif SNOR_BUS_MODE == SNOR_BUS_MODE_WSPI2L
WSPI_CFG_CMD_MODE_TWO_LINES |
WSPI_CFG_ADDR_MODE_TWO_LINES |
WSPI_CFG_DATA_MODE_TWO_LINES |
@ -416,7 +861,7 @@ void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
wspiMapFlash(devp->config->busp, &cmd, addrp);
/* Bus release.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
}
/**
@ -429,7 +874,7 @@ void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
void snorMemoryUnmap(SNORDriver *devp) {
/* Bus acquisition.*/
jesd216_bus_acquire(devp->config->busp, devp->config->buscfg);
bus_acquire(devp->config->busp, devp->config->buscfg);
/* Stopping WSPI memory mapped mode.*/
wspiUnmapFlash(devp->config->busp);
@ -437,9 +882,9 @@ void snorMemoryUnmap(SNORDriver *devp) {
snor_reset_xip(devp);
/* Bus release.*/
jesd216_bus_release(devp->config->busp);
bus_release(devp->config->busp);
}
#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
/** @} */

View File

@ -15,23 +15,36 @@
*/
/**
* @file m25q.h
* @brief M25Q serial flash driver header.
* @file serial_nor.h
* @brief Serial NOR driver header.
*
* @addtogroup M25Q
* @ingroup M25Q
* @addtogroup SERIAL_NOR
* @ingroup SERIAL_NOR
* @{
*/
#ifndef M25Q_H
#define M25Q_H
#ifndef SERIAL_NOR_H
#define SERIAL_NOR_H
#include "hal_jesd216_flash.h"
#include "hal_flash.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Bus interface modes.
* @{
*/
#define SNOR_BUS_MODE_SPI 0U
#define SNOR_BUS_MODE_WSPI1L 1U
#define SNOR_BUS_MODE_WSPI2L 2U
#define SNOR_BUS_MODE_WSPI4L 4U
#define SNOR_BUS_MODE_WSPI8L 8U
/** @} */
#define SNOR_BUS_CMD_EXTENDED_ADDRESSING 0x80000000U
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@ -40,10 +53,30 @@
* @name Configuration options
* @{
*/
/**
* @brief Physical transport interface.
*/
#if !defined(SNOR_BUS_MODE) || defined(__DOXYGEN__)
#define SNOR_BUS_MODE SNOR_BUS_MODE_WSPI4L
#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 WSPI_USE_MUTUAL_EXCLUSION depending on mode selected
* with @p SNOR_BUS_MODE.
*/
#if !defined(SNOR_SHARED_BUS) || defined(__DOXYGEN__)
#define SNOR_SHARED_BUS TRUE
#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
* operations.
* TODO: Should be handled in LLD.
*/
#if !defined(SNOR_READ_DUMMY_CYCLES) || defined(__DOXYGEN__)
#define SNOR_READ_DUMMY_CYCLES 8
@ -56,6 +89,7 @@
* device is configured using the Non Volatile Configuration
* Register then this option is not required.
* @note This option is only valid in QSPI bus modes.
* TODO: Should go in LLD.
*/
#if !defined(SNOR_SWITCH_WIDTH) || defined(__DOXYGEN__)
#define SNOR_SWITCH_WIDTH TRUE
@ -66,6 +100,7 @@
* @details If enabled this options inserts delays into the flash waiting
* routines releasing some extra CPU time for threads with lower
* priority, this may slow down the driver a bit however.
* TODO: Should go in LLD.
*/
#if !defined(SNOR_NICE_WAITING) || defined(__DOXYGEN__)
#define SNOR_NICE_WAITING TRUE
@ -73,6 +108,7 @@
/**
* @brief Uses 4kB sub-sectors rather than 64kB sectors.
* TODO: Should go in LLD.
*/
#if !defined(SNOR_USE_SUB_SECTORS) || defined(__DOXYGEN__)
#define SNOR_USE_SUB_SECTORS FALSE
@ -84,6 +120,7 @@
* @p flashVerifyErase() and its size must be a power of two.
* Larger buffers lead to better verify performance but increase
* stack usage for that function.
* TODO: Should go in LLD.
*/
#if !defined(SNOR_COMPARE_BUFFER_SIZE) || defined(__DOXYGEN__)
#define SNOR_COMPARE_BUFFER_SIZE 32
@ -94,6 +131,14 @@
/* Derived constants and error checks. */
/*===========================================================================*/
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
#define BUSConfig WSPIConfig
#define BUSDriver WSPIDriver
#else
#define BUSConfig SPIConfig
#define BUSDriver SPIDriver
#endif
#if (SNOR_READ_DUMMY_CYCLES < 1) || (SNOR_READ_DUMMY_CYCLES > 15)
#error "invalid SNOR_READ_DUMMY_CYCLES value (1..15)"
#endif
@ -107,29 +152,41 @@
/*===========================================================================*/
/**
* @brief Type of a M25Q configuration structure.
* @brief Type of a SNOR configuration structure.
*/
typedef struct {
_jesd216_config
BUSDriver *busp;
const BUSConfig *buscfg;
} SNORConfig;
/**
* @brief @p SNOR specific methods.
* @brief @p SNORDriver specific methods.
*/
#define _snor_methods \
_jesd216_flash_methods
#define _snor_flash_methods_alone \
/* Read SFDP.*/ \
flash_error_t (*read_sfdp)(void *instance, \
flash_offset_t offset, \
size_t n, \
uint8_t *rp);
/**
* @extends JESD216FlashVMT
* @brief @p SNORDriver specific methods with inherited ones.
*/
#define _snor_flash_methods \
_base_flash_methods \
_snor_flash_methods_alone
/**
* @extends BaseFlashVMT
*
* @brief @p SNOR virtual methods table.
*/
struct SNORDriverVMT {
_snor_methods
_snor_flash_methods
};
/**
* @extends JESD216Flash
* @extends BaseFlash
*
* @brief Type of SNOR flash class.
*/
@ -138,7 +195,7 @@ typedef struct {
* @brief SNORDriver Virtual Methods Table.
*/
const struct SNORDriverVMT *vmt;
_jesd216_flash_data
_base_flash_data
/**
* @brief Current configuration data.
*/
@ -160,15 +217,38 @@ typedef struct {
#ifdef __cplusplus
extern "C" {
#endif
void bus_cmd(BUSDriver *busp, uint32_t cmd);
void bus_cmd_send(BUSDriver *busp, uint32_t cmd, size_t n, const uint8_t *p);
void bus_cmd_receive(BUSDriver *busp,
uint32_t cmd,
size_t n,
uint8_t *p);
void bus_cmd_addr(BUSDriver *busp, uint32_t cmd, flash_offset_t offset);
void bus_cmd_addr_send(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
const uint8_t *p);
void bus_cmd_addr_receive(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
size_t n,
uint8_t *p);
void bus_cmd_addr_dummy_receive(BUSDriver *busp,
uint32_t cmd,
flash_offset_t offset,
uint32_t dummy,
size_t n,
uint8_t *p);
void snorObjectInit(SNORDriver *devp);
void snorStart(SNORDriver *devp, const SNORConfig *config);
void snorStop(SNORDriver *devp);
#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (SNOR_BUS_MODE != SNOR_BUS_MODE_SPI) || defined(__DOXYGEN__)
#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
void snorMemoryMap(SNORDriver *devp, uint8_t ** addrp);
void snorMemoryUnmap(SNORDriver *devp);
#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
#ifdef __cplusplus
}
#endif
@ -176,7 +256,7 @@ extern "C" {
/* Device-specific implementations.*/
#include "flash_device.h"
#endif /* M25Q_H */
#endif /* SERIAL_NOR_H */
/** @} */