cancel
Showing results for 
Search instead for 
Did you mean: 

SPI reading data from external flash?

reckan
Associate II
Posted on April 18, 2011 at 15:29

SPI reading data from external flash?

#spi
18 REPLIES 18
reckan
Associate II
Posted on May 17, 2011 at 14:31

Hey

What do you mean what part?

Posted on May 17, 2011 at 14:31

What do you mean what part?

Which EXTERNAL FLASH MEMORY part are you using? It might help for someone here to read the specifications, and suggest some part appropriate settings.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
reckan
Associate II
Posted on May 17, 2011 at 14:31

Im using the Winbond W25X16 spiflash!

Here's the datasheet: http://www.winbond-usa.com/products/Nexflash/pdfs/datasheets/W25X16_32_64h.pdf

I have connected /WP with /HOLD and VCC. (at the top on page 5)

VCC: +3V

Thanks for your help!

Posted on May 17, 2011 at 14:31

For starters, it's definitely an 8-bit MSB device.

      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

So 0x90 goes out most significant bit first (ie not using 0x09)

The data clocks out on the rising clock edge, and read back on the falling clock.

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x9F); // 1001 1111 = hex 9F

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_ReceiveData(SPI1); // Clear out any pending RX data

        SPI_I2S_SendData(SPI1,0x00); // Junk Byte

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

        mfg = SPI_I2S_ReceiveData(SPI1); // Manufactuer ID 0xEF

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00); // Junk Byte

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

        memtype = SPI_I2S_ReceiveData(SPI1);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00); // Junk Byte

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

        capacity = SPI_I2S_ReceiveData(SPI1);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
reckan
Associate II
Posted on May 17, 2011 at 14:31

Hey clive1, first i really wanna thank you for helping me with this!

I tried your code and my main looks like this right now:

=============================================

int main(void)

{

    uint16_t mfg = 0, memtype = 0, capacity = 0;

    //NVIC_Configuration();

    RCC_Configuration();

    GPIO_Configuration();

    SPI_Configuration();

    //memory ChipSelect must set high and thn low after powerup

    GPIO_SetBits(GPIOA, GPIO_Pin_4);//Chip select set high

    GPIO_ResetBits(GPIOA, GPIO_Pin_4);//Chip select set low

    for(;;){

        //Chip select set low

        GPIO_ResetBits(GPIOA, GPIO_Pin_4);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

           SPI_I2S_SendData(SPI1,0x9F); // 1001 1111 = hex 9F

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

           SPI_I2S_ReceiveData(SPI1); // Clear out any pending RX data

           SPI_I2S_SendData(SPI1,0x00); // Junk Byte

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

           mfg = SPI_I2S_ReceiveData(SPI1); // Manufactuer ID 0xEF

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

           SPI_I2S_SendData(SPI1,0x00); // Junk Byte

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

           memtype = SPI_I2S_ReceiveData(SPI1);

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

           SPI_I2S_SendData(SPI1,0x00); // Junk Byte

           while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

           capacity = SPI_I2S_ReceiveData(SPI1);

        //Chip select set high

        GPIO_SetBits(GPIOA, GPIO_Pin_4);

    }

}

================================================

And the spi-config:

================================================

void SPI_Configuration(void)

{

    SPI_InitTypeDef SPI_InitStructure;

    /* SPI_MASTER configuration -------------------------------------------------*/

      SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

      SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 4 = 5Mhz

      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

      SPI_InitStructure.SPI_CRCPolynomial = 7;

      SPI_Init(SPI_COMMS, &SPI_InitStructure);

    /* Enable SPI_MASTER TXE interrupt */

      SPI_I2S_ITConfig(SPI_COMMS, SPI_I2S_IT_TXE, ENABLE);

    /* Enable SPI_MASTER */

      SPI_Cmd(SPI_COMMS, ENABLE);

}

=================================================

I dont know why you are sending 0x9F on your second row of the code but i tried it and my MISO is still dead.

I also tried 0x90 but it didn't change anything. Here's a screenshot of the oscilloscope when sending 0x90:

https://picasaweb.google.com/reckan/20Apr2011#5597560089271622738

EDIT: I think i managed to attach the photo here aswell! Look under attachments!

channel one (yellow) showing clock signal

channel two (purple) showing data out (MOSI)

channel three (blue) showing chip select

channel four (green) showing data in (MISO)

Its pretty zoomed out but it shows one loop. Im sending 0x90 first, followed by 3 0x00 junk bytes

but channel 4 (green) is still not showing any signs of data being transferred.

I also read in the datasheet, that to be able to receive the manufacturer and device id, you need to do following:

''The instruction is initiated by driving the /CS pin low and shifting the instruction code ''90h'' followedby a 24-bit address

 

(A23-A0) of 000000h. After which, the Manufacturer ID for Winbond (Efh) and the Device ID are shifted out on the falling

edge of CLK with most significant bit (MSB) first as shown in figure 18.''

So i have also tried sending:

=============================

SPI_I2S_SendData(SPI1,0x90); // 1001 0000 = hex 90

while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

SPI_I2S_SendData(SPI1,0x00); // 0000 0000 = hex 00

while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

SPI_I2S_SendData(SPI1,0x00); // 0000 0000 = hex 00

while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

SPI_I2S_SendData(SPI1,0x00); // 0000 0000 = hex 00

while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

But that didn't change anything. So what else could be wrong?

Once again, thanks for your help!

//Fredrik

reckan
Associate II
Posted on May 17, 2011 at 14:31

No one knows what could be wrong?

//Fredrik

thekozak82
Associate
Posted on May 17, 2011 at 14:31

Check the HOLD line on flash memory. Flash memory gives response only if there is high state on this line.

mhussnainraza_1986
Associate
Posted on May 06, 2015 at 15:18

Hello Clive,

I am trying to get the ID of Winbond SPI flash W25Q128FV. Here is my code. But I am not getting the SPI flash ID i.e EF4018 instead i am getting some random values. the value of ''Temp'' is changed when ever i want to debug the code.

#include ''stm32f4_discovery.h''

void Delay(uint32_t time);

void SPI_GPIO();

void SPI_Config();

uint8_t SPI_SendByte(uint8_t byte);

uint32_t mfg = 0, memtype = 0, capacity = 0;

uint8_t DUMMY_BYTE = 0xFF;

int main(void)

  SPI_Config();

  GPIO_InitTypeDef GPIO_InitStructure; 

  /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  while(1)

  {

    GPIO_SetBits(GPIOA,GPIO_Pin_4); /*!< Deselect the FLASH: Chip Select high */

       // Identity Check

  GPIO_ResetBits(GPIOA,GPIO_Pin_4); /*!< Select the FLASH: Chip Select Low */

  SPI_SendByte(0x90);

  /*!< Read a byte from the FLASH */

  Temp0 = SPI_SendByte(DUMMY_BYTE);

  /*!< Read a byte from the FLASH */

  Temp1 = SPI_SendByte(DUMMY_BYTE);

  /*!< Read a byte from the FLASH */

  Temp2 = SPI_SendByte(DUMMY_BYTE);

  /*!< Deselect the FLASH: Chip Select high */

  GPIO_SetBits(GPIOA,GPIO_Pin_4); /*!< Deselect the FLASH: Chip Select high */

  

  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  GPIO_ToggleBits(GPIOD,GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15);

  Delay(5000000);

  }

}

void SPI_Config()

{

  SPI_InitTypeDef SPI_InitStructure;

  SPI_GPIO();

  GPIO_SetBits(GPIOA,GPIO_Pin_4); /*!< Deselect the FLASH: Chip Select high */

  

    // SPI Configuration

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // Set to full duplex

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                          // Transmit in master mode

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // One packet of data is 8 bits wide

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                            // Clock is Low when idle

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                          // Data sampled at First edge

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // Set the NSS Soft

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;   // SPI Frequency is SPI Bus Clock/4

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // Data is transmitted MSB first

  SPI_InitStructure.SPI_CRCPolynomial = 7;  /*!< Specifies the polynomial used for the CRC calculation. */

  SPI_Init(SPI1 , &SPI_InitStructure);

  SPI_Cmd(SPI1 , ENABLE);

}

  

void SPI_GPIO()

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* SPI Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  /* Enable clock for used SPI IO pins */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  /*!< Connect SPI pins to AF5 */ 

  

  GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);     // SCK 

  GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1);     // MISO

  GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);     // MOSI

  

  /* Pin  5=SCK, 6=MISO, 7=MOSI*/

  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  

  /*!< Configure CS pin in output pushpull mode ********************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

uint8_t SPI_SendByte(uint8_t byte)

{

  /*!< Loop while DR register in not empty */

  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /*!< Send byte through the SPI1 peripheral */

  SPI_I2S_SendData(SPI1, byte);

  /*!< Wait to receive a byte */

  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /*!< Return the byte read from the SPI bus */

  return SPI_I2S_ReceiveData(SPI1);

}

void Delay(uint32_t time)

{

   int i = 100000;

   for(; time != 0; time--)     

     while(i!=0) i--;

   

}

Posted on May 06, 2015 at 18:02

If you want the 3 bytes returned to mean something why not use command 0x9F (JEDEC ID)

For 0x90 the FOURTH byte returned is 0x00, and the FIFTH and SIXTH are the ID

Page 25 of the Manual might be instructive

https://www.pjrc.com/teensy/W25Q128FV.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..