This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/MSP432P401R: FatFS with EEPROM?

Guru 18625 points

Part Number: MSP432P401R

Tool/software: TI-RTOS

Dear,

I just read

http://dev.ti.com/tirex/content/simplelink_cc13x0_sdk_1_40_00_10/docs/simplelink_mcu_sdk/Users_Guide.html#making-choices-for-your-application

in the section FatFS, it seems RTOS provides drivers for using this filesystem with SD cards (SDSPI) and USB devices.

However, I was wondering if there is any issue in trying to use FatFS with a SPI 1Gbit flash memory.

  1. Is the implementation of such driver a realistic effort? I plan to use MSP432. Memory would be not accessed very often.
  2. Are there similar examples and/or documentation related to this case you would recommend me? I will look into this thread meanwhile:

Please let me know and have a beautiful weekend.

  • Are you thinking of NOR or NAND flash?

    Serial NOR flash presents a fairly simple byte/small-block interface familiar to anyone who has worked with a serial EEPROM device. You could probably write a FATFS driver for a NOR device pretty easily. (You might even be able to adapt the one from that Wiki article.)

    Serial NAND presents a much more complex interface -- a thin veneer over a parallel NAND device -- with a page buffer, ECC, and bad blocks. I've written drivers for a few of these (both serial and bus-banging) and they aren't trivial.
  • Hi Kazola,

    You could certainly implement FatFs with a spi flash chip. The FatFs website has documentation on how to do this.

    However our NVS API has support for some spi flash parts and we also support the third party SPIFFS library. SPIFFS is intended to provide configurable file systems on spi flash parts. In our NVSSPI25X.h, it lists compatible parts:

     *  # Overview #
     *
     *  The NVSSPI25X module allows you to manage SPI flash memory.
     *  This driver works with most 256 byte/page SPI flash memory devices
     *  such as:
     *
     *      Winbond     W25xx   family
     *      Macronics   MX25Rxx family
     *      Micron      N25Qxx  family

    You can start with our spiffsinternal example shipped with the latest MSP432P401R SDK. This example usually uses internal flash but it is easy to change it to use spi flash. I hooked up my spi flash breakout board as follows:

    CS - P4.6

    CLK - P2.5

    Data Out - P2.7

    Data In - P2.6

    Vcc - 3.3V

    GND - GND

    You should modify the NVS section of MSP_EXP432P401R.c to look as follows:

    /*
     *  =============================== NVS ===============================
     */
    #include <ti/drivers/NVS.h>
    #include <ti/drivers/nvs/NVSMSP432.h>
    #include <ti/drivers/nvs/NVSSPI25X.h>
    
    #define SECTORSIZE       0x1000
    #define NVS_REGIONS_BASE 0x30000
    #define REGIONSIZE       (SECTORSIZE * 16)
    
    /*
     * Reserve flash sectors for NVS driver use
     * by placing an uninitialized byte array
     * at the desired flash address.
     */
    #if defined(__TI_COMPILER_VERSION__)
    
    /*
     * Place uninitialized array at NVS_REGIONS_BASE
     */
    #pragma LOCATION(flashBuf, NVS_REGIONS_BASE);
    #pragma NOINIT(flashBuf);
    static char flashBuf[REGIONSIZE];
    
    #elif defined(__IAR_SYSTEMS_ICC__)
    
    /*
     * Place uninitialized array at NVS_REGIONS_BASE
     */
    static __no_init char flashBuf[REGIONSIZE] @ NVS_REGIONS_BASE;
    
    #elif defined(__GNUC__)
    
    /*
     * Place the flash buffers in the .nvs section created in the gcc linker file.
     * The .nvs section enforces alignment on a sector boundary but may
     * be placed anywhere in flash memory.  If desired the .nvs section can be set
     * to a fixed address by changing the following in the gcc linker file:
     *
     * .nvs (FIXED_FLASH_ADDR) (NOLOAD) : AT (FIXED_FLASH_ADDR) {
     *      *(.nvs)
     * } > REGION_TEXT
     */
    __attribute__ ((section (".nvs")))
    static char flashBuf[REGIONSIZE];
    
    #endif
    
    #define SPISECTORSIZE    0x1000
    #define SPIREGIONSIZE    (SPISECTORSIZE * 32)
    #define VERIFYBUFSIZE    64
    
    static uint8_t verifyBuf[VERIFYBUFSIZE];
    
    /* Allocate objects for NVS External Regions */
    NVSSPI25X_Object nvsSPI25XObjects[1];
    
    /* Hardware attributes for NVS External Regions */
    const NVSSPI25X_HWAttrs nvsSPI25XHWAttrs[1] = {
        {
            .regionBaseOffset = 0,
            .regionSize = SPIREGIONSIZE,
            .sectorSize = SPISECTORSIZE,
            .verifyBuf = verifyBuf,
            .verifyBufSize = VERIFYBUFSIZE,
            .spiHandle = NULL,
            .spiIndex = 2,
            .spiBitRate = 2000000,
            .spiCsnGpioIndex = MSP_EXP432P401R_SDSPI_CS,
            .statusPollDelayUs = 100,
        },
    };
    
    NVSMSP432_Object nvsMSP432Objects[MSP_EXP432P401R_NVSCOUNT];
    
    const NVSMSP432_HWAttrs nvsMSP432HWAttrs[MSP_EXP432P401R_NVSCOUNT] = {
        {
            .regionBase = (void *) flashBuf,
            .regionSize = REGIONSIZE,
        },
    };
    
    const NVS_Config NVS_config[MSP_EXP432P401R_NVSCOUNT] = {
        {
            .fxnTablePtr = &NVSMSP432_fxnTable,
            .object = &nvsMSP432Objects[MSP_EXP432P401R_NVSMSP4320],
            .hwAttrs = &nvsMSP432HWAttrs[MSP_EXP432P401R_NVSMSP4320],
        },
        {
            .fxnTablePtr = &NVSSPI25X_fxnTable,
            .object = &nvsSPI25XObjects[0],
            .hwAttrs = &nvsSPI25XHWAttrs[0],
        },
    };

    In Board.h you will add the following definition:

    #define Board_NVSEXTERNAL           MSP_EXP432P401R_NVSMSP4321

    In MSP_EXP432P401R.h you add this entry to the NVS table:

    /*!
     *  @def    MSP_EXP432P401R_NVSName
     *  @brief  Enum of NVS names on the MSP_EXP432P401R dev board
     */
    typedef enum MSP_EXP432P401R_NVSName {
        MSP_EXP432P401R_NVSMSP4320 = 0,
        MSP_EXP432P401R_NVSMSP4321,
    
        MSP_EXP432P401R_NVSCOUNT
    } MSP_EXP432P401R_NVSName;

    And finally in spiffsinternal.c we change the initialization call to use our external spi flash instead of internal flash:

    /* Initialize spiffs, spiffs_config & spiffsnvsdata structures */
    status = SPIFFSNVS_config(&spiffsnvsData, Board_NVSEXTERNAL, &fs, &fsConfig,
                              SPIFFS_LOGICAL_BLOCK_SIZE, SPIFFS_LOGICAL_PAGE_SIZE);

    I just tried this on my desk and the example works as expected:

    Hope this helps, let me know if you need further clarification. Thanks!

    Sean

  • Hi both,

    thanks for your amazing answers.

    I will proceed to mark this as "solved".

    Just one more thing.

    Is there similar information to the one you just posted but for SPI FRAM memory type? We are looking at Cypress and Fujitsu parts.

    Please let me know.

    Have a nice weekend.

  • The Fujitsu FRAM (and probably the Cypress FRAM as well) looks very much like SPI EEPROM or SPI NOR Flash. I vaguely recall one or two of the opcodes being different for no good reason, but that's minor.
  • Thanks to all!

**Attention** This is a public forum