2015-02-23 03:39 PM
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); }2015-02-26 06:04 AM
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.
2015-02-26 06:06 AM
What is WriteEnable()?
It would be sending a command sequence to get WREN set in the devices internal register2015-02-26 06:55 AM
>> 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. JW2015-03-01 02:42 PM
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 }2015-03-01 06:37 PM
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?2015-03-02 01:52 AM
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