소스 검색

[DeviceDriver] Update SFUD (Serial Flash Universal Driver) library to latest version.

armink 6 년 전
부모
커밋
3b20db1903

+ 18 - 1
components/drivers/spi/sfud/inc/sfud.h

@@ -1,7 +1,7 @@
 /*
  * This file is part of the Serial Flash Universal Driver Library.
  *
- * Copyright (c) 2016, Armink, <armink.ztl@gmail.com>
+ * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -75,6 +75,23 @@ size_t sfud_get_device_num(void);
  */
 const sfud_flash *sfud_get_device_table(void);
 
+#ifdef SFUD_USING_QSPI
+/**
+ * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
+ *
+ * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
+ * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
+ *
+ * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
+ *
+ * @param flash flash device
+ * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
+ *
+ * @return result
+ */
+sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width);
+#endif /* SFUD_USING_QSPI */
+
 /**
  * read flash data
  *

+ 7 - 0
components/drivers/spi/sfud/inc/sfud_cfg.h

@@ -45,6 +45,13 @@
 #define SFUD_USING_SFDP
 #endif
 
+/**
+ * SFUD will support QSPI mode.
+ */
+#ifdef RT_SFUD_USING_QSPI
+#define SFUD_USING_QSPI
+#endif
+
 /**
  * Using probe flash JEDEC ID then query defined supported flash chip information table. @see SFUD_FLASH_CHIP_TABLE
  */

+ 43 - 3
components/drivers/spi/sfud/inc/sfud_def.h

@@ -1,7 +1,7 @@
 /*
  * This file is part of the Serial Flash Universal Driver Library.
  *
- * Copyright (c) 2016, Armink, <armink.ztl@gmail.com>
+ * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -78,7 +78,7 @@ if (!(EXPR))                                                                   \
     else {if (__delay_temp) {__delay_temp();} retry --;}
 
 /* software version number */
-#define SFUD_SW_VERSION                             "1.0.6"
+#define SFUD_SW_VERSION                             "1.1.0"
 /*
  * all defined supported command
  */
@@ -118,6 +118,22 @@ if (!(EXPR))                                                                   \
 #define SFUD_CMD_READ_DATA                             0x03
 #endif
 
+#ifndef SFUD_CMD_DUAL_OUTPUT_READ_DATA 
+#define SFUD_CMD_DUAL_OUTPUT_READ_DATA                 0x3B
+#endif
+
+#ifndef SFUD_CMD_DUAL_IO_READ_DATA 
+#define SFUD_CMD_DUAL_IO_READ_DATA                     0xBB
+#endif
+
+#ifndef SFUD_CMD_QUAD_IO_READ_DATA
+#define SFUD_CMD_QUAD_IO_READ_DATA                     0xEB
+#endif
+
+#ifndef SFUD_CMD_QUAD_OUTPUT_READ_DATA
+#define SFUD_CMD_QUAD_OUTPUT_READ_DATA                 0x6B
+#endif
+
 #ifndef SFUD_CMD_MANUFACTURER_DEVICE_ID
 #define SFUD_CMD_MANUFACTURER_DEVICE_ID                0x90
 #endif
@@ -183,6 +199,21 @@ typedef enum {
     SFUD_ERR_ADDR_OUT_OF_BOUND = 5,                        /**< address is out of flash bound */
 } sfud_err;
 
+#ifdef SFUD_USING_QSPI
+/**
+ * QSPI flash read cmd format
+ */
+typedef struct {
+    uint8_t instruction;
+    uint8_t instruction_lines;
+    uint8_t address_size;
+    uint8_t address_lines;
+    uint8_t alternate_bytes_lines;
+    uint8_t dummy_cycles;
+    uint8_t data_lines;
+} sfud_qspi_read_cmd_format;
+#endif /* SFUD_USING_QSPI */
+
 /* SPI bus write read data function type */
 typedef sfud_err (*spi_write_read_func)(const uint8_t *write_buf, size_t write_size, uint8_t *read_buf, size_t read_size);
 
@@ -218,7 +249,12 @@ typedef struct __sfud_spi {
     char *name;
     /* SPI bus write read data function */
     sfud_err (*wr)(const struct __sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
-            size_t read_size);
+                   size_t read_size);
+#ifdef SFUD_USING_QSPI
+    /* QSPI fast read function */
+    sfud_err (*qspi_read)(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format,
+                          uint8_t *read_buf, size_t read_size);
+#endif
     /* lock SPI bus */
     void (*lock)(const struct __sfud_spi *spi);
     /* unlock SPI bus */
@@ -243,6 +279,10 @@ typedef struct {
     } retry;
     void *user_data;                             /**< some user data */
 
+#ifdef SFUD_USING_QSPI
+    sfud_qspi_read_cmd_format read_cmd_format;   /**< fast read cmd format */
+#endif
+
 #ifdef SFUD_USING_SFDP
     sfud_sfdp sfdp;                              /**< serial flash discoverable parameters by JEDEC standard */
 #endif

+ 48 - 2
components/drivers/spi/sfud/inc/sfud_flash_def.h

@@ -1,7 +1,7 @@
 /*
  * This file is part of the Serial Flash Universal Driver Library.
  *
- * Copyright (c) 2016-2017, Armink, <armink.ztl@gmail.com>
+ * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -59,11 +59,21 @@ typedef struct {
     uint8_t type_id;                             /**< memory type ID */
     uint8_t capacity_id;                         /**< capacity ID */
     uint32_t capacity;                           /**< flash capacity (bytes) */
-    uint16_t write_mode;                         /**< write mode  @see sfud_write_mode */
+    uint16_t write_mode;                         /**< write mode @see sfud_write_mode */
     uint32_t erase_gran;                         /**< erase granularity (bytes) */
     uint8_t erase_gran_cmd;                      /**< erase granularity size block command */
 } sfud_flash_chip;
 
+#ifdef SFUD_USING_QSPI
+/* QSPI flash chip's extended information compared with SPI flash */
+typedef struct {
+    uint8_t mf_id;                               /**< manufacturer ID */
+    uint8_t type_id;                             /**< memory type ID */
+    uint8_t capacity_id;                         /**< capacity ID */
+    uint8_t read_mode;                           /**< supported read mode on this qspi flash chip */
+} sfud_qspi_flash_ext_info;
+#endif
+
 /* SFUD support manufacturer JEDEC ID */
 #define SFUD_MF_ID_CYPRESS                             0x01
 #define SFUD_MF_ID_FUJITSU                             0x04
@@ -131,6 +141,42 @@ typedef struct {
 }
 #endif /* SFUD_USING_FLASH_INFO_TABLE */
 
+#ifdef SFUD_USING_QSPI
+/* This table saves flash read-fast instructions in QSPI mode, 
+ * SFUD can use this table to select the most appropriate read instruction for flash.
+ * | mf_id | type_id | capacity_id | qspi_read_mode |
+ */
+#define SFUD_FLASH_EXT_INFO_TABLE                                                                  \
+{                                                                                                  \
+    /* W25Q40BV */                                                                                 \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x13, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
+    /* W25Q80JV */                                                                                 \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
+    /* W25Q16BV */                                                                                 \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
+    /* W25Q32BV */                                                                                 \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
+    /* W25Q64JV */                                                                                 \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
+    /* W25Q128JV */                                                                                \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
+    /* W25Q256FV */                                                                                \
+    {SFUD_MF_ID_WINBOND, 0x40, 0x19, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
+    /* EN25Q32B */                                                                                 \
+    {SFUD_MF_ID_EON, 0x30, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_IO},                             \
+    /* S25FL216K */                                                                                \
+    {SFUD_MF_ID_CYPRESS, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
+    /* A25L080 */                                                                                  \
+    {SFUD_MF_ID_AMIC, 0x30, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO},                            \
+    /* A25LQ64 */                                                                                  \
+    {SFUD_MF_ID_AMIC, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_IO},                    \
+    /* MX25L3206E and KH25L3206E */                                                                \
+    {SFUD_MF_ID_MICRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT},                                \
+    /* GD25Q64B */                                                                                 \
+    {SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT},                              \
+}
+#endif /* SFUD_USING_QSPI */
+
 #ifdef __cplusplus
 }
 #endif

+ 119 - 8
components/drivers/spi/sfud/src/sfud.c

@@ -1,7 +1,7 @@
 /*
  * This file is part of the Serial Flash Universal Driver Library.
  *
- * Copyright (c) 2016, Armink, <armink.ztl@gmail.com>
+ * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -46,6 +46,22 @@ static const sfud_mf mf_table[] = SFUD_MF_TABLE;
 static const sfud_flash_chip flash_chip_table[] = SFUD_FLASH_CHIP_TABLE;
 #endif
 
+#ifdef SFUD_USING_QSPI
+/**
+ * flash read data mode
+ */
+enum sfud_qspi_read_mode {
+    NORMAL_SPI_READ = 1 << 0,               /**< mormal spi read mode */
+    DUAL_OUTPUT = 1 << 1,                   /**< qspi fast read dual output */
+    DUAL_IO = 1 << 2,                       /**< qspi fast read dual input/output */
+    QUAD_OUTPUT = 1 << 3,                   /**< qspi fast read quad output */
+    QUAD_IO = 1 << 4,                       /**< qspi fast read quad input/output */
+};
+
+/* QSPI flash chip's extended information table */
+static const sfud_qspi_flash_ext_info qspi_flash_ext_info_table[] = SFUD_FLASH_EXT_INFO_TABLE;
+#endif /* SFUD_USING_QSPI */
+
 static sfud_err software_init(const sfud_flash *flash);
 static sfud_err hardware_init(sfud_flash *flash);
 static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
@@ -146,11 +162,89 @@ const sfud_flash *sfud_get_device_table(void) {
     return flash_table;
 }
 
+#ifdef SFUD_USING_QSPI
+static void qspi_set_read_cmd_format(sfud_flash *flash, uint8_t ins, uint8_t ins_lines, uint8_t addr_lines,
+        uint8_t dummy_cycles, uint8_t data_lines) {
+    /* if medium size greater than 16Mb, use 4-Byte address, instruction should be added one */
+    if (flash->chip.capacity <= 0x1000000) {
+        flash->read_cmd_format.instruction = ins;
+        flash->read_cmd_format.address_size = 24;
+    } else {
+        flash->read_cmd_format.instruction = ins + 1;
+        flash->read_cmd_format.address_size = 32;
+    }
+
+    flash->read_cmd_format.instruction_lines = ins_lines;
+    flash->read_cmd_format.address_lines = addr_lines;
+    flash->read_cmd_format.alternate_bytes_lines = 0;
+    flash->read_cmd_format.dummy_cycles = dummy_cycles;
+    flash->read_cmd_format.data_lines = data_lines;
+}
+
+/**
+ * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
+ *
+ * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
+ * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
+ *
+ * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
+ *
+ * @param flash flash device
+ * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
+ *
+ * @return result
+ */
+sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width) {
+    size_t i = 0;
+    uint8_t read_mode = NORMAL_SPI_READ;
+    sfud_err result = SFUD_SUCCESS;
+
+    SFUD_ASSERT(flash);
+    SFUD_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
+
+    /* get read_mode, If don't found, the default is SFUD_QSPI_NORMAL_SPI_READ */
+    for (i = 0; i < sizeof(qspi_flash_ext_info_table) / sizeof(sfud_qspi_flash_ext_info); i++) {
+        if ((qspi_flash_ext_info_table[i].mf_id == flash->chip.mf_id)
+                && (qspi_flash_ext_info_table[i].type_id == flash->chip.type_id)
+                && (qspi_flash_ext_info_table[i].capacity_id == flash->chip.capacity_id)) {
+            read_mode = qspi_flash_ext_info_table[i].read_mode;
+        }
+    }
+
+    /* determine qspi supports which read mode and set read_cmd_format struct */
+    switch (data_line_width) {
+    case 1:
+        qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+        break;
+    case 2:
+        if (read_mode & DUAL_IO) {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 8, 2);
+        } else if (read_mode & DUAL_OUTPUT) {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_OUTPUT_READ_DATA, 1, 1, 8, 2);
+        } else {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+        }
+        break;
+    case 4:
+        if (read_mode & QUAD_IO) {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_IO_READ_DATA, 1, 4, 6, 4);
+        } else if (read_mode & QUAD_OUTPUT) {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_OUTPUT_READ_DATA, 1, 1, 8, 4);
+        } else {
+            qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+        }
+        break;
+    }
+
+    return result;
+}
+#endif /* SFUD_USING_QSPI */
+
 /**
  * hardware initialize
  */
 static sfud_err hardware_init(sfud_flash *flash) {
-    extern sfud_err sfud_spi_port_init(sfud_flash *flash);
+    extern sfud_err sfud_spi_port_init(sfud_flash * flash);
 
     sfud_err result = SFUD_SUCCESS;
     size_t i;
@@ -162,6 +256,9 @@ static sfud_err hardware_init(sfud_flash *flash) {
         return result;
     }
 
+    /* set default read instruction */
+    flash->read_cmd_format.instruction = SFUD_CMD_READ_DATA;
+
     /* SPI write read function must be initialize */
     SFUD_ASSERT(flash->spi.wr);
     /* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
@@ -315,10 +412,17 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t
     result = wait_busy(flash);
 
     if (result == SFUD_SUCCESS) {
-        cmd_data[0] = SFUD_CMD_READ_DATA;
-        make_adress_byte_array(flash, addr, &cmd_data[1]);
-        cmd_size = flash->addr_in_4_byte ? 5 : 4;
-        result = spi->wr(spi, cmd_data, cmd_size, data, size);
+#ifdef SFUD_USING_QSPI
+        if (flash->read_cmd_format.instruction != SFUD_CMD_READ_DATA) {
+            result = spi->qspi_read(spi, addr, (sfud_qspi_read_cmd_format *)&flash->read_cmd_format, data, size);
+        } else
+#endif
+        {
+            cmd_data[0] = SFUD_CMD_READ_DATA;
+            make_adress_byte_array(flash, addr, &cmd_data[1]);
+            cmd_size = flash->addr_in_4_byte ? 5 : 4;
+            result = spi->wr(spi, cmd_data, cmd_size, data, size);
+        }
     }
     /* unlock SPI */
     if (spi->unlock) {
@@ -328,7 +432,6 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t
     return result;
 }
 
-
 /**
  * erase all flash data
  *
@@ -715,8 +818,16 @@ static sfud_err reset(const sfud_flash *flash) {
     SFUD_ASSERT(flash);
 
     cmd_data[0] = SFUD_CMD_ENABLE_RESET;
+    result = spi->wr(spi, cmd_data, 1, NULL, 0);
+    if (result == SFUD_SUCCESS) {
+        result = wait_busy(flash);
+    } else {
+        SFUD_INFO("Error: Flash device reset failed.");
+        return result;
+    }
+
     cmd_data[1] = SFUD_CMD_RESET;
-    result = spi->wr(spi, cmd_data, 2, NULL, 0);
+    result = spi->wr(spi, &cmd_data[1], 1, NULL, 0);
 
     if (result == SFUD_SUCCESS) {
         result = wait_busy(flash);