Query on External flash memory interfacing with STM32F072XX over SPI bus
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