Skip to content

Spi Nand Flash Usage Guide*

Notes:

  • Flash operation addresses start from 0 and should not exceed the maximum flash size.
  • Erase must be performed before writing data.
  • Write/Read: Operation addresses should be aligned to page (2K) size, and the length should also be an integer multiple of the page size.
  • Erase: Operation addresses should be aligned to block (128K) size, and the erase size should also be an integer multiple of the block size.
  • Bad blocks do not need to be handled when calling read, write, erase interfaces; the driver handles them internally.

Example locations:

  • Example App Demo: app/spi_nand_flash_sample/spi_nand_flash_sample.c
  • Default configuration: configs/release/nationalchip/grus_gx8002b_dev_1v4_spi_nand_flash_sample.config

Usage:

$ cp configs/release/nationalchip/grus_gx8002b_dev_1v4_spi_nand_flash_sample.config .config
$ make defconfig
$ make clean;make
After compilation, flash the board and run.

2. Pin Multiplexing Notes*

Ensure the Spi Master pin multiplexing is configured correctly.

  • Run make menuconfig
  • Enter Board Options
  • Select BOARD_HAS_SPI_MASTER

The file boards/nationalchip/grus_gx8002b_dev_1v/misc_board.c performs the relevant configuration.

#if defined(CONFIG_BOARD_HAS_SPI_MASTER)
    ret += _BoardPadmuxSet(7, 4);
    ret += _BoardPadmuxSet(8, 4);
    ret += _BoardPadmuxSet(9, 4);
    ret += _BoardPadmuxSet(10, 4);
#endif

3.1. Header File Inclusion:*

#include <board_config.h>
#include <driver/gx_flash.h>

3.2. Initialization Notes:*

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
GX_FLASH_DEV *flash = NULL;
int spi_nand_flash_init(void)
{
    extern GX_FLASH_DEV spi_nand_flash_dev;
    flash = spi_nand_flash_dev.init(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);

    if (flash == NULL) {
        printf("spi_nand_flash_dev init fail !!!\n", __LINE__);

        return -1;
    }
}

3.3. Read, Write, Erase Notes:*

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
uint8_t test_data[4096] = {0};
int spi_nand_flash_test(void)
{
    printf(LOG_TAG"Test start\n");

    // Prepare test data
    for (int i = 0; i < sizeof(test_data); i++) {
        test_data[i] = i % 256;
    }

    // Read/write operation addresses should be page (2K) aligned
    unsigned int test_flash_addr = 0x400000 - 0x1000;

    // 1. Print current flash bad block information; if any bad blocks exist, they will be printed
    gx_spi_flash_badinfo(flash);

    // 2. Check whether the address is a bad block; returns 1: bad block, 0: not a bad block
    ret = gx_spi_flash_block_isbad(flash, test_flash_addr);
    printf(LOG_TAG"addr: %#x isbad? %s\n", test_flash_addr, ret == 1 ? "yes" : "no");

    // 3. Erase; address must be block (128K) aligned, erase size should be a multiple of block (128K). Bad blocks are skipped, and erasing continues to the next block until the erase length is satisfied.
    // [Note: If the erase length is not a multiple of the block size, no error is reported; it will be rounded up to the nearest block multiple for erasing]
    int block_size = gx_spi_flash_getinfo(flash, GX_FLASH_BLOCK_SIZE);
    int block_num = gx_spi_flash_getinfo(flash, GX_FLASH_BLOCK_NUM);
    ret = gx_spi_flash_erasedata(flash, 0x0, block_size * block_num);   // Erase all
    if (ret < 0)
        printf(LOG_TAG"erasedata error %d\n",  ret);
    else
        printf(LOG_TAG"erasedata success\n");

    // 4. Write; address must be page (2K) aligned, length should be a multiple of page (2K). Bad blocks are skipped, and data is written to the next block until the write length is satisfied.
    // [Note: If the write length is not a multiple of the page size, no error is reported; only the specified length is written. However, the unwritten portion after this page cannot be written again; it can only be written after erasing the block]
    ret = gx_spi_flash_pageprogram(flash, test_flash_addr, test_data, sizeof(test_data));
    if (ret < 0)
        printf(LOG_TAG"write data error %d\n",  ret);
    else if (ret >= sizeof(test_data))
        printf(LOG_TAG"write data success, len: %d\n",  ret);

    // Clear the location to be read
    memset(test_data, 0, sizeof(test_data));
    for (int i = 0; i < sizeof(test_data); i++) {
        if (test_data[i] != 0)
            printf(LOG_TAG"error index [%d] is not 0: %d", i, test_data[i]);
    }

    // 5. Read; address must be page (2K) aligned, length should be a multiple of page (2K). Bad blocks are skipped, and data is read from the next block until the read length is satisfied.
    // [Note: If the read length is not a multiple of the page size, no error is reported; only the specified length is read]
    ret = gx_spi_flash_readdata(flash, test_flash_addr, test_data, sizeof(test_data));
    if (ret < 0)
        printf(LOG_TAG"readdata error %d\n",  ret);
    else if (ret >= sizeof(test_data))
        printf(LOG_TAG"readdata success, len: %d\n",  ret);

    // Compare the read data with the written data
    for (int i = 0; i < sizeof(test_data); i++) {
        if (test_data[i] != (i % 256))
            printf(LOG_TAG"error index[%d] read(%d) != write(%d)\n", i, test_data[i], i % 256);
    }
    printf(LOG_TAG"Test Successful\n");

    return 0;
}