AnsweredAssumed Answered

Query on External flash memory interfacing with STM32F072XX over SPI bus

Question asked by sidekick on Oct 23, 2015
Latest reply on Jul 28, 2016 by Clive One

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);
}







Outcomes