2015-10-23 05:25 AM
I've a custom board with STM32F073C8 SOC [1] and Spansion flash memory [2] among other things. This external flash memory (Spansion) on board is connected to STM32F072C8 over SPI bus. I'm planning to use STM32 as master and spansion flash memory as slave.
The pin connection is as follows:
STM SPANSION PURPOSE
PA.4 NCS Chip select (Negative logic)
PA.5 SCK Clock
PA.6 SI MOSI (Master out, Slave in)
PA.7 SO MISO (Master in, Slave out)
PB.0 NWP Write protect (Negative logic)
The setup is as follows:
1: Enable clock for GPIOA.
2: Configure GPIOA pins PA.{4,5,6,7} in Alternate function mode (AF_1)
3: Enable clock for GPIOB
4: Configure GPIOB, PB.0 as output mode
5: Configure SPI1 with NSS (Negative slave select as 'soft')
6: Reset chip select (in this case PA.4) and read configuration register (For spansion memory, it is RDCR(0x35) )
7: Send some consecutive dummy bytes (For this, I refered some example for a different flash memory, but I think, sending the dummy bytes are for timing purpose)
However, based on the above understanding and using some sample code in public domain, I tried to implement this communication between STM and Spansion, but I don't get anything (I think, I'm getting stuck in the loop, while trying to read the SPI flag status).
Please let me know, what am i missing? Code snip is below:
/* Spansion specific commands */
#define FLASH_RDCR 0x35 /* Read Configuration Register */
/* Dummy cycles read */
#define sFLASH_DUMMY_BYTE 0xA5
#define sFLASH_CS_LOW() GPIO_ResetBits(sFLASH_CS_GPIO_PORT, sFLASH_CS_PIN)
#define sFLASH_CS_HIGH() GPIO_SetBits(sFLASH_CS_GPIO_PORT, sFLASH_CS_PIN)
#define sFLASH_SPI SPI1
#define sFLASH_SPI_CLK RCC_APB2Periph_SPI1
#define sFLASH_SPI_SCK_PIN GPIO_Pin_5 /* PA.05 */
#define sFLASH_SPI_SCK_GPIO_PORT GPIOA /* GPIOA */
#define sFLASH_SPI_SCK_GPIO_CLK RCC_AHBPeriph_GPIOA
#define sFLASH_SPI_MISO_PIN GPIO_Pin_6 /* PA.06 */
#define sFLASH_SPI_MISO_GPIO_PORT GPIOA /* GPIOA */
#define sFLASH_SPI_MISO_GPIO_CLK RCC_AHBPeriph_GPIOA
#define sFLASH_SPI_MOSI_PIN GPIO_Pin_7 /* PA.07 */
#define sFLASH_SPI_MOSI_GPIO_PORT GPIOA /* GPIOA */
#define sFLASH_SPI_MOSI_GPIO_CLK RCC_AHBPeriph_GPIOA
#define sFLASH_CS_PIN GPIO_Pin_4 /* PA.04 */
#define sFLASH_CS_GPIO_PORT GPIOA /* GPIOA */
#define sFLASH_CS_GPIO_CLK RCC_AHBPeriph_GPIOA
#define sFLASH_SPI_WREN_PIN GPIO_Pin_0 /* PB.0 */
#define sFLASH_SPI_WREN_GPIO_PORT GPIOB
#define sFLASH_WREN_GPIO_CLK RCC_AHBPeriph_GPIOB
void
sFLASH_LowLevel_Init(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA PA.{4,5,6,7}*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Write protect GPIOB PB.0*/
RCC_AHBPeriphClockCmd(sFLASH_WREN_GPIO_CLK, ENABLE);
/*!< sFLASH_SPI Periph clock enable SPI1 */
RCC_APB2PeriphClockCmd(sFLASH_SPI_CLK, ENABLE);
/*!< Configure GPIOA pins: SCK,MOSI,MISO,CS */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN|sFLASH_SPI_MOSI_PIN|sFLASH_SPI_MISO_PIN|sFLASH_CS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);
/*!< Configure sFLASH_SPI pins: WREN */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_WREN_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(sFLASH_SPI_WREN_GPIO_PORT, &GPIO_InitStructure);
}
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_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_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(sFLASH_SPI, &SPI_InitStructure);
/*!< Enable the sFLASH_SPI */
SPI_Cmd(sFLASH_SPI, ENABLE);
}
uint8_t sFLASH_SendByte(uint8_t
byte
)
{
/*!< Loop while DR register in not empty */
while
(SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
/*!< Send byte through the SPI1 peripheral */
SPI_SendData8(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_ReceiveData8(sFLASH_SPI);
}
uint32_t sFLASH_ReadID(
void
)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send ''RDID '' instruction */
sFLASH_SendByte(FLASH_RDCR);
/*!< Read a byte from the FLASH */
Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return
Temp;
}
int
main(
void
)
{
sFLASH_Init();
/* i think, it does not return */
uint32_t ret = sFLASH_ReadID();
while
(1);
}
[1] http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1574/LN1823/PF259609
[2] https://www.spansion.com/Support/Datasheets/S25FL128S_256S_00.pdf
Thanks a lot for your help.
#stm32f072 #stm32 #spi #solved
2016-06-16 03:08 AM
Have you success in this problem, i try to interface with flash spansion memory!
Could you give me some code interface with this flash memory, thank you2016-07-18 11:55 PM
Did you check your data with CRC? If yes how would you check and where to save it?
2016-07-21 12:55 PM
> Did you check your data with CRC? If yes how would you check and where to save it?
Please start your own thread. It's unlikely the OP watches this thread after several months. JW2016-07-21 01:11 PM
It would seem reasonably apparent that he isn't using the CRC
The STM32 SPI CRC works by accumulating a value as the transfer proceed, and when you are done you either switch the SPI data mode so it emits the CRC as the next byte, or you physically read the CRC accumulator and then send it as a byte.So:Does the SPI device you are using expect a CRC?What device is this, and what CRC polynomial does it use?Do you have any experience with CRCs in some other, non-STM32, context.If you are just trying to CRC some arbitrary memory transfer, and write the CRC byte into memory, then you'd reset the CRC, send your N bytes of data, and then for the N+1 byte you'd supply the CRC. When reading you'd reset the CRC, pull you N bytes of data, and the N+1 byte, and the CRC register should be ZERO. ie you've done this mathematical long-division, and the value you wrote is perfectly divisible leaving a zero remainder/residual.You could also generate your own 16-bit or 32-bit CRC for data you write, and append it after the data it describes.2016-07-27 03:22 AM
I'm using your code and I
erase->write->read I
success
But I can't select one sector to read data, I erase sector(60) and write to itthen I erase sector (44) an write to itSo now, I want to read data from sector(60) but I can'tSome one help me how to select one sector to read data from it,Pleases!!!Thank!2016-07-27 05:04 AM
Ok,
What STM32 part are you using? What SPI Flash are you using? Have you thoroughly reviewed the documentation for the flash part? How is it connected? Can you show the commands (bytes to/from the device) used to initialize it? Can you show the ID and settings from the device? Can you show the test code that does the Erase, Write, Read, Erase? Your test code, not the library/driver.2016-07-27 08:32 PM
Thank you!
I'm using FL256SAIF100,
Parameter 4-kB Sector Erase- 4P4E, Sector Erase 4SE DC,
I use SPI interface with ARM stm32f103vct6
So can you help me: Can select one sector to read or write
example: Select sector 40: write some data to it, then select sector 66 to write data, then back select sector 40 to read data!
What is command send by SPI interface to select one sector
Thank you!
2016-07-27 09:53 PM
So can you help me
Well it is not a part I have, and I'm not going to spend my time writing and debugging code for you, if that is what you are expecting. I can help you with some of the datasheet stuff, but you're going to have to understand enough of the basics for that to work. The programming (write) commands are typically byte addresses within the memory, sent as 24-bit or 32-bit addresses. What I might do with a blank device is write a data pattern across the memory, confirm I can read that back, and that I could read random bytes within the array properly. Then I'd try the erase commands, erase one sector, and then see how much of the array it erased.