i am trying to interface a serial flash (m25p80) using the spi protocol with the stm32f4 discovery board. This is the code that i am using...i am unable to figure out what is the problem...
#include "stm32f4_discovery.h"
#define SPI_PORT SPI2
#define SPI_PORT_CLOCK RCC_APB1Periph_SPI2
#define SPI_PORT_CLOCK_INIT RCC_APB1PeriphClockCmd
#define SPI_NSS_PIN GPIO_Pin_12
#define SPI_NSS_GPIO_PORT GPIOB
#define SPI_NSS_GPIO_CLK RCC_AHB1Periph_GPIOB
#define SPI_NSS_SOURCE GPIO_PinSource12
#define SPI_NSS_AF GPIO_AF_SPI2
#define SPI_SCK_PIN GPIO_Pin_13
#define SPI_SCK_GPIO_PORT GPIOB
#define SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOB
#define SPI_SCK_SOURCE GPIO_PinSource13
#define SPI_SCK_AF GPIO_AF_SPI2
#define SPI_MOSI_PIN GPIO_Pin_15
#define SPI_MOSI_GPIO_PORT GPIOB
#define SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOB
#define SPI_MOSI_SOURCE GPIO_PinSource15
#define SPI_MOSI_AF GPIO_AF_SPI2
#define SPI_MISO_PIN GPIO_Pin_14
#define SPI_MISO_GPIO_PORT GPIOB
#define SPI_MISO_GPIO_CLK RCC_AHB1Periph_GPIOB
#define SPI_MISO_SOURCE GPIO_PinSource14
#define SPI_MISO_AF GPIO_AF_SPI2
/** @addtogroup STM32F4_Discovery_Peripheral_Examples
* @{
*/
/** @addtogroup RCC_Example
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void Delay (uint32_t nCount);
void HardwareSPI_init(void);
void spiPutWord(uint16_t data);
uint16_t spiGetWord(void) ;
uint16_t a;
//uint16_t datawrite[10]={0x12,0x11,0x10,0x09,0x08,0x07,0x06,0x05,0x04,0x03},dataread[10]={0},i,j;
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
#define FLASH_WRITE_ADDRESS 0x70000
#define FLASH_WRITE_ADDRESS_test 0x60000
#define FLASH_READ_ADDRESS FLASH_WRITE_ADDRESS
#define FLASH_READ_ADDRESS_test FLASH_WRITE_ADDRESS_test
#define FLASH_SECTOR_TO_ERASE FLASH_WRITE_ADDRESS
#define FLASH_SECTOR_TO_ERASE_test FLASH_WRITE_ADDRESS_test
#define BufferSize (countof(Tx_Buffer)-1)
#define BufferSize_test (countof(Tx_Buffer1)-1)
/* Private macro -------------------------------------------------------------*/
#define countof(a) (sizeof(a) / sizeof(*(a)))
/* Private variables ---------------------------------------------------------*/
uint8_t Tx_Buffer[] = "STM32F4xx SPI Firmware Library Example: communication with an M25P SPI FLASH";
uint8_t Tx_Buffer1[] ={0xfb,0xfc};
uint8_t Rx_Buffer[BufferSize];
uint8_t Rx_Buffer1[]={0,0};
__IO uint8_t Index = 0x0;
volatile TestStatus TransferStatus1 = FAILED, TransferStatus2 = PASSED;
__IO uint32_t FlashID = 0xfa;
/* Private functions ---------------------------------------------------------*/
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOD Periph clock enable */
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
/* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
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);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
//GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO);
HardwareSPI_init();
sFLASH_Init();
sFLASH_EraseSector(FLASH_SECTOR_TO_ERASE);
sFLASH_EraseSector(FLASH_SECTOR_TO_ERASE_test);
/* Get SPI Flash ID */
FlashID = sFLASH_ReadID();
//GPIO_SetBits(GPIOD, GPIO_Pin_13);
/* Write Tx_Buffer data to SPI FLASH memory */
if( FlashID ==0x00)
{
sFLASH_WriteBuffer(Tx_Buffer1, FLASH_WRITE_ADDRESS_test, BufferSize_test);
spiPutWord(0x0000); //dummy write to get clock cycles
sFLASH_ReadBuffer(Rx_Buffer1, FLASH_READ_ADDRESS_test, BufferSize_test);
if(Rx_Buffer1[0]==Tx_Buffer1[0] && Rx_Buffer1[1]==Tx_Buffer[1])
{
sFLASH_WriteBuffer(Tx_Buffer, FLASH_WRITE_ADDRESS, BufferSize);
GPIO_SetBits(GPIOD, GPIO_Pin_12);
/* Read data from SPI FLASH memory */
spiPutWord(0x0000); //dummy write to get clock cycles
sFLASH_ReadBuffer(Rx_Buffer, FLASH_READ_ADDRESS, BufferSize);
if(*Rx_Buffer != 0xff)
GPIO_SetBits(GPIOD, GPIO_Pin_13);
/* Check the correctness of written dada */
TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);
if(TransferStatus1 == PASSED)
{
GPIO_SetBits(GPIOD, GPIO_Pin_14);
}
else
{
GPIO_SetBits(GPIOD, GPIO_Pin_15);
}
//GPIO_SetBits(GPIOB, GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOD, GPIO_Pin_12);
GPIO_SetBits(GPIOD, GPIO_Pin_13);
GPIO_SetBits(GPIOD, GPIO_Pin_14);
GPIO_SetBits(GPIOD, GPIO_Pin_15);
}
while (1)
{}
}
void HardwareSPI_init(void)
{
uint8_t spiConfigured;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// enable the SPI peripheral clock
SPI_PORT_CLOCK_INIT(SPI_PORT_CLOCK, ENABLE);
// enable the peripheral GPIO port clocks
RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK|SPI_MISO_GPIO_CLK , ENABLE);
// Connect SPI pins to AF5 - see section 3, Table 6 in the device datasheet
//GPIO_PinAFConfig(SPI_NSS_GPIO_PORT, SPI_NSS_SOURCE, SPI_NSS_AF);
GPIO_PinAFConfig(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF);
GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF);
GPIO_PinAFConfig(SPI_MISO_GPIO_PORT, SPI_MISO_SOURCE, SPI_MISO_AF);
// now configure the pins themselves
// they are all going to be fast push-pull outputs
// but the SPI pins use the alternate function
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// GPIO_InitStructure.GPIO_Pin = SPI_NSS_PIN;
//GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;
GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN;
GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI_MISO_PIN;
GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
// now we can set up the SPI peripheral
// Assume the target is write only and we look after the chip select ourselves
// SPI clock rate will be system frequency/4/prescaler
// so here we will go for 72/4/8 = 2.25MHz
SPI_I2S_DeInit(SPI_PORT);
SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex ;
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_256;
SPI_Init(SPI_PORT, &SPI_InitStructure);
// Enable the SPI port
SPI_Cmd(SPI_PORT, ENABLE);
spiConfigured = 1;
}
void spiPutWord(uint16_t data)
{
// make sure the transmit buffer is free
while (SPI_I2S_GetFlagStatus(SPI_PORT, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, data);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
};
uint16_t spiGetWord(void)
{ STM_EVAL_LEDOn(LED6);
Delay(0xffff);
// make sure the transmit buffer is free
while (SPI_I2S_GetFlagStatus(SPI_PORT, SPI_I2S_FLAG_RXNE) == RESET);
STM_EVAL_LEDOff(LED6);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
STM_EVAL_LEDOff(LED5);
return SPI_I2S_ReceiveData(SPI2);
};
/**
* @brief Inserts a delay time.
* @param nCount: specifies the delay time length.
* @retval None
*/
void Delay(__IO uint32_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--)
{
if (*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
the function descriptions are as follows:
void sFLASH_DeInit(void)
{
sFLASH_LowLevel_DeInit();
}
/**
* @brief Initializes the peripherals used by the SPI FLASH driver.
* @param None
* @retval None
*/
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_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);
}
/**
* @brief Erases the specified FLASH sector.
* @param SectorAddr: address of the sector to erase.
* @retval None
*/
void sFLASH_EraseSector(uint32_t SectorAddr)
{
/*!< Send write enable instruction */
sFLASH_WriteEnable();
/*!< Sector Erase */
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send Sector Erase instruction */
sFLASH_SendByte(sFLASH_CMD_SE);
/*!< Send SectorAddr high nibble address byte */
sFLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
/*!< Send SectorAddr medium nibble address byte */
sFLASH_SendByte((SectorAddr & 0xFF00) >> 8);
/*!< Send SectorAddr low nibble address byte */
sFLASH_SendByte(SectorAddr & 0xFF);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
/*!< Wait the end of Flash writing */
sFLASH_WaitForWriteEnd();
}
/**
* @brief Erases the entire FLASH.
* @param None
* @retval None
*/
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_BE);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
/*!< Wait the end of Flash writing */
sFLASH_WaitForWriteEnd();
}
/**
* @brief Writes more than one byte to the FLASH with a single WRITE cycle
* (Page WRITE sequence).
* @note The number of byte can't exceed the FLASH page size.
* @param pBuffer: pointer to the buffer containing the data to be written
* to the FLASH.
* @param WriteAddr: FLASH's internal address to write to.
* @param NumByteToWrite: number of bytes to write to the FLASH, must be equal
* or less than "sFLASH_PAGESIZE" value.
* @retval None
*/
void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
/*!< Enable the write access to the FLASH */
sFLASH_WriteEnable();
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "Write to Memory " instruction */
sFLASH_SendByte(sFLASH_CMD_WRITE);
/*!< Send WriteAddr high nibble address byte to write to */
sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/*!< Send WriteAddr medium nibble address byte to write to */
sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/*!< Send WriteAddr low nibble address byte to write to */
sFLASH_SendByte(WriteAddr & 0xFF);
/*!< while there is data to be written on the FLASH */
while (NumByteToWrite--)
{
/*!< Send the current byte */
sFLASH_SendByte(*pBuffer);
/*!< Point on the next byte to be written */
pBuffer++;
}
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
/*!< Wait the end of Flash writing */
sFLASH_WaitForWriteEnd();
}
/**
* @brief Writes block of data to the FLASH. In this function, the number of
* WRITE cycles are reduced, using Page WRITE sequence.
* @param pBuffer: pointer to the buffer containing the data to be written
* to the FLASH.
* @param WriteAddr: FLASH's internal address to write to.
* @param NumByteToWrite: number of bytes to write to the FLASH.
* @retval None
*/
void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
Addr = WriteAddr % sFLASH_SPI_PAGESIZE;
count = sFLASH_SPI_PAGESIZE - Addr;
NumOfPage = NumByteToWrite / sFLASH_SPI_PAGESIZE;
NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;
if (Addr == 0) /*!< WriteAddr is sFLASH_PAGESIZE aligned */
{
if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */
{
sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
}
else /*!< NumByteToWrite > sFLASH_PAGESIZE */
{
while (NumOfPage--)
{
sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
WriteAddr += sFLASH_SPI_PAGESIZE;
pBuffer += sFLASH_SPI_PAGESIZE;
}
sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
}
}
else /*!< WriteAddr is not sFLASH_PAGESIZE aligned */
{
if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */
{
if (NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > sFLASH_PAGESIZE */
{
temp = NumOfSingle - count;
sFLASH_WritePage(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
sFLASH_WritePage(pBuffer, WriteAddr, temp);
}
else
{
sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /*!< NumByteToWrite > sFLASH_PAGESIZE */
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / sFLASH_SPI_PAGESIZE;
NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;
sFLASH_WritePage(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
while (NumOfPage--)
{
sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
WriteAddr += sFLASH_SPI_PAGESIZE;
pBuffer += sFLASH_SPI_PAGESIZE;
}
if (NumOfSingle != 0)
{
sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
/**
* @brief Reads a block of data from the FLASH.
* @param pBuffer: pointer to the buffer that receives the data read from the FLASH.
* @param ReadAddr: FLASH's internal address to read from.
* @param NumByteToRead: number of bytes to read from the FLASH.
* @retval None
*/
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_READ);
/*!< 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);
/*!< Point to the next location where the byte read will be saved */
pBuffer++;
}
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
}
/**
* @brief Reads FLASH identification.
* @param None
* @retval FLASH identification
*/
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(0x9F);
/*!< 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;
}
/**
* @brief Initiates a read data byte (READ) sequence from the Flash.
* This is done by driving the /CS line low to select the device, then the READ
* instruction is transmitted followed by 3 bytes address. This function exit
* and keep the /CS line low, so the Flash still being selected. With this
* technique the whole content of the Flash is read with a single READ instruction.
* @param ReadAddr: FLASH's internal address to read from.
* @retval None
*/
void sFLASH_StartReadSequence(uint32_t ReadAddr)
{
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "Read from Memory " instruction */
sFLASH_SendByte(sFLASH_CMD_READ);
/*!< Send the 24-bit address of the address to read from -------------------*/
/*!< Send ReadAddr high nibble address byte */
sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
/*!< Send ReadAddr medium nibble address byte */
sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
/*!< Send ReadAddr low nibble address byte */
sFLASH_SendByte(ReadAddr & 0xFF);
}
/**
* @brief Reads a byte from the SPI Flash.
* @note This function must be used only if the Start_Read_Sequence function
* has been previously called.
* @param None
* @retval Byte Read from the SPI Flash.
*/
uint8_t sFLASH_ReadByte(void)
{
return (sFLASH_SendByte(sFLASH_DUMMY_BYTE));
}
/**
* @brief Sends a byte through the SPI interface and return the byte received
* from the SPI bus.
* @param byte: byte to send.
* @retval The value of the received byte.
*/
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);
}
/**
* @brief Sends a Half Word through the SPI interface and return the Half Word
* received from the SPI bus.
* @param HalfWord: Half Word to send.
* @retval The value of the received Half Word.
*/
uint16_t sFLASH_SendHalfWord(uint16_t HalfWord)
{
/*!< Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
/*!< Send Half Word through the sFLASH peripheral */
SPI_I2S_SendData(sFLASH_SPI, HalfWord);
/*!< Wait to receive a Half Word */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/*!< Return the Half Word read from the SPI bus */
return SPI_I2S_ReceiveData(sFLASH_SPI);
}
/**
* @brief Enables the write access to the FLASH.
* @param None
* @retval None
*/
void sFLASH_WriteEnable(void)
{
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "Write Enable" instruction */
sFLASH_SendByte(sFLASH_CMD_WREN);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
}
/**
* @brief Polls the status of the Write In Progress (WIP) flag in the FLASH's
* status register and loop until write opertaion has completed.
* @param None
* @retval None
*/
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_RDSR);
/*!< 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();
}
/**
* @brief Initializes the peripherals used by the SPI FLASH driver.
* @param None
* @retval None
*/
void sFLASH_LowLevel_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< Enable the SPI clock */
sFLASH_SPI_CLK_INIT(sFLASH_SPI_CLK, ENABLE);
/*!< Enable GPIO clocks */
RCC_AHB1PeriphClockCmd(sFLASH_SPI_SCK_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK |
sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_CS_GPIO_CLK, ENABLE);
/*!< SPI pins configuration *************************************************/
/*!< Connect SPI pins to AF5 */
GPIO_PinAFConfig(sFLASH_SPI_SCK_GPIO_PORT, sFLASH_SPI_SCK_SOURCE, sFLASH_SPI_SCK_AF);
GPIO_PinAFConfig(sFLASH_SPI_MISO_GPIO_PORT, sFLASH_SPI_MISO_SOURCE, sFLASH_SPI_MISO_AF);
GPIO_PinAFConfig(sFLASH_SPI_MOSI_GPIO_PORT, sFLASH_SPI_MOSI_SOURCE, sFLASH_SPI_MOSI_AF);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
/*!< SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN;
GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
/*!< SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MOSI_PIN;
GPIO_Init(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
/*!< SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MISO_PIN;
GPIO_Init(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
/*!< Configure sFLASH Card CS pin in output pushpull mode ********************/
GPIO_InitStructure.GPIO_Pin = sFLASH_CS_PIN;
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_NOPULL;
GPIO_Init(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);
}
/**
* @brief DeInitializes the peripherals used by the SPI FLASH driver.
* @param None
* @retval None
*/
void sFLASH_LowLevel_DeInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< Disable the sFLASH_SPI ************************************************/
SPI_Cmd(sFLASH_SPI, DISABLE);
/*!< DeInitializes the sFLASH_SPI *******************************************/
SPI_I2S_DeInit(sFLASH_SPI);
/*!< sFLASH_SPI Periph clock disable ****************************************/
sFLASH_SPI_CLK_INIT(sFLASH_SPI_CLK, DISABLE);
/*!< Configure all pins used by the SPI as input floating *******************/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN;
GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MISO_PIN;
GPIO_Init(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_MOSI_PIN;
GPIO_Init(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = sFLASH_CS_PIN;
GPIO_Init(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);
}