2013-05-03 12:02 AM
I want to interface winbond W25Q64BV SPI flash with STM32F103VE running at 24MHz. I was able to perfectly read the status registers and ID's of flash using commands 0x05,0x35,0x9F,0x4B,0x90,0xAB. But I am not able to erase or write data on flash. When I read the flash after erase chip command,I am not getting 0xFF neither writing command is working. I have checked all memory protection bits and there is no protection set. Why am I not able to write or erase flash??
void sFLASH_Init(void)
{ SPI_InitTypeDef SPI_InitStructure; sFLASH_LowLevel_Init(); /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH(); /*!< SPI 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_High;//SPI_CPOL_High SPI_CPOL_Low SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//SPI_CPHA_1Edge SPI_CPHA_2Edge SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(sFLASH_SPI, &SPI_InitStructure); /*!< Enable the sFLASH_SPI */ SPI_Cmd(sFLASH_SPI, ENABLE);}void sFLASH_LowLevel_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; /*!< sFLASH_SPI_CS_GPIO, sFLASH_SPI_MOSI_GPIO, sFLASH_SPI_MISO_GPIO and sFLASH_SPI_SCK_GPIO Periph clock enable */ RCC_APB2PeriphClockCmd(sFLASH_CS_GPIO_CLK | sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK | sFLASH_SPI_SCK_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); /*!< sFLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(sFLASH_SPI_CLK, ENABLE); /*!< Configure sFLASH_SPI pins: SCK */ GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MOSI */ GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MOSI_PIN; GPIO_Init(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_SPI pins: MISO */ GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */ GPIO_InitStructure.GPIO_Pin = sFLASH_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);}void sFLASH_EraseBulk(void){ /*!< Send write enable instruction */ sFLASH_WriteEnable(); /*!< Bulk Erase */ /*!< Select the FLASH: Chip Select low */ sFLASH_CS_LOW(); /*!< Send Bulk Erase instruction */ sFLASH_SendByte(sFLASH_CMD_ER_CHIP); /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH(); /*!< Wait the end of Flash writing */ sFLASH_WaitForWriteEnd();}void sFLASH_WriteEnable(void){ /*!< Select the FLASH: Chip Select low */ sFLASH_CS_LOW(); /*!< Send ''Write Enable'' instruction */ sFLASH_SendByte(sFLASH_CMD_WR_ENABLE); /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH();}void sFLASH_WaitForWriteEnd(void){ uint8_t flashstatus = 0; /*!< Select the FLASH: Chip Select low */ sFLASH_CS_LOW(); /*!< Send ''Read Status Register'' instruction */ sFLASH_SendByte(sFLASH_CMD_RD_STATUS_REG1); /*!< Loop as long as the memory is busy with a write cycle */ do { /*!< Send a dummy byte to generate the clock needed by the FLASH and put the value of the status register in FLASH_Status variable */ flashstatus = sFLASH_SendByte(sFLASH_DUMMY_BYTE); } while ((flashstatus & sFLASH_WIP_FLAG) == SET); /* Write in progress */ /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH();}uint8_t sFLASH_SendByte(uint8_t byte){ /*!< Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET); /*!< Send byte through the SPI1 peripheral */ SPI_I2S_SendData(sFLASH_SPI, byte); /*!< Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET); /*!< Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(sFLASH_SPI);}void sFLASH_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead){ /*!< Select the FLASH: Chip Select low */ sFLASH_CS_LOW(); /*!< Send ''Read from Memory '' instruction */ sFLASH_SendByte(sFLASH_CMD_RD_DATA); /*!< Send ReadAddr high nibble address byte to read from */ sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16); /*!< Send ReadAddr medium nibble address byte to read from */ sFLASH_SendByte((ReadAddr& 0xFF00) >> 8); /*!< Send ReadAddr low nibble address byte to read from */ sFLASH_SendByte(ReadAddr & 0xFF); while (NumByteToRead--) /*!< while there is data to be read */ { /*!< Read a byte from the FLASH */ *pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE); USART1_Put(*pBuffer); /*!< Point to the next location where the byte read will be saved */ pBuffer++; } /*!< Deselect the FLASH: Chip Select high */ sFLASH_CS_HIGH();}int main(void){ USART1_Config(); //USART1_SendData_s(''Main start::\n\r''); // Initialize the SPI FLASH driver sFLASH_Init(); sFLASH_EraseBulk(); sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize); while (1) { }} #stm32 #spi-flash2013-05-03 03:56 AM
Ok, Found problem. Current was limit due to a resistor(2k) between MCU supply and SPI Flash. For page write or erase operation, 25mA is needed according to datasheet. Removed the resistor and now it works fine.
2015-05-06 06:07 AM
hello,
I am programming Winbond SPI flash but i am unable to get the ID, when i am send the 0x9F instruction. SPI flash is giving me some random value.I have connected the HOLD and WP pin to high but still having the same problem.I am sending you code. 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--; }2015-05-06 09:04 AM
You're sending 0x90 not 0x9F