Tentative driver for macronix MX25LM51245G, untested.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12400 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
parent
ef66327057
commit
da54384531
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
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_flash_device.c
|
||||
* @brief Macronix MX25 serial flash driver code.
|
||||
*
|
||||
* @addtogroup MACRONIX_MX25
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hal.h"
|
||||
#include "hal_serial_nor.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define PAGE_SIZE 256U
|
||||
#define PAGE_MASK (PAGE_SIZE - 1U)
|
||||
|
||||
#if MX25_USE_SUB_SECTORS == TRUE
|
||||
#define SECTOR_SIZE 0x00001000U
|
||||
#define CMD_SECTOR_ERASE MX25_CMD_SUBSECTOR_ERASE
|
||||
#else
|
||||
#define SECTOR_SIZE 0x00010000U
|
||||
#define CMD_SECTOR_ERASE MX25_CMD_SECTOR_ERASE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief MX25LM51245G descriptor.
|
||||
*/
|
||||
flash_descriptor_t snor_descriptor = {
|
||||
.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
|
||||
FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
|
||||
.page_size = 256U,
|
||||
.sectors_count = 0U, /* It is overwritten.*/
|
||||
.sectors = NULL,
|
||||
.sectors_size = SECTOR_SIZE,
|
||||
.address = 0U
|
||||
};
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
|
||||
#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Fast read command for memory mapped mode.
|
||||
*/
|
||||
const wspi_command_t snor_memmap_read = {
|
||||
.addr = 0U,
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
.cmd = MX25_CMD_SPI_FAST_READ4B,
|
||||
.dummy = 8, /* Note, always 8 for this command. */
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
WSPI_CFG_CMD_SIZE_8 |
|
||||
WSPI_CFG_ADDR_SIZE_32
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
.cmd = MX25_CMD_OPI_8READ,
|
||||
.dummy = MX25_READ_DUMMY_CYCLES,
|
||||
.cfg = WSPI_CFG_CMD_MODE_TWO_LINES |
|
||||
WSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||
WSPI_CFG_DATA_MODE_TWO_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_ADDR_SIZE_32
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
.cmd = MX25_CMD_OPI_8DTRD,
|
||||
.dummy = MX25_READ_DUMMY_CYCLES,
|
||||
.cfg = WSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||
WSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||
WSPI_CFG_DATA_MODE_FOUR_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_ADDR_SIZE_32 |
|
||||
WSPI_CFG_CMD_DDR |
|
||||
WSPI_CFG_ADDR_DDR |
|
||||
WSPI_CFG_DATA_DDR
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
|
||||
/* Initial MX25_CMD_READ_ID command.*/
|
||||
static const wspi_command_t mx25_cmd_read_id = {
|
||||
|
||||
#if MX25_SWITCH_WIDTH == TRUE
|
||||
.cmd = MX25_CMD_SPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
WSPI_CFG_CMD_SIZE_8,
|
||||
.dummy = 0,
|
||||
#else
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
.cmd = MX25_CMD_SPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
WSPI_CFG_CMD_SIZE_8,
|
||||
.dummy = 0,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
.cmd = MX25_CMD_OPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16,
|
||||
.dummy = MX25_READ_DUMMY_CYCLES,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
.cmd = MX25_CMD_OPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_CMD_DDR,
|
||||
.dummy = MX25_READ_DUMMY_CYCLES,
|
||||
#endif
|
||||
#endif
|
||||
.addr = 0,
|
||||
.alt = 0
|
||||
};
|
||||
|
||||
static const uint8_t n25q_manufacturer_ids[] = MX25_SUPPORTED_MANUFACTURE_IDS;
|
||||
static const uint8_t n25q_memory_type_ids[] = MX25_SUPPORTED_MEMORY_TYPE_IDS;
|
||||
#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static bool n25q_find_id(const uint8_t *set, size_t size, uint8_t element) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (set[i] == element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static flash_error_t n25q_poll_status(SNORDriver *devp) {
|
||||
uint8_t sts;
|
||||
|
||||
do {
|
||||
#if MX25_NICE_WAITING == TRUE
|
||||
osalThreadSleepMilliseconds(1);
|
||||
#endif
|
||||
/* Read status command.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSR, 1, &sts);
|
||||
#else
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSR, 1, &sts);
|
||||
#endif
|
||||
} while ((sts & 1U) != 0U);
|
||||
|
||||
/* Reading security register and checking for errors.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSCUR, 1, &sts);
|
||||
#else
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSCUR, 1, &sts);
|
||||
#endif
|
||||
if ((sts & MX25_FLAGS_ALL_ERRORS) != 0U) {
|
||||
|
||||
return FLASH_ERROR_PROGRAM;
|
||||
}
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
|
||||
static void n25q_reset_memory(SNORDriver *devp) {
|
||||
|
||||
/* 1x MX25_CMD_SPI_RSTEN command.*/
|
||||
static const wspi_command_t cmd_reset_enable_1 = {
|
||||
.cmd = MX25_CMD_SPI_RSTEN,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
/* 1x MX25_CMD_SPI_RST command.*/
|
||||
static const wspi_command_t cmd_reset_memory_1 = {
|
||||
.cmd = MX25_CMD_SPI_RST,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE | WSPI_CFG_CMD_SIZE_8,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
/* If the device is in one bit mode then the following commands are
|
||||
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 MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
/* 8xDTR MX25_CMD_OPI_RSTEN command.*/
|
||||
static const wspi_command_t cmd_reset_enable_8dtr = {
|
||||
.cmd = MX25_CMD_OPI_RSTEN,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_CMD_DDR,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
/* 8xDTR MX25_CMD_OPI_RST command.*/
|
||||
static const wspi_command_t cmd_reset_memory_8dtr = {
|
||||
.cmd = MX25_CMD_OPI_RST,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_CMD_DDR,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
wspiCommand(devp->config->busp, &cmd_reset_enable_8dtr);
|
||||
wspiCommand(devp->config->busp, &cmd_reset_memory_8dtr);
|
||||
#else
|
||||
/* 8xSTR MX25_CMD_OPI_RSTEN command.*/
|
||||
static const wspi_command_t cmd_reset_enable_8str = {
|
||||
.cmd = MX25_CMD_OPI_RSTEN,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
/* 8xSTR MX25_CMD_OPI_RST command.*/
|
||||
static const wspi_command_t cmd_reset_memory_8str = {
|
||||
.cmd = MX25_CMD_OPI_RST,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16,
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
wspiCommand(devp->config->busp, &cmd_reset_enable_8str);
|
||||
wspiCommand(devp->config->busp, &cmd_reset_memory_8str);
|
||||
#endif
|
||||
|
||||
/* Now the device should be in one bit mode for sure and we perform a
|
||||
device reset.*/
|
||||
wspiCommand(devp->config->busp, &cmd_reset_enable_1);
|
||||
wspiCommand(devp->config->busp, &cmd_reset_memory_1);
|
||||
}
|
||||
|
||||
static void mx25_write_cr2(SNORDriver *devp, uint32_t addr, const uint8_t *value) {
|
||||
|
||||
const wspi_command_t cmd_write_cr2 = {
|
||||
|
||||
#if MX25_SWITCH_WIDTH == TRUE
|
||||
.cmd = MX25_CMD_SPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
WSPI_CFG_CMD_SIZE_8 |
|
||||
WSPI_CFG_ADDR_SIZE_32,
|
||||
#else
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
.cmd = MX25_CMD_SPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE |
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE |
|
||||
WSPI_CFG_CMD_SIZE_8 |
|
||||
WSPI_CFG_ADDR_SIZE_32,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
.cmd = MX25_CMD_OPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_ADDR_SIZE_32,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
.cmd = MX25_CMD_OPI_RDID,
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_ADDR_SIZE_32 |
|
||||
WSPI_CFG_CMD_DDR,
|
||||
#endif
|
||||
#endif
|
||||
.addr = addr,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
static const wspi_command_t cmd_write_enable = {
|
||||
#if MX25_SWITCH_WIDTH == TRUE
|
||||
.cmd = MX25_CMD_SPI_WREN,
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
|
||||
#else
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
.cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16,
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
.cfg = WSPI_CFG_CMD_MODE_EIGHT_LINES |
|
||||
WSPI_CFG_CMD_SIZE_16 |
|
||||
WSPI_CFG_CMD_DDR,
|
||||
#endif
|
||||
#endif
|
||||
.addr = 0,
|
||||
.alt = 0,
|
||||
.dummy = 0
|
||||
};
|
||||
|
||||
wspiCommand(devp->config->busp, &cmd_write_enable);
|
||||
wspiSend(devp->config->busp, &cmd_write_cr2, 1, value);
|
||||
}
|
||||
#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
void snor_device_init(SNORDriver *devp) {
|
||||
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI
|
||||
/* Reading device ID.*/
|
||||
bus_cmd_receive(devp->config->busp, MX25_CMD_READ_ID,
|
||||
sizeof devp->device_id, devp->device_id);
|
||||
|
||||
#else /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
|
||||
|
||||
/* Attempting a reset of the device, it could be in an unexpected state
|
||||
because a CPU reset does not reset the memory too.*/
|
||||
n25q_reset_memory(devp);
|
||||
|
||||
/* Reading device ID and unique ID.*/
|
||||
wspiReceive(devp->config->busp, &mx25_cmd_read_id,
|
||||
sizeof devp->device_id, devp->device_id);
|
||||
#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
|
||||
|
||||
/* Checking if the device is white listed.*/
|
||||
osalDbgAssert(n25q_find_id(n25q_manufacturer_ids,
|
||||
sizeof n25q_manufacturer_ids,
|
||||
devp->device_id[0]),
|
||||
"invalid manufacturer id");
|
||||
osalDbgAssert(n25q_find_id(n25q_memory_type_ids,
|
||||
sizeof n25q_memory_type_ids,
|
||||
devp->device_id[1]),
|
||||
"invalid memory type id");
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (MX25_SWITCH_WIDTH == TRUE)
|
||||
{
|
||||
/* Bus width initialization.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
static const uint8_t regval[1] = {0x01};
|
||||
#else
|
||||
static const uint8_t regval[1] = {0x02};
|
||||
#endif
|
||||
uint8_t id[8];
|
||||
|
||||
/* Setting up final bus width.*/
|
||||
mx25_write_cr2(devp, 0x00000000U, regval);
|
||||
|
||||
/* Reading ID again for confirmation, in DTR mode bytes are read twice,
|
||||
it needs adjusting.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDID, 6, id);
|
||||
id[1] = id[2];
|
||||
id[2] = id[4];
|
||||
#else
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDID,
|
||||
MX25_READ_DUMMY_CYCLES, 3, id);
|
||||
#endif
|
||||
|
||||
/* Checking if the device is white listed.*/
|
||||
osalDbgAssert(memcmp(id, devp->device_id, 3) == 0,
|
||||
"id confirmation failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setting up the device size.*/
|
||||
snor_descriptor.sectors_count = (1U << ((size_t)devp->device_id[2]) & 0x1FU) /
|
||||
SECTOR_SIZE;
|
||||
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
|
||||
{
|
||||
static const uint8_t regval[1] = {
|
||||
~((MX25_READ_DUMMY_CYCLES - 6U) / 2U) & 7U
|
||||
};
|
||||
|
||||
/* Setting up the dummy cycles to be used for fast read operations.*/
|
||||
mx25_write_cr2(devp, 0x00000300U, regval);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const flash_descriptor_t *snor_get_descriptor(void *instance) {
|
||||
SNORDriver *devp = (SNORDriver *)instance;
|
||||
|
||||
osalDbgCheck(instance != NULL);
|
||||
osalDbgAssert((devp->state != FLASH_UNINIT) && (devp->state != FLASH_STOP),
|
||||
"invalid state");
|
||||
|
||||
return &snor_descriptor;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, uint8_t *rp) {
|
||||
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
|
||||
/* Fast read command in WSPI mode.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_SPI_FAST_READ4B,
|
||||
offset, 8, /* Note, always 8 dummy cycles. */
|
||||
n, rp);
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8DTRD,
|
||||
offset, MX25_READ_DUMMY_CYCLES, n, rp);
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8READ,
|
||||
offset, MX25_READ_DUMMY_CYCLES, n, rp);
|
||||
#endif
|
||||
#else
|
||||
/* Normal read command in SPI mode.*/
|
||||
bus_cmd_addr_receive(devp->config->busp, MX25_CMD_SPI_READ4B,
|
||||
offset, n, rp);
|
||||
#endif
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, const uint8_t *pp) {
|
||||
|
||||
/* Data is programmed page by page.*/
|
||||
while (n > 0U) {
|
||||
flash_error_t err;
|
||||
|
||||
/* Data size that can be written in a single program page operation.*/
|
||||
size_t chunk = (size_t)(((offset | PAGE_MASK) + 1U) - offset);
|
||||
if (chunk > n) {
|
||||
chunk = n;
|
||||
}
|
||||
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
|
||||
|
||||
/* Page program command.*/
|
||||
bus_cmd_addr_send(devp->config->busp, MX25_CMD_SPI_PP4B, offset,
|
||||
chunk, pp);
|
||||
#else
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
|
||||
|
||||
/* Page program command.*/
|
||||
bus_cmd_addr_send(devp->config->busp, MX25_CMD_OPI_PP4B, offset,
|
||||
chunk, pp);
|
||||
#endif
|
||||
|
||||
/* Wait for status and check errors.*/
|
||||
err = n25q_poll_status(devp);
|
||||
if (err != FLASH_NO_ERROR) {
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Next page.*/
|
||||
offset += chunk;
|
||||
pp += chunk;
|
||||
n -= chunk;
|
||||
}
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_start_erase_all(SNORDriver *devp) {
|
||||
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
|
||||
|
||||
/* Bulk erase command.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_SPI_CE);
|
||||
#else
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
|
||||
|
||||
/* Bulk erase command.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_OPI_CE);
|
||||
#endif
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
|
||||
flash_sector_t sector) {
|
||||
flash_offset_t offset = (flash_offset_t)(sector * SECTOR_SIZE);
|
||||
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
|
||||
|
||||
#if MX25_USE_SUB_SECTORS == FALSE
|
||||
/* Block erase command.*/
|
||||
bus_cmd_addr(devp->config->busp, MX25_CMD_SPI_BE4B, offset);
|
||||
#else
|
||||
/* Sector erase command.*/
|
||||
bus_cmd_addr(devp->config->busp, MX25_CMD_SPI_SE4B, offset);
|
||||
#endif
|
||||
#else
|
||||
/* Enabling write operation.*/
|
||||
bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
|
||||
|
||||
#if MX25_USE_SUB_SECTORS == FALSE
|
||||
/* Block erase command.*/
|
||||
bus_cmd_addr(devp->config->busp, MX25_CMD_OPI_BE4B, offset);
|
||||
#else
|
||||
/* Sector erase command.*/
|
||||
bus_cmd_addr(devp->config->busp, MX25_CMD_OPI_SE4B, offset);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_verify_erase(SNORDriver *devp,
|
||||
flash_sector_t sector) {
|
||||
uint8_t cmpbuf[MX25_COMPARE_BUFFER_SIZE];
|
||||
flash_offset_t offset;
|
||||
size_t n;
|
||||
|
||||
/* Read command.*/
|
||||
offset = (flash_offset_t)(sector * SECTOR_SIZE);
|
||||
n = SECTOR_SIZE;
|
||||
while (n > 0U) {
|
||||
uint8_t *p;
|
||||
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_SPI_FAST_READ4B,
|
||||
offset, 8, /* Note, always 8 dummy cycles. */
|
||||
sizeof cmpbuf, cmpbuf);
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8READ,
|
||||
offset, MX25_READ_DUMMY_CYCLES,
|
||||
sizeof cmpbuf, cmpbuf);
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
|
||||
bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8DTRD,
|
||||
offset, MX25_READ_DUMMY_CYCLES,
|
||||
sizeof cmpbuf, cmpbuf);
|
||||
#endif
|
||||
#else
|
||||
/* Normal read command in SPI mode.*/
|
||||
bus_cmd_addr_receive(devp->config->busp, MX25_CMD_SPI_READ4B,
|
||||
offset, sizeof cmpbuf, cmpbuf);
|
||||
#endif
|
||||
|
||||
/* Checking for erased state of current buffer.*/
|
||||
for (p = cmpbuf; p < &cmpbuf[MX25_COMPARE_BUFFER_SIZE]; p++) {
|
||||
if (*p != 0xFFU) {
|
||||
/* Ready state again.*/
|
||||
devp->state = FLASH_READY;
|
||||
|
||||
return FLASH_ERROR_VERIFY;
|
||||
}
|
||||
}
|
||||
|
||||
offset += sizeof cmpbuf;
|
||||
n -= sizeof cmpbuf;
|
||||
}
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
|
||||
uint8_t sts, sec;
|
||||
|
||||
/* Read status register.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSR, 1, &sts);
|
||||
#else
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSR, 1, &sts);
|
||||
#endif
|
||||
|
||||
/* Read security register.*/
|
||||
#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSCUR, 1, &sec);
|
||||
#else
|
||||
bus_cmd_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSCUR, 1, &sec);
|
||||
#endif
|
||||
|
||||
/* If the WIP bit is one (busy) or the flash in a suspended state then
|
||||
report that the operation is still in progress.*/
|
||||
if (((sts & 1) != 0U) || ((sec & 8) != 0U)) {
|
||||
|
||||
/* Recommended time before polling again, this is a simplified
|
||||
implementation.*/
|
||||
if (msec != NULL) {
|
||||
*msec = 1U;
|
||||
}
|
||||
|
||||
return FLASH_BUSY_ERASING;
|
||||
}
|
||||
|
||||
/* Checking for errors.*/
|
||||
if ((sec & MX25_FLAGS_ALL_ERRORS) != 0U) {
|
||||
|
||||
/* Erase operation failed.*/
|
||||
return FLASH_ERROR_ERASE;
|
||||
}
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, uint8_t *rp) {
|
||||
|
||||
(void)devp;
|
||||
(void)rp;
|
||||
(void)offset;
|
||||
(void)n;
|
||||
|
||||
return FLASH_NO_ERROR;
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
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_flash_device.h
|
||||
* @brief Macronix MX25 serial flash driver header.
|
||||
*
|
||||
* @addtogroup MACRONIX_MX25
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_FLASH_DEVICE_H
|
||||
#define HAL_FLASH_DEVICE_H
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Device capabilities
|
||||
* @{
|
||||
*/
|
||||
#define SNOR_DEVICE_SUPPORTS_XIP FALSE
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device identification
|
||||
* @{
|
||||
*/
|
||||
#define MX25_SUPPORTED_MANUFACTURE_IDS {0xC2}
|
||||
#define MX25_SUPPORTED_MEMORY_TYPE_IDS {0x85}
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Command codes, SPI mode
|
||||
* @{
|
||||
*/
|
||||
#define MX25_CMD_SPI_READ3B 0x03U
|
||||
#define MX25_CMD_SPI_FAST_READ3B 0x0BU
|
||||
#define MX25_CMD_SPI_PP3B 0x02U
|
||||
#define MX25_CMD_SPI_SE3B 0x20U
|
||||
#define MX25_CMD_SPI_BE3B 0xD8U
|
||||
#define MX25_CMD_SPI_CE 0xC7U
|
||||
#define MX25_CMD_SPI_READ4B 0x13U
|
||||
#define MX25_CMD_SPI_FAST_READ4B 0x0CU
|
||||
#define MX25_CMD_SPI_PP4B 0x12U
|
||||
#define MX25_CMD_SPI_SE4B 0x21U
|
||||
#define MX25_CMD_SPI_BE4B 0xDCU
|
||||
#define MX25_CMD_SPI_WREN 0x06U
|
||||
#define MX25_CMD_SPI_WRDI 0x04U
|
||||
#define MX25_CMD_SPI_PE_SUSPEND 0xB0U
|
||||
#define MX25_CMD_SPI_PE_RESUME 0x30U
|
||||
#define MX25_CMD_SPI_DP 0xB9U
|
||||
#define MX25_CMD_SPI_SBL 0xC0U
|
||||
#define MX25_CMD_SPI_ENSO 0xB1U
|
||||
#define MX25_CMD_SPI_EXSO 0xC1U
|
||||
#define MX25_CMD_SPI_NOP 0x00U
|
||||
#define MX25_CMD_SPI_RSTEN 0x66U
|
||||
#define MX25_CMD_SPI_RST 0x99U
|
||||
#define MX25_CMD_SPI_RDID 0x9FU
|
||||
#define MX25_CMD_SPI_RDSFDP 0x5AU
|
||||
#define MX25_CMD_SPI_RDSR 0x05U
|
||||
#define MX25_CMD_SPI_RDCR 0x15U
|
||||
#define MX25_CMD_SPI_WRSR 0x01U
|
||||
#define MX25_CMD_SPI_RDCR2 0x71U
|
||||
#define MX25_CMD_SPI_WRCR2 0x72U
|
||||
#define MX25_CMD_SPI_RDFBR 0x16U
|
||||
#define MX25_CMD_SPI_WRFBR 0x17U
|
||||
#define MX25_CMD_SPI_ESFBR 0x18U
|
||||
#define MX25_CMD_SPI_RDSCUR 0x2BU
|
||||
#define MX25_CMD_SPI_WRSCUR 0x2FU
|
||||
#define MX25_CMD_SPI_WRLR 0x2CU
|
||||
#define MX25_CMD_SPI_RDLR 0x2DU
|
||||
#define MX25_CMD_SPI_WRSPB 0xE3U
|
||||
#define MX25_CMD_SPI_ESSPB 0xE4U
|
||||
#define MX25_CMD_SPI_RDSPB 0xE2U
|
||||
#define MX25_CMD_SPI_WRDPB 0xE1U
|
||||
#define MX25_CMD_SPI_RDDPB 0xE0U
|
||||
#define MX25_CMD_SPI_WPSEL 0x68U
|
||||
#define MX25_CMD_SPI_GBLK 0x7EU
|
||||
#define MX25_CMD_SPI_GBULK 0x98U
|
||||
#define MX25_CMD_SPI_RDPASS 0x27U
|
||||
#define MX25_CMD_SPI_WRPASS 0x28U
|
||||
#define MX25_CMD_SPI_PASSULK 0x29U
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Command codes, OPI mode
|
||||
* @{
|
||||
*/
|
||||
#define MX25_CMD_OPI_8READ 0xEC13U
|
||||
#define MX25_CMD_OPI_8DTRD 0xEE11U
|
||||
#define MX25_CMD_OPI_RDID 0x9F60U
|
||||
#define MX25_CMD_OPI_RDSFDP 0x5AA5U
|
||||
#define MX25_CMD_OPI_PP 0x12EDU
|
||||
#define MX25_CMD_OPI_SE 0x21DEU
|
||||
#define MX25_CMD_OPI_BE 0xDC23U
|
||||
#define MX25_CMD_OPI_CE 0xC738U
|
||||
#define MX25_CMD_OPI_WREN 0x06F9U
|
||||
#define MX25_CMD_OPI_WRDI 0x04FBU
|
||||
#define MX25_CMD_OPI_PE_SUSPEND 0xB04FU
|
||||
#define MX25_CMD_OPI_PE_RESUME 0x30CFU
|
||||
#define MX25_CMD_OPI_DP 0xB946U
|
||||
#define MX25_CMD_OPI_SBL 0xC03FU
|
||||
#define MX25_CMD_OPI_ENSO 0xB14EU
|
||||
#define MX25_CMD_OPI_EXSO 0xC13EU
|
||||
#define MX25_CMD_OPI_NOP 0x00FFU
|
||||
#define MX25_CMD_OPI_RSTEN 0x6699U
|
||||
#define MX25_CMD_OPI_RST 0x9966U
|
||||
#define MX25_CMD_OPI_RDSR 0x05FAU
|
||||
#define MX25_CMD_OPI_RDCR 0x15EAU
|
||||
#define MX25_CMD_OPI_WRSR 0x01FEU
|
||||
#define MX25_CMD_OPI_WRCR 0x01FEU
|
||||
#define MX25_CMD_OPI_RDCR2 0x718EU
|
||||
#define MX25_CMD_OPI_WRCR2 0x728DU
|
||||
#define MX25_CMD_OPI_RDFBR 0x16E9U
|
||||
#define MX25_CMD_OPI_WRFBR 0x17E8U
|
||||
#define MX25_CMD_OPI_ESFBR 0x18E7U
|
||||
#define MX25_CMD_OPI_RDSCUR 0x2BD4U
|
||||
#define MX25_CMD_OPI_WRSCUR 0x2FD0U
|
||||
#define MX25_CMD_OPI_WRLR 0x2CD3U
|
||||
#define MX25_CMD_OPI_RDLR 0x2DD2U
|
||||
#define MX25_CMD_OPI_WRSPB 0xE31CU
|
||||
#define MX25_CMD_OPI_ESSPB 0xE41BU
|
||||
#define MX25_CMD_OPI_RDSPB 0xE21DU
|
||||
#define MX25_CMD_OPI_WRDPB 0xE11EU
|
||||
#define MX25_CMD_OPI_RDDPB 0xE01FU
|
||||
#define MX25_CMD_OPI_WPSEL 0x6897U
|
||||
#define MX25_CMD_OPI_GBLK 0x7E81U
|
||||
#define MX25_CMD_OPI_GBULK 0x9867U
|
||||
#define MX25_CMD_OPI_RDPASS 0x27D8U
|
||||
#define MX25_CMD_OPI_WRPASS 0x28D7U
|
||||
#define MX25_CMD_OPI_PASSULK 0x29D6U
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Flags status register bits
|
||||
* @{
|
||||
*/
|
||||
#define MX25_FLAGS_WPSEL 0x80U
|
||||
#define MX25_FLAGS_E_FAIL 0x40U
|
||||
#define MX25_FLAGS_P_FAIL 0x20U
|
||||
#define MX25_FLAGS_ESB 0x08U
|
||||
#define MX25_FLAGS_PSB 0x04U
|
||||
#define MX25_FLAGS_LDSO 0x02U
|
||||
#define MX25_FLAGS_SECURED_OTP 0x01U
|
||||
#define MX25_FLAGS_ALL_ERRORS (MX25_FLAGS_E_FAIL | \
|
||||
MX25_FLAGS_P_FAIL)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Bus interface modes.
|
||||
* @{
|
||||
*/
|
||||
#define MX25_BUS_MODE_SPI 0U
|
||||
#define MX25_BUS_MODE_OPI_STR 1U
|
||||
#define MX25_BUS_MODE_OPI_DTR 2U
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Switch WSPI bus width on initialization.
|
||||
* @details A bus width initialization is performed by writing the
|
||||
* Enhanced Volatile Configuration Register. If the flash
|
||||
* 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.
|
||||
*/
|
||||
#if !defined(MX25_SWITCH_WIDTH) || defined(__DOXYGEN__)
|
||||
#define MX25_SWITCH_WIDTH TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device bus mode to be used.
|
||||
* #note if @p MX25_SWITCH_WIDTH is @p FALSE then this is the bus mode
|
||||
* that the device is expected to be using.
|
||||
* #note if @p MX25_SWITCH_WIDTH is @p TRUE then this is the bus mode
|
||||
* that the device will be switched in.
|
||||
* @note This option is only valid in WSPI bus mode.
|
||||
*/
|
||||
#if !defined(MX25_BUS_MODE) || defined(__DOXYGEN__)
|
||||
#define MX25_BUS_MODE MX25_BUS_MODE_SPI
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(MX25_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
#define MX25_NICE_WAITING TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Uses 4kB sub-sectors rather than 64kB sectors.
|
||||
*/
|
||||
#if !defined(MX25_USE_SUB_SECTORS) || defined(__DOXYGEN__)
|
||||
#define MX25_USE_SUB_SECTORS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of the compare buffer.
|
||||
* @details This buffer is allocated in the stack frame of the function
|
||||
* @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.
|
||||
*/
|
||||
#if !defined(MX25_COMPARE_BUFFER_SIZE) || defined(__DOXYGEN__)
|
||||
#define MX25_COMPARE_BUFFER_SIZE 32
|
||||
#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.
|
||||
*/
|
||||
#if !defined(MX25_READ_DUMMY_CYCLES) || defined(__DOXYGEN__)
|
||||
#define MX25_READ_DUMMY_CYCLES 6
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (MX25_COMPARE_BUFFER_SIZE & (MX25_COMPARE_BUFFER_SIZE - 1)) != 0
|
||||
#error "invalid MX25_COMPARE_BUFFER_SIZE value"
|
||||
#endif
|
||||
|
||||
#if (MX25_READ_DUMMY_CYCLES < 6) || (MX25_READ_DUMMY_CYCLES > 20) || \
|
||||
((MX25_READ_DUMMY_CYCLES & 1) != 0)
|
||||
#error "invalid MX25_READ_DUMMY_CYCLES value (6, 8, 10, 12, 14, 16, 18, 20)"
|
||||
#endif
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI) && \
|
||||
(MX25_BUS_MODE != MX25_BUS_MODE_SPI)
|
||||
#error "only MX25_BUS_MODE_SPI is allowed when using SPI driver"
|
||||
#endif
|
||||
|
||||
#if (MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief WSPI settings for command only.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32 | \
|
||||
WSPI_CFG_CMD_DDR)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command and address.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32 | \
|
||||
WSPI_CFG_CMD_DDR | \
|
||||
WSPI_CFG_ADDR_DDR)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command and data.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32 | \
|
||||
WSPI_CFG_CMD_DDR | \
|
||||
WSPI_CFG_DATA_DDR)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command, address and data.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32 | \
|
||||
WSPI_CFG_CMD_DDR | \
|
||||
WSPI_CFG_ADDR_DDR | \
|
||||
WSPI_CFG_DATA_DDR)
|
||||
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_EIGHT_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_16 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#elif MX25_BUS_MODE == MX25_BUS_MODE_SPI
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_32)
|
||||
|
||||
#else
|
||||
#error "invalid MX25_BUS_MODE setting"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern flash_descriptor_t snor_descriptor;
|
||||
#endif
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (WSPI_SUPPORTS_MEMMAP == TRUE)
|
||||
extern const wspi_command_t snor_memmap_read;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void snor_device_init(SNORDriver *devp);
|
||||
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);
|
||||
flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, const uint8_t *pp);
|
||||
flash_error_t snor_device_start_erase_all(SNORDriver *devp);
|
||||
flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
|
||||
flash_sector_t sector);
|
||||
flash_error_t snor_device_verify_erase(SNORDriver *devp,
|
||||
flash_sector_t sector);
|
||||
flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec);
|
||||
flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, uint8_t *rp);
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && \
|
||||
(SNOR_DEVICE_SUPPORTS_XIP == TRUE)
|
||||
void snor_activate_xip(SNORDriver *devp);
|
||||
void snor_reset_xip(SNORDriver *devp);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_FLASH_DEVICE_H */
|
||||
|
||||
/** @} */
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# List of all the Micron N25Q device files.
|
||||
SERNORSRC := $(CHIBIOS)/os/hal/lib/peripherals/flash/hal_flash.c \
|
||||
$(CHIBIOS)/os/hal/lib/complex/serial_nor/hal_serial_nor.c \
|
||||
$(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.c
|
||||
|
||||
# Required include directories
|
||||
SERNORINC := $(CHIBIOS)/os/hal/lib/peripherals/flash \
|
||||
$(CHIBIOS)/os/hal/lib/complex/serial_nor \
|
||||
$(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/macronix_mx25
|
||||
|
||||
# Shared variables
|
||||
ALLCSRC += $(SERNORSRC)
|
||||
ALLINC += $(SERNORINC)
|
|
@ -19,7 +19,6 @@
|
|||
* @brief Micron N25Q serial flash driver code.
|
||||
*
|
||||
* @addtogroup MICRON_N25Q
|
||||
* @ingroup MICRON_N25Q
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* @brief Micron N25Q serial flash driver header.
|
||||
*
|
||||
* @addtogroup MICRON_N25Q
|
||||
* @ingroup MICRON_N25Q
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -30,6 +29,13 @@
|
|||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Device capabilities
|
||||
* @{
|
||||
*/
|
||||
#define SNOR_DEVICE_SUPPORTS_XIP TRUE
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device identification
|
||||
* @{
|
||||
|
@ -181,100 +187,100 @@
|
|||
/**
|
||||
* @brief WSPI settings for command only.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command and address.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_FOUR_LINES| \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command and data.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_FOUR_LINES| \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
/**
|
||||
* @brief WSPI settings for command, address and data.
|
||||
*/
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_FOUR_LINES| \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_FOUR_LINES| \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_FOUR_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_TWO_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_TWO_LINES | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_TWO_LINES | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_NONE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_NONE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ADDR_MODE_ONE_LINE | \
|
||||
WSPI_CFG_ALT_MODE_NONE | \
|
||||
WSPI_CFG_DATA_MODE_ONE_LINE | \
|
||||
WSPI_CFG_CMD_SIZE_8 | \
|
||||
WSPI_CFG_ADDR_SIZE_24)
|
||||
|
||||
#else
|
||||
#error "invalid N25Q_BUS_MODE setting"
|
||||
|
@ -317,7 +323,8 @@ extern "C" {
|
|||
flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec);
|
||||
flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
|
||||
size_t n, uint8_t *rp);
|
||||
#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && \
|
||||
(SNOR_DEVICE_SUPPORTS_XIP == TRUE)
|
||||
void snor_activate_xip(SNORDriver *devp);
|
||||
void snor_reset_xip(SNORDriver *devp);
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* @brief Serial NOR serial flash driver code.
|
||||
*
|
||||
* @addtogroup HAL_SERIAL_NOR
|
||||
* @ingroup HAL_SERIAL_NOR
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -564,6 +563,33 @@ void bus_cmd_addr_receive(BUSDriver *busp,
|
|||
}
|
||||
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Sends a command followed by dummy cycles and a
|
||||
* data receive phase.
|
||||
*
|
||||
* @param[in] busp pointer to the bus driver
|
||||
* @param[in] cmd instruction code
|
||||
* @param[in] dummy number of dummy cycles
|
||||
* @param[in] n number of bytes to receive
|
||||
* @param[out] p data buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void bus_cmd_dummy_receive(BUSDriver *busp,
|
||||
uint32_t cmd,
|
||||
uint32_t dummy,
|
||||
size_t n,
|
||||
uint8_t *p) {
|
||||
wspi_command_t mode;
|
||||
|
||||
mode.cmd = cmd;
|
||||
mode.cfg = SNOR_WSPI_CFG_CMD_ADDR_DATA;
|
||||
mode.addr = 0U;
|
||||
mode.alt = 0U;
|
||||
mode.dummy = dummy;
|
||||
wspiReceive(busp, &mode, n, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a command followed by a flash address, dummy cycles and a
|
||||
* data receive phase.
|
||||
|
@ -691,8 +717,10 @@ void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
|
|||
/* Bus acquisition.*/
|
||||
bus_acquire(devp->config->busp, devp->config->buscfg);
|
||||
|
||||
#if SNOR_DEVICE_SUPPORTS_XIP == TRUE
|
||||
/* Activating XIP mode in the device.*/
|
||||
snor_activate_xip(devp);
|
||||
#endif
|
||||
|
||||
/* Starting WSPI memory mapped mode.*/
|
||||
wspiMapFlash(devp->config->busp, &snor_memmap_read, addrp);
|
||||
|
@ -716,7 +744,9 @@ void snorMemoryUnmap(SNORDriver *devp) {
|
|||
/* Stopping WSPI memory mapped mode.*/
|
||||
wspiUnmapFlash(devp->config->busp);
|
||||
|
||||
#if SNOR_DEVICE_SUPPORTS_XIP == TRUE
|
||||
snor_reset_xip(devp);
|
||||
#endif
|
||||
|
||||
/* Bus release.*/
|
||||
bus_release(devp->config->busp);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* @brief Serial NOR driver header.
|
||||
*
|
||||
* @addtogroup SERIAL_NOR
|
||||
* @ingroup SERIAL_NOR
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -169,12 +168,19 @@ extern "C" {
|
|||
flash_offset_t offset,
|
||||
size_t n,
|
||||
uint8_t *p);
|
||||
#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
|
||||
void bus_cmd_dummy_receive(BUSDriver *busp,
|
||||
uint32_t cmd,
|
||||
uint32_t dummy,
|
||||
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);
|
||||
#endif
|
||||
void snorObjectInit(SNORDriver *devp);
|
||||
void snorStart(SNORDriver *devp, const SNORConfig *config);
|
||||
void snorStop(SNORDriver *devp);
|
||||
|
|
Loading…
Reference in New Issue