git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9558 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
4121213741
commit
f3c38b36f5
|
@ -152,54 +152,6 @@ static const qspi_command_t cmd_write_enable = {
|
||||||
.alt = 0
|
.alt = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 1x M25Q_CMD_RESET_ENABLE command.*/
|
|
||||||
static const qspi_command_t cmd_reset_enable_1 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
|
||||||
QSPI_CFG_CMD_MODE_ONE_LINE,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 2x M25Q_CMD_RESET_ENABLE command.*/
|
|
||||||
static const qspi_command_t cmd_reset_enable_2 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
|
||||||
QSPI_CFG_CMD_MODE_TWO_LINES,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 4x M25Q_CMD_RESET_ENABLE command.*/
|
|
||||||
static const qspi_command_t cmd_reset_enable_4 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
|
||||||
QSPI_CFG_CMD_MODE_FOUR_LINES,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 1x M25Q_CMD_RESET_MEMORY command.*/
|
|
||||||
static const qspi_command_t cmd_reset_memory_1 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
|
||||||
QSPI_CFG_CMD_MODE_ONE_LINE,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 2x M25Q_CMD_RESET_MEMORY command.*/
|
|
||||||
static const qspi_command_t cmd_reset_memory_2 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
|
||||||
QSPI_CFG_CMD_MODE_TWO_LINES,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 4x M25Q_CMD_RESET_MEMORY command.*/
|
|
||||||
static const qspi_command_t cmd_reset_memory_4 = {
|
|
||||||
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
|
||||||
QSPI_CFG_CMD_MODE_FOUR_LINES,
|
|
||||||
.addr = 0,
|
|
||||||
.alt = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Bus width initialization.*/
|
/* Bus width initialization.*/
|
||||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||||
static const uint8_t evconf_value[1] = {0xCF};
|
static const uint8_t evconf_value[1] = {0xCF};
|
||||||
|
@ -208,19 +160,6 @@ static const uint8_t evconf_value[1] = {0x8F};
|
||||||
#else
|
#else
|
||||||
static const uint8_t evconf_value[1] = {0x4F};
|
static const uint8_t evconf_value[1] = {0x4F};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const uint8_t flash_status[1] = {(M25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU};
|
|
||||||
static const uint8_t flash_status_xip[1] = {(M25Q_READ_DUMMY_CYCLES << 4U) | 0x07U};
|
|
||||||
static const uint8_t flash_reset_xip_pattern[50] = {
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
||||||
0x11, 0x11
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -513,24 +452,99 @@ static void flash_cmd_addr_dummy_receive(M25QDriver *devp,
|
||||||
qspiReceive(devp->config->qspip, &mode, n, p);
|
qspiReceive(devp->config->qspip, &mode, n, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_xip_reset(M25QDriver *devp) {
|
void flash_reset_xip(M25QDriver *devp) {
|
||||||
qspi_command_t cmd;
|
qspi_command_t cmd;
|
||||||
|
uint8_t buf[1];
|
||||||
|
|
||||||
/* The only mode to generate an odd number of clock cycles is to write
|
/* Resetting XIP mode by reading one byte without XIP confirmation bit.*/
|
||||||
data on 4 lines in DDR mode.*/
|
cmd.cfg = QSPI_CFG_CMD(M25Q_CMD_FAST_READ) |
|
||||||
|
QSPI_CFG_ADDR_SIZE_24 |
|
||||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI1L
|
||||||
cmd.cfg = QSPI_CFG_DUMMY_CYCLES(25);
|
QSPI_CFG_CMD_MODE_ONE_LINE |
|
||||||
|
QSPI_CFG_ADDR_MODE_ONE_LINE |
|
||||||
|
QSPI_CFG_DATA_MODE_ONE_LINE |
|
||||||
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
#elif M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI2L
|
||||||
cmd.cfg = QSPI_CFG_DUMMY_CYCLES(13);
|
QSPI_CFG_CMD_MODE_TWO_LINES |
|
||||||
|
QSPI_CFG_ADDR_MODE_TWO_LINES |
|
||||||
|
QSPI_CFG_DATA_MODE_TWO_LINES |
|
||||||
#else
|
#else
|
||||||
cmd.cfg = QSPI_CFG_CMD(0x11) |
|
|
||||||
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
QSPI_CFG_CMD_MODE_FOUR_LINES |
|
||||||
QSPI_CFG_DUMMY_CYCLES(8) |
|
QSPI_CFG_ADDR_MODE_FOUR_LINES |
|
||||||
QSPI_CFG_DATA_MODE_FOUR_LINES;
|
QSPI_CFG_DATA_MODE_FOUR_LINES |
|
||||||
#endif
|
#endif
|
||||||
cmd.addr = 0U;
|
QSPI_CFG_ALT_MODE_FOUR_LINES | /* Always 4 lines, note.*/
|
||||||
cmd.alt = 0U;
|
QSPI_CFG_DUMMY_CYCLES(M25Q_READ_DUMMY_CYCLES - 2);
|
||||||
qspiSend(devp->config->qspip, &cmd, 2, flash_reset_xip_pattern);
|
cmd.alt = 0xFF;
|
||||||
|
cmd.addr = 0;
|
||||||
|
qspiReceive(devp->config->qspip, &cmd, 1, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_reset_memory(M25QDriver *devp) {
|
||||||
|
|
||||||
|
/* 1x M25Q_CMD_RESET_ENABLE command.*/
|
||||||
|
static const qspi_command_t cmd_reset_enable_1 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
||||||
|
QSPI_CFG_CMD_MODE_ONE_LINE,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 1x M25Q_CMD_RESET_MEMORY command.*/
|
||||||
|
static const qspi_command_t cmd_reset_memory_1 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
||||||
|
QSPI_CFG_CMD_MODE_ONE_LINE,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 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 M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI4L
|
||||||
|
/* 4x M25Q_CMD_RESET_ENABLE command.*/
|
||||||
|
static const qspi_command_t cmd_reset_enable_4 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
||||||
|
QSPI_CFG_CMD_MODE_FOUR_LINES,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 4x M25Q_CMD_RESET_MEMORY command.*/
|
||||||
|
static const qspi_command_t cmd_reset_memory_4 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
||||||
|
QSPI_CFG_CMD_MODE_FOUR_LINES,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_enable_4);
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_memory_4);
|
||||||
|
#else
|
||||||
|
/* 2x M25Q_CMD_RESET_ENABLE command.*/
|
||||||
|
static const qspi_command_t cmd_reset_enable_2 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
|
||||||
|
QSPI_CFG_CMD_MODE_TWO_LINES,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 2x M25Q_CMD_RESET_MEMORY command.*/
|
||||||
|
static const qspi_command_t cmd_reset_memory_2 = {
|
||||||
|
.cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
|
||||||
|
QSPI_CFG_CMD_MODE_TWO_LINES,
|
||||||
|
.addr = 0,
|
||||||
|
.alt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_enable_2);
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_memory_2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now the device should be in one bit mode for sure and we perform a
|
||||||
|
device reset.*/
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_enable_1);
|
||||||
|
qspiCommand(devp->config->qspip, &cmd_reset_memory_1);
|
||||||
}
|
}
|
||||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||||
|
|
||||||
|
@ -911,26 +925,13 @@ void m25qStart(M25QDriver *devp, const M25QConfig *config) {
|
||||||
/* QSPI initialization.*/
|
/* QSPI initialization.*/
|
||||||
qspiStart(devp->config->qspip, devp->config->qspicfg);
|
qspiStart(devp->config->qspip, devp->config->qspicfg);
|
||||||
|
|
||||||
/* Resetting XIP mode on entry.*/
|
/* Attempting a reset of the XIP mode, it could be in an unexpected state
|
||||||
flash_xip_reset(devp);
|
because a CPU reset does not reset the memory too.*/
|
||||||
|
flash_reset_xip(devp);
|
||||||
|
|
||||||
#if M25Q_SWITCH_WIDTH == TRUE
|
/* Attempting a eeset of the device, it could be in an unexpected state
|
||||||
/* If the device is in one bit mode then the following commands are
|
because a CPU reset does not reset the memory too.*/
|
||||||
rejected because shorter than 8 bits. If the device is in multiple
|
flash_reset_memory(devp);
|
||||||
bits mode then the comands are accepted and the device is reset to
|
|
||||||
one bit mode.*/
|
|
||||||
#if M25Q_BUS_MODE == M25Q_BUS_MODE_QSPI4L
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_4);
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_4);
|
|
||||||
#else
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_2);
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_2);
|
|
||||||
#endif
|
|
||||||
/* Now the device should be in one bit mode for sure and we perform a
|
|
||||||
device reset.*/
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_enable_1);
|
|
||||||
qspiCommand(devp->config->qspip, &cmd_reset_memory_1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Reading device ID and unique ID.*/
|
/* Reading device ID and unique ID.*/
|
||||||
qspiReceive(devp->config->qspip, &cmd_read_id,
|
qspiReceive(devp->config->qspip, &cmd_read_id,
|
||||||
|
@ -968,10 +969,16 @@ void m25qStart(M25QDriver *devp, const M25QConfig *config) {
|
||||||
descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) / SECTOR_SIZE;
|
descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) / SECTOR_SIZE;
|
||||||
|
|
||||||
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI)
|
#if (M25Q_BUS_MODE != M25Q_BUS_MODE_SPI)
|
||||||
/* Setting up the dummy cycles to be used for rast read operations.*/
|
{
|
||||||
|
static const uint8_t flash_status[1] = {
|
||||||
|
(M25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Setting up the dummy cycles to be used for fast read operations.*/
|
||||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||||
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||||
1, flash_status);
|
1, flash_status);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Driver in ready state.*/
|
/* Driver in ready state.*/
|
||||||
|
@ -1030,8 +1037,14 @@ void m25qStop(M25QDriver *devp) {
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
||||||
|
static const uint8_t flash_status_xip[1] = {
|
||||||
|
(M25Q_READ_DUMMY_CYCLES << 4U) | 0x07U
|
||||||
|
};
|
||||||
qspi_command_t cmd;
|
qspi_command_t cmd;
|
||||||
|
|
||||||
|
/* Bus acquisition.*/
|
||||||
|
flash_bus_acquire(devp);
|
||||||
|
|
||||||
/* Activating XIP mode in the device.*/
|
/* Activating XIP mode in the device.*/
|
||||||
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
flash_cmd(devp, M25Q_CMD_WRITE_ENABLE);
|
||||||
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
flash_cmd_send(devp, M25Q_CMD_WRITE_V_CONF_REGISTER,
|
||||||
|
@ -1058,6 +1071,9 @@ void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
||||||
QSPI_CFG_DUMMY_CYCLES(M25Q_READ_DUMMY_CYCLES - 2);
|
QSPI_CFG_DUMMY_CYCLES(M25Q_READ_DUMMY_CYCLES - 2);
|
||||||
|
|
||||||
qspiMapFlash(devp->config->qspip, &cmd, addrp);
|
qspiMapFlash(devp->config->qspip, &cmd, addrp);
|
||||||
|
|
||||||
|
/* Bus release.*/
|
||||||
|
flash_bus_release(devp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1069,10 +1085,15 @@ void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp) {
|
||||||
*/
|
*/
|
||||||
void m25qMemoryUnmap(M25QDriver *devp) {
|
void m25qMemoryUnmap(M25QDriver *devp) {
|
||||||
|
|
||||||
|
/* Bus acquisition.*/
|
||||||
|
flash_bus_acquire(devp);
|
||||||
|
|
||||||
qspiUnmapFlash(devp->config->qspip);
|
qspiUnmapFlash(devp->config->qspip);
|
||||||
|
|
||||||
/* Resetting XIP mode.*/
|
flash_reset_xip(devp);
|
||||||
flash_xip_reset(devp);
|
|
||||||
|
/* Bus release.*/
|
||||||
|
flash_bus_release(devp);
|
||||||
}
|
}
|
||||||
#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
|
#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
|
||||||
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
#endif /* M25Q_BUS_MODE != M25Q_BUS_MODE_SPI */
|
||||||
|
|
Loading…
Reference in New Issue