38 #define PAGE_SIZE 256U 39 #define PAGE_MASK (PAGE_SIZE - 1U) 41 #if M25Q_USE_SUB_SECTORS == TRUE 42 #define SECTOR_SIZE 0x00001000U 43 #define CMD_SECTOR_ERASE M25Q_CMD_SUBSECTOR_ERASE 45 #define SECTOR_SIZE 0x00010000U 46 #define CMD_SECTOR_ERASE M25Q_CMD_SECTOR_ERASE 59 size_t n, uint8_t *rp);
61 size_t n,
const uint8_t *pp);
65 static flash_error_t m25q_query_erase(
void *instance, uint32_t *msec);
68 size_t n, uint8_t *rp);
75 m25q_get_descriptor, m25q_read, m25q_program,
76 m25q_start_erase_all, m25q_start_erase_sector,
77 m25q_query_erase, m25q_verify_erase,
85 .
attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
86 FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
90 .sectors_size = SECTOR_SIZE,
94 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI 97 .cfg = QSPI_CFG_CMD(M25Q_CMD_READ_ID) |
98 #if M25Q_SWITCH_WIDTH == TRUE 99 QSPI_CFG_CMD_MODE_ONE_LINE |
100 QSPI_CFG_DATA_MODE_ONE_LINE,
102 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 103 QSPI_CFG_CMD_MODE_ONE_LINE |
104 QSPI_CFG_DATA_MODE_ONE_LINE,
105 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 106 QSPI_CFG_CMD_MODE_TWO_LINES |
107 QSPI_CFG_DATA_MODE_TWO_LINES,
109 QSPI_CFG_CMD_MODE_FOUR_LINES |
110 QSPI_CFG_DATA_MODE_FOUR_LINES,
119 .cfg = QSPI_CFG_CMD(M25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER) |
120 #if M25Q_SWITCH_WIDTH == TRUE 121 QSPI_CFG_CMD_MODE_ONE_LINE |
122 QSPI_CFG_DATA_MODE_ONE_LINE,
124 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 125 QSPI_CFG_CMD_MODE_ONE_LINE |
126 QSPI_CFG_DATA_MODE_ONE_LINE,
127 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 128 QSPI_CFG_CMD_MODE_TWO_LINES |
129 QSPI_CFG_DATA_MODE_TWO_LINES,
131 QSPI_CFG_CMD_MODE_FOUR_LINES |
132 QSPI_CFG_DATA_MODE_FOUR_LINES,
141 .cfg = QSPI_CFG_CMD(M25Q_CMD_WRITE_ENABLE) |
142 #if M25Q_SWITCH_WIDTH == TRUE 143 QSPI_CFG_CMD_MODE_ONE_LINE,
145 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 146 QSPI_CFG_CMD_MODE_ONE_LINE,
147 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 148 QSPI_CFG_CMD_MODE_TWO_LINES,
150 QSPI_CFG_CMD_MODE_FOUR_LINES,
158 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 159 static const uint8_t m25q_evconf_value[1] = {0xCF};
160 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 161 static const uint8_t m25q_evconf_value[1] = {0x8F};
163 static const uint8_t m25q_evconf_value[1] = {0x4F};
174 static bool m25q_find_id(
const uint8_t *
set,
size_t size, uint8_t element) {
177 for (i = 0; i < size; i++) {
178 if (
set[i] == element) {
185 #if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__) 187 static const uint8_t flash_conf[1] = {
196 cmd.cfg = QSPI_CFG_CMD_MODE_NONE |
197 QSPI_CFG_ADDR_SIZE_24 |
198 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 199 QSPI_CFG_ADDR_MODE_ONE_LINE |
200 QSPI_CFG_DATA_MODE_ONE_LINE |
201 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 202 QSPI_CFG_ADDR_MODE_TWO_LINES |
203 QSPI_CFG_DATA_MODE_TWO_LINES |
205 QSPI_CFG_ADDR_MODE_FOUR_LINES |
206 QSPI_CFG_DATA_MODE_FOUR_LINES |
208 QSPI_CFG_ALT_MODE_FOUR_LINES |
209 QSPI_CFG_ALT_SIZE_8 |
214 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
217 jesd216_cmd_send(devp->
config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
225 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
226 QSPI_CFG_CMD_MODE_ONE_LINE,
233 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
234 QSPI_CFG_CMD_MODE_ONE_LINE,
243 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI4L 246 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
247 QSPI_CFG_CMD_MODE_FOUR_LINES,
254 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
255 QSPI_CFG_CMD_MODE_FOUR_LINES,
265 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_ENABLE) |
266 QSPI_CFG_CMD_MODE_TWO_LINES,
273 .cfg = QSPI_CFG_CMD(M25Q_CMD_RESET_MEMORY) |
274 QSPI_CFG_CMD_MODE_TWO_LINES,
294 #if M25Q_NICE_WAITING == TRUE 298 jesd216_cmd_receive(devp->
config->busp, M25Q_CMD_READ_FLAG_STATUS_REGISTER,
300 }
while ((sts & M25Q_FLAGS_PROGRAM_ERASE) == 0U);
303 if ((sts & M25Q_FLAGS_ALL_ERRORS) != 0U) {
305 jesd216_cmd(devp->
config->busp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
308 return FLASH_ERROR_PROGRAM;
311 return FLASH_NO_ERROR;
318 osalDbgAssert((devp->state != FLASH_UNINIT) && (devp->state != FLASH_STOP),
325 size_t n, uint8_t *rp) {
328 osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
331 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
334 if (devp->state == FLASH_ERASE) {
335 return FLASH_BUSY_ERASING;
339 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
342 devp->state = FLASH_READ;
344 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI 346 jesd216_cmd_addr_dummy_receive(devp->
config->busp, M25Q_CMD_FAST_READ,
350 jesd216_cmd_addr_receive(devp->
config->busp, M25Q_CMD_READ,
355 devp->state = FLASH_READY;
358 jesd216_bus_release(devp->
config->busp);
360 return FLASH_NO_ERROR;
364 size_t n,
const uint8_t *pp) {
367 osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
370 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
373 if (devp->state == FLASH_ERASE) {
374 return FLASH_BUSY_ERASING;
378 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
381 devp->state = FLASH_PGM;
388 size_t chunk = (size_t)(((offset | PAGE_MASK) + 1U) - offset);
394 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
397 jesd216_cmd_addr_send(devp->
config->busp, M25Q_CMD_PAGE_PROGRAM, offset,
401 err = m25q_poll_status(devp);
402 if (err != FLASH_NO_ERROR) {
405 jesd216_bus_release(devp->
config->busp);
417 devp->state = FLASH_READY;
420 jesd216_bus_release(devp->
config->busp);
422 return FLASH_NO_ERROR;
429 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
432 if (devp->state == FLASH_ERASE) {
433 return FLASH_BUSY_ERASING;
437 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
440 devp->state = FLASH_ERASE;
443 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
446 jesd216_cmd(devp->
config->busp, M25Q_CMD_BULK_ERASE);
449 jesd216_bus_release(devp->
config->busp);
451 return FLASH_NO_ERROR;
461 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
464 if (devp->state == FLASH_ERASE) {
465 return FLASH_BUSY_ERASING;
469 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
472 devp->state = FLASH_ERASE;
475 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
478 jesd216_cmd_addr(devp->
config->busp, M25Q_CMD_SECTOR_ERASE, offset);
481 jesd216_bus_release(devp->
config->busp);
483 return FLASH_NO_ERROR;
495 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
498 if (devp->state == FLASH_ERASE) {
499 return FLASH_BUSY_ERASING;
503 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
506 devp->state = FLASH_READ;
514 #if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI 515 jesd216_cmd_addr_dummy_receive(devp->
config->busp, M25Q_CMD_FAST_READ,
517 sizeof cmpbuf, cmpbuf);
520 jesd216_cmd_addr_receive(devp->
config->busp, M25Q_CMD_READ,
521 offset,
sizeof cmpbuf, cmpbuf);
528 devp->state = FLASH_READY;
531 jesd216_bus_release(devp->
config->busp);
533 return FLASH_ERROR_VERIFY;
537 offset +=
sizeof cmpbuf;
542 devp->state = FLASH_READY;
545 jesd216_bus_release(devp->
config->busp);
547 return FLASH_NO_ERROR;
550 static flash_error_t m25q_query_erase(
void *instance, uint32_t *msec) {
555 osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
559 if (devp->state == FLASH_ERASE) {
562 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
565 jesd216_cmd_receive(devp->
config->busp, M25Q_CMD_READ_FLAG_STATUS_REGISTER,
570 if (((sts & M25Q_FLAGS_PROGRAM_ERASE) == 0U) ||
571 ((sts & M25Q_FLAGS_ERASE_SUSPEND) != 0U)) {
574 jesd216_bus_release(devp->
config->busp);
582 return FLASH_BUSY_ERASING;
586 devp->state = FLASH_READY;
589 if ((sts & M25Q_FLAGS_ALL_ERRORS) != 0U) {
592 jesd216_cmd(devp->
config->busp, M25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
595 return FLASH_ERROR_ERASE;
599 jesd216_bus_release(devp->
config->busp);
602 return FLASH_NO_ERROR;
606 size_t n, uint8_t *rp) {
613 return FLASH_NO_ERROR;
632 devp->state = FLASH_STOP;
651 if (devp->state == FLASH_STOP) {
654 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
656 #if JESD216_BUS_MODE == JESD216_BUS_MODE_SPI 658 jesd216_cmd_receive(devp->
config->busp, M25Q_CMD_READ_ID,
664 m25q_reset_xip(devp);
668 m25q_reset_memory(devp);
677 sizeof m25q_manufacturer_ids,
679 "invalid manufacturer id");
681 sizeof m25q_memory_type_ids,
683 "invalid memory type id");
685 #if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (M25Q_SWITCH_WIDTH == TRUE) 688 qspiSend(devp->
config->busp, &m25q_cmd_write_evconf, 1, m25q_evconf_value);
694 jesd216_cmd_receive(devp->
config->busp, M25Q_CMD_MULTIPLE_IO_READ_ID,
699 "id confirmation failed");
707 #if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) 709 static const uint8_t flash_conf[1] = {
714 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
715 jesd216_cmd_send(devp->
config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
721 devp->state = FLASH_READY;
724 jesd216_bus_release(devp->
config->busp);
740 if (devp->state != FLASH_STOP) {
743 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
746 jesd216_stop(devp->
config->busp);
752 devp->state = FLASH_STOP;
755 jesd216_bus_release(devp->
config->busp);
759 #if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__) 760 #if (QSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) 774 static const uint8_t flash_status_xip[1] = {
780 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
783 jesd216_cmd(devp->
config->busp, M25Q_CMD_WRITE_ENABLE);
784 jesd216_cmd_send(devp->
config->busp, M25Q_CMD_WRITE_V_CONF_REGISTER,
785 1, flash_status_xip);
788 cmd.cfg = QSPI_CFG_CMD(M25Q_CMD_FAST_READ) |
789 QSPI_CFG_ADDR_SIZE_24 |
790 #if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L 791 QSPI_CFG_CMD_MODE_ONE_LINE |
792 QSPI_CFG_ADDR_MODE_ONE_LINE |
793 QSPI_CFG_DATA_MODE_ONE_LINE |
794 #elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L 795 QSPI_CFG_CMD_MODE_TWO_LINES |
796 QSPI_CFG_ADDR_MODE_TWO_LINES |
797 QSPI_CFG_DATA_MODE_TWO_LINES |
799 QSPI_CFG_CMD_MODE_FOUR_LINES |
800 QSPI_CFG_ADDR_MODE_FOUR_LINES |
801 QSPI_CFG_DATA_MODE_FOUR_LINES |
803 QSPI_CFG_ALT_MODE_FOUR_LINES |
804 QSPI_CFG_ALT_SIZE_8 |
811 jesd216_bus_release(devp->
config->busp);
824 jesd216_bus_acquire(devp->
config->busp, devp->
config->buscfg);
828 m25q_reset_xip(devp);
831 jesd216_bus_release(devp->
config->busp);
uint8_t device_id[20]
Device ID and unique ID.
uint32_t flash_sector_t
Type of a flash sector number.
void m25qMemoryMap(M25QDriver *devp, uint8_t **addrp)
Enters the memory Mapping mode.
#define M25Q_SUPPORTED_MEMORY_TYPE_IDS
Supported memory type identifiers.
uint32_t attributes
Device_attributes.
void m25qObjectInit(M25QDriver *devp)
Initializes an instance.
void qspiUnmapFlash(QSPIDriver *qspip)
Unmaps from memory space a QSPI flash device.
const struct M25QDriverVMT * vmt
M25QDriver Virtual Methods Table.
#define M25Q_READ_DUMMY_CYCLES
Number of dummy cycles for fast read (1..15).
uint32_t sectors_size
Size of sectors for devices with uniform sector size.
void m25qStart(M25QDriver *devp, const M25QConfig *config)
Configures and activates N25Q128 driver.
static flash_descriptor_t m25q_descriptor
N25Q128 descriptor.
#define osalThreadSleepMilliseconds(msecs)
Delays the invoking thread for the specified number of milliseconds.
Type of M25Q flash class.
void m25qStop(M25QDriver *devp)
Deactivates the N25Q128 driver.
Type of a flash device descriptor.
M25Q virtual methods table.
Micron serial flash driver header.
static const struct M25QDriverVMT m25q_vmt
Virtual methods table.
void qspiReceive(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, uint8_t *rxbuf)
Sends a command then receives data over the QSPI bus.
flash_error_t
Type of a flash error code.
#define osalDbgCheck(c)
Function parameters check.
#define M25Q_SUPPORTED_MANUFACTURE_IDS
Supported JEDEC manufacturer identifiers.
#define M25Q_COMPARE_BUFFER_SIZE
Size of the compare buffer.
_jesd216_flash_data const M25QConfig * config
Current configuration data.
void qspiSend(QSPIDriver *qspip, const qspi_command_t *cmdp, size_t n, const uint8_t *txbuf)
Sends a command with data over the QSPI bus.
uint32_t flash_offset_t
Type of a flash offset.
void m25qMemoryUnmap(M25QDriver *devp)
Leaves the memory Mapping mode.
void qspiMapFlash(QSPIDriver *qspip, const qspi_command_t *cmdp, uint8_t **addrp)
Maps in memory space a QSPI flash device.
void qspiCommand(QSPIDriver *qspip, const qspi_command_t *cmdp)
Sends a command without data phase.
#define osalDbgAssert(c, remark)
Condition assertion.
Type of a M25Q configuration structure.
flash_sector_t sectors_count
Number of sectors in the device.
Type of a QSPI command descriptor.