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:
parent
57a173c178
commit
6d92e3242e
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
Loading…
Reference in New Issue