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.

MSPM0G3507: SPI communication error with W25Q80DV Flash

Part Number: MSPM0G3507


Tool/software:

Dear TI Team, 

I have SPI enabled W25Q80DV Flash and trying to read and write operation with MSPM03507 launchpad. I am starting with trying to reading the manufacture ID of the flash. I took the example code form the MSPM0 SDK for spi_controller_multibyte_fifo_poll and just changed the TX values. The problem is that I get only garbage value 0xFF. On further investigation with oscilloscope, I understood that with the same code flashed either of these two conditions occur

- based on snapshot,  the CS pin (red) goes high with SYSCFG_DL_init function, in DL_SPI_fillTXFIFO8() function it goes low for an instance with one short CLK (blue) pulse then CS goes high again with CLK stopped

- based on snapshot2, the CS pin (red) goes high with SYSCFG_DL_init function, but then never goes low during the DL_SPI_fillTXFIFO8(), with one short pulse on CLK (blue) pin 


#include "ti_msp_dl_config.h"

/*
 * Number of bytes for SPI packet size
 * The packet will be transmitted by the SPI controller.
 * This example uses FIFOs with polling, and the maximum FIFO size is 4.
 * Refer to interrupt examples to handle larger packets.
 */
#define SPI_PACKET_SIZE_TX (4)
#define SPI_PACKET_SIZE_RX (2)

/* Data for SPI to transmit */
//uint8_t gTxPacket[SPI_PACKET_SIZE] = {'M', 'S', 'P', '!'};
uint8_t gTxPacket[SPI_PACKET_SIZE_TX] = {0x90, 0x00, 0x00, 0x00};

/* Data received from SPI Peripheral */
volatile uint8_t gRxPacket[SPI_PACKET_SIZE_RX];

int main(void)
{
    SYSCFG_DL_init();

    /* Fill TX FIFO with data and transmit to SPI Peripheral */
    DL_SPI_fillTXFIFO8(SPI_0_INST, &gTxPacket[0], SPI_PACKET_SIZE_TX);
//    DL_SPI_transmitDataBlocking8(SPI_0_INST, gTxPacket[0]);

    /* Wait until all bytes have been transmitted and the TX FIFO is empty */
    while (DL_SPI_isBusy(SPI_0_INST));

    /*
     * Wait to receive the SPI data
     * This loop expects SPI_PACKET_SIZE bytes
     */
    for (uint8_t i = 0; i < SPI_PACKET_SIZE_RX; i++) {
        DL_SPI_transmitDataBlocking8(SPI_0_INST, 0xFF);
        while (DL_SPI_isBusy(SPI_0_INST));
        gRxPacket[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST);
    }
    /*
     * If this example is used with the spi_peripheral_multibyte_fifo_poll
     * example, the expected data to receive in gRxPacket is
     * {0x01, 0x02, 0x03, 0x04}.
     */

    /* If write and read were successful, toggle LED */
    while (1) {
        DL_GPIO_togglePins(GPIO_LEDS_PORT,
            GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
        delay_cycles(16000000);
    }
}

Reference: e2e.ti.com/.../lp-mspm0g3507-spi-communication-with-nor-flash

  • 1) The hardware /CS works (in general) on a per-byte basis, while your device expects to have /CS asserted over the entire transaction. You should configure the /CS pin as a GPIO and manipulate it explicitly.

    2) Each Tx byte is matched with an Rx byte. You need to read these Rx bytes (then throw them away if you're not interested) to get them out of the FIFO. Writing those first 4 Tx bytes results in 4 Rx bytes (probably =0xFF), which fills the FIFO so the Rx bytes you're interested in are lost. To clear out the Rx FIFO, you could add something like this before your readback loop:

    > while (DL_SPI_receiveDataCheck8(SPI_0_INST, &gRxPacket[0]) {/*EMPTY*/;} // Read everything in Rx FIFO (and throw away the results)

    3) The scope traces seem to have too-low resolution. You might want to check the sampling rate on your scope. I don't remember what SCK speed the example uses, but it's in the .syscfg file.

    We didn't get to see the final version over in the other thread, but s/he seemed to be headed in the right direction.

  • thank you for your response. I made the code simpler and followed your instructions, but still the expected output could not be seen.

    Below is the SPI oscilloscope snap shot, I only get all return (0xFF)s

    But the expected output from the datasheet is -

    #include "ti_msp_dl_config.h"
    
    /*
     * Number of bytes for SPI packet size
     * The packet will be transmitted by the SPI controller.
     * This example uses FIFOs with polling, and the maximum FIFO size is 4.
     * Refer to interrupt examples to handle larger packets.
     */
    #define SPI_PACKET_SIZE_TX (1)
    #define SPI_PACKET_SIZE_RX (3)
    
    /* Data for SPI to transmit */
    //uint8_t gTxPacket[SPI_PACKET_SIZE] = {'M', 'S', 'P', '!'};
    uint8_t gTxPacket[SPI_PACKET_SIZE_TX] = {0x9F};
    
    /* Data received from SPI Peripheral */
    volatile uint8_t gRxPacket[SPI_PACKET_SIZE_RX];
    uint8_t gRxPacketTemp[SPI_PACKET_SIZE_RX];
    
    int main(void)
    {
        SYSCFG_DL_init();
        // manual chip select
        IOMUX->SECCFG.PINCM[IOMUX_PINCM17] = (((uint32_t)0x00000001UL) | IOMUX_PINCM_PC_CONNECTED | IOMUX_PINCM_INV_DISABLE |
                (IOMUX_PINCM_PIPU_ENABLE | IOMUX_PINCM_PIPD_DISABLE) | IOMUX_PINCM_DRV_DRVVAL0 | IOMUX_PINCM_HIZ1_DISABLE);
        GPIOB->DOESET31_0 = GPIO_DOESET31_0_DIO4_MASK;
        GPIOB->DOUTSET31_0 = GPIO_DOESET31_0_DIO4_MASK;
    
        delay_cycles(10000);
    
        GPIOB->DOUTCLR31_0 = GPIO_DOESET31_0_DIO4_MASK;
    //    delay_cycles(1000);
        /* Fill TX FIFO with data and transmit to SPI Peripheral */
    //    DL_SPI_fillTXFIFO8(SPI_0_INST, &gTxPacket[0], SPI_PACKET_SIZE_TX);
        DL_SPI_transmitDataBlocking8(SPI_0_INST, gTxPacket[0]);
        /* Wait until all bytes have been transmitted and the TX FIFO is empty */
        while (DL_SPI_isBusy(SPI_0_INST));
        gRxPacketTemp[0] = DL_SPI_receiveDataBlocking8(SPI_0_INST);
    
        /*
         * Wait to receive the SPI data
         * This loop expects SPI_PACKET_SIZE bytes
         */
        for (uint8_t i = 0; i < SPI_PACKET_SIZE_RX; i++) {
            DL_SPI_transmitDataBlocking8(SPI_0_INST, 0xFF);
            while (DL_SPI_isBusy(SPI_0_INST));
            gRxPacket[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST);
        }
        GPIOB->DOUTSET31_0 = GPIO_DOESET31_0_DIO4_MASK;
        /*
         * If this example is used with the spi_peripheral_multibyte_fifo_poll
         * example, the expected data to receive in gRxPacket is
         * {0x01, 0x02, 0x03, 0x04}.
         */
    
        /* If write and read were successful, toggle LED */
        while (1) {
            DL_GPIO_togglePins(GPIO_LEDS_PORT,
                GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
            delay_cycles(16000000);
        }
    }
    

  • I don't see anything obviously wrong with your code.

    Are you using a commercial breakout board for the flash chip? I'd be curious whether they're doing (or not doing) something with /HOLD.

  • I just tried this on on G3507 Launchpad with a W25Q128JV [Adafruit #5643] and I got back {0xEF, 0x40, 0x18} which looks correct. I imported spi_controller_multibyte_fifo_poll and then pasted your code over the .c file.

    I'm not sure what we're doing differently.

  • Hi Paul,

    Have you tried reading this particular device using some other SPI controller? The waveform appears that the MSPM0/controller is starting communication effectively, and the adafruit chip seems to not respond correctly. Is the adafruit IC definitely functioning properly?

  • Thank you Bruce and Dylan for your valuable inputs. It is working now. The fix was added a pull up resistor on MOSI as well and the hold pin connected to VCC. The issues were with the flash device configuration that I was trying to communicate with. I really appreciate your support here.

    Reference - community.st.com/.../343532