cancel
Showing results for 
Search instead for 
Did you mean: 

First write into any SPI flash address does not match read value

stenasc
Senior
Posted on February 24, 2015 at 00:39

Hello,

After a device or sector erase, whenever I write into the first SPI flash address and then read it back, the val ue read does not match the written value. All other wrire and reads to subsequent memory locations are fine. It is just the very first address. I thought it may have been to do with page boundaries but I selected the first address to be in the middle of a page and it still occurs. Below are my read and write routines. Can anyone provide any insite to why this is occurring?

Kind Regards

Bob

uint8_t SPI_Flash_Write(uint8_t ins, uint32_t address, uint8_t data)

{

uint8_t address_byte;

    

    // Now write the actual data tht we want

    WriteEnable();    

    EEPROM_CS_LOW;    

    SPI_SendByte(ins);

    address_byte = (address >> 16) & 0x0000FF;

    SPI_SendByte(address_byte);

    address_byte = (address >> 8) & 0x0000FF;    

    SPI_SendByte(address_byte);

    address_byte = address & 0x0000FF;    

    SPI_SendByte(address_byte);    

    SPI_SendByte(data);

        if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET)

            SPI_ReceiveData8(SPIx);

        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);

    EEPROM_CS_HIGH;                

     return (1);

}

uint8_t SPI_Flash_Read(uint8_t ins, uint32_t address)

{

uint8_t spi_rd_data_local = 0;

uint8_t address_byte;    

    

  WriteEnable();

    

  EEPROM_CS_LOW;    

  if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET)

       spi_rd_data_local = SPI_ReceiveData8(SPIx);    

  // Send SPI instruction        

  SPI_SendByte(ins);    

  // Send SPI address H

  address_byte = (address >> 16) & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send SPI address M

  address_byte = (address >> 8) & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send SPI address L

  address_byte = address & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send Dummy Byte for Clocks

  SPI_SendByte(0xFF);

  if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET)

       spi_rd_data_local = SPI_ReceiveData8(SPIx);

  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);

  EEPROM_CS_HIGH;

  return(spi_rd_data_local);         

}
15 REPLIES 15
Posted on February 26, 2015 at 15:04

I don't have any boards with this class of SST devices, mainly Winbond and Macronix, but the behaviour you describe does surprise me. I also have a very narrow view of your code, and the values being sent to the device.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 26, 2015 at 15:06

What is WriteEnable()?

It would be sending a command sequence to get WREN set in the devices internal register
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on February 26, 2015 at 15:55

>> What is WriteEnable()?

> It would be sending a command sequence to get WREN set in the devices internal register

I expect the devil be in the details.

JW

stenasc
Senior
Posted on March 01, 2015 at 23:42

Hi Clive,

Here is the test code I am using. I wonder is the code writing and reading 16 bits rather than 8 bit as expected. I've read some literature online suggesting issue around this.

Bob

void SPI_Config(void)

{

  SPI_InitTypeDef SPI_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);   

         

 

  /* SPI SCK, MOSI, MISO pin configuration */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15 | GPIO_Pin_14;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1; // 10 MHz

  GPIO_Init(GPIOB, &GPIO_InitStructure);

 

  // Configure CS pin as output floating

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  GPIO_Init(GPIOB, &GPIO_InitStructure);   

         

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0); // SPI2 SCK

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0); // SPI2 MOSI

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0); // SPI2 MISO

 

  /* SPI configuration -------------------------------------------------------*/

  SPI_I2S_DeInit(SPIx);

        

  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_1Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

    

 

  SPI_Init(SPIx, &SPI_InitStructure);

    SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);

  SPI_SSOutputCmd(SPIx, ENABLE);

  SPI_Cmd(SPIx, ENABLE);

}

while(1)

{

SPI_Flash_Sectors_Chip_Erase(0xD8);

   

for (mem_add = 131000;  mem_add <= 131002; mem_add++)    

   {

    srand(mem_add);  //Set initial seed for random number    

    value = rand() % 255;

       

        

        SPI_Flash_Write(0x02, mem_add, value);

        

        printf(''\r\nWritten value at %.8X  %.2X'', mem_add, value);

        

        result = SPI_Flash_Read(0x03, mem_add);

       

        printf(''\r\nRead value at %.8X  %.2X'', mem_add, result);

                         

   }

    

 }

uint8_t SPI_Flash_Read(uint8_t ins, uint32_t address)

{

uint8_t spi_rd_data_local = 0;

uint8_t address_byte;    

    

  EEPROM_CS_LOW;    

  // Send SPI instruction        

  SPI_SendByte(ins);

  // Send SPI address H

  address_byte = (address >> 16) & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send SPI address M

  address_byte = (address >> 8) & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send SPI address L

  address_byte = address & 0x0000FF;    

  SPI_SendByte(address_byte);

  // Send Dummy Byte for Clocks

  spi_rd_data_local = SPI_SendByte(0xFF);

        

  if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET);

     spi_rd_data_local = SPI_ReceiveData8(SPIx);                       

  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);        

  EEPROM_CS_HIGH;

    

  return(spi_rd_data_local);         

}

uint8_t SPI_Flash_Write(uint8_t ins, uint32_t address, uint8_t data)

{

uint8_t address_byte;

    

    // Now write the actual data tht we want

    WriteEnable();    

    EEPROM_CS_LOW;    

    SPI_SendByte(ins);

    address_byte = (address >> 16) & 0x0000FF;

    SPI_SendByte(address_byte);

    address_byte = (address >> 8) & 0x0000FF;    

    SPI_SendByte(address_byte);

    address_byte = address & 0x0000FF;    

    SPI_SendByte(address_byte);    

    SPI_SendByte(data);

        if (SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_RXNE) == SET)

            SPI_ReceiveData8(SPIx);

        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET);

    EEPROM_CS_HIGH;                

     return (1);

}

void WriteEnable(void)

{

    EEPROM_CS_LOW;    

    SPI_SendData8(SPIx, 0x06);    

    // Wait for SPI Tx buffer empty

    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) != SET);    

    EEPROM_CS_HIGH;            

}

uint8_t SPI_SendByte(uint8_t x)

{

  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); // Wait for TX Empty (Front Test)

  SPI_SendData8(SPIx,x);   

  while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET); // Wait for data to shift out

  return(SPI_ReceiveData8(SPIx)); // Read to clear RXNE

    

}

Posted on March 02, 2015 at 03:37

Yes, I don't know what STM32 this is for, guessing not an F4, but I'd think that the 8-bit vs 16-bit would be rather apparent from a scope/analyzer.

You're configuring at 8-bit. Erase/WriteEnable which might be problematic is not shown. Does the write need a wait busy?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on March 02, 2015 at 10:52

Hi Clive,

STM32F051. Yes as soon as I can get the scope on the part, then I will be able to see more details.

Bob