stm32_eval_spi_flash.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32_eval_spi_flash.c
00004   * @author  MCD Application Team
00005   * @version V4.3.0
00006   * @date    10/15/2010
00007   * @brief   This file provides a set of functions needed to manage the SPI M25Pxxx
00008   *          FLASH memory mounted on STM32xx-EVAL board (refer to stm32_eval.h
00009   *          to know about the boards supporting this memory). 
00010   *          It implements a high level communication layer for read and write 
00011   *          from/to this memory. The needed STM32 hardware resources (SPI and 
00012   *          GPIO) are defined in stm32xx_eval.h file, and the initialization is 
00013   *          performed in sFLASH_LowLevel_Init() function declared in stm32xx_eval.c 
00014   *          file.
00015   *          You can easily tailor this driver to any other development board, 
00016   *          by just adapting the defines for hardware resources and 
00017   *          sFLASH_LowLevel_Init() function.
00018   *            
00019   *          +-----------------------------------------------------------+
00020   *          |                     Pin assignment                        |
00021   *          +-----------------------------+---------------+-------------+
00022   *          |  STM32 SPI Pins             |     sFLASH    |    Pin      |
00023   *          +-----------------------------+---------------+-------------+
00024   *          | sFLASH_CS_PIN               | ChipSelect(/S)|    1        |
00025   *          | sFLASH_SPI_MISO_PIN / MISO  |   DataOut(Q)  |    2        |
00026   *          |                             |   VCC         |    3 (3.3 V)|
00027   *          |                             |   GND         |    4 (0 V)  |
00028   *          | sFLASH_SPI_MOSI_PIN / MOSI  |   DataIn(D)   |    5        |
00029   *          | sFLASH_SPI_SCK_PIN / SCLK   |   Clock(C)    |    6        |
00030   *          |                             |    VCC        |    7 (3.3 V)|
00031   *          |                             |    VCC        |    8 (3.3 V)|  
00032   *          +-----------------------------+---------------+-------------+  
00033   ******************************************************************************
00034   * @copy
00035   *
00036   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00037   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00038   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00039   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00040   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00041   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00042   *
00043   * <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
00044   */ 
00045 
00046 /* Includes ------------------------------------------------------------------*/
00047 #include "stm32_eval_spi_flash.h"
00048 
00049 /** @addtogroup Utilities
00050   * @{
00051   */
00052   
00053 /** @addtogroup STM32_EVAL
00054   * @{
00055   */ 
00056 
00057 /** @addtogroup Common
00058   * @{
00059   */
00060   
00061 /** @addtogroup STM32_EVAL_SPI_FLASH
00062   * @brief      This file includes the M25Pxxx SPI FLASH driver of STM32-EVAL boards.
00063   * @{
00064   */  
00065 
00066 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Types
00067   * @{
00068   */ 
00069 /**
00070   * @}
00071   */ 
00072 
00073 
00074 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Defines
00075   * @{
00076   */  
00077 /**
00078   * @}
00079   */ 
00080 
00081 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Macros
00082   * @{
00083   */
00084 /**
00085   * @}
00086   */ 
00087   
00088 
00089 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Variables
00090   * @{
00091   */ 
00092 /**
00093   * @}
00094   */ 
00095 
00096 
00097 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Function_Prototypes
00098   * @{
00099   */ 
00100 /**
00101   * @}
00102   */ 
00103 
00104 
00105 /** @defgroup STM32_EVAL_SPI_FLASH_Private_Functions
00106   * @{
00107   */ 
00108 
00109 /**
00110   * @brief  DeInitializes the peripherals used by the SPI FLASH driver.
00111   * @param  None
00112   * @retval None
00113   */
00114 void sFLASH_DeInit(void)
00115 {
00116   sFLASH_LowLevel_DeInit();
00117 }
00118 
00119 /**
00120   * @brief  Initializes the peripherals used by the SPI FLASH driver.
00121   * @param  None
00122   * @retval None
00123   */
00124 void sFLASH_Init(void)
00125 {
00126   SPI_InitTypeDef  SPI_InitStructure;
00127 
00128   sFLASH_LowLevel_Init();
00129     
00130   /*!< Deselect the FLASH: Chip Select high */
00131   sFLASH_CS_HIGH();
00132 
00133   /*!< SPI configuration */
00134   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
00135   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
00136   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
00137   SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
00138   SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
00139   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
00140 #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
00141   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
00142 #else
00143   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
00144 #endif
00145 
00146   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
00147   SPI_InitStructure.SPI_CRCPolynomial = 7;
00148   SPI_Init(sFLASH_SPI, &SPI_InitStructure);
00149 
00150   /*!< Enable the sFLASH_SPI  */
00151   SPI_Cmd(sFLASH_SPI, ENABLE);
00152 }
00153 
00154 /**
00155   * @brief  Erases the specified FLASH sector.
00156   * @param  SectorAddr: address of the sector to erase.
00157   * @retval None
00158   */
00159 void sFLASH_EraseSector(uint32_t SectorAddr)
00160 {
00161   /*!< Send write enable instruction */
00162   sFLASH_WriteEnable();
00163 
00164   /*!< Sector Erase */
00165   /*!< Select the FLASH: Chip Select low */
00166   sFLASH_CS_LOW();
00167   /*!< Send Sector Erase instruction */
00168   sFLASH_SendByte(sFLASH_CMD_SE);
00169   /*!< Send SectorAddr high nibble address byte */
00170   sFLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
00171   /*!< Send SectorAddr medium nibble address byte */
00172   sFLASH_SendByte((SectorAddr & 0xFF00) >> 8);
00173   /*!< Send SectorAddr low nibble address byte */
00174   sFLASH_SendByte(SectorAddr & 0xFF);
00175   /*!< Deselect the FLASH: Chip Select high */
00176   sFLASH_CS_HIGH();
00177 
00178   /*!< Wait the end of Flash writing */
00179   sFLASH_WaitForWriteEnd();
00180 }
00181 
00182 /**
00183   * @brief  Erases the entire FLASH.
00184   * @param  None
00185   * @retval None
00186   */
00187 void sFLASH_EraseBulk(void)
00188 {
00189   /*!< Send write enable instruction */
00190   sFLASH_WriteEnable();
00191 
00192   /*!< Bulk Erase */
00193   /*!< Select the FLASH: Chip Select low */
00194   sFLASH_CS_LOW();
00195   /*!< Send Bulk Erase instruction  */
00196   sFLASH_SendByte(sFLASH_CMD_BE);
00197   /*!< Deselect the FLASH: Chip Select high */
00198   sFLASH_CS_HIGH();
00199 
00200   /*!< Wait the end of Flash writing */
00201   sFLASH_WaitForWriteEnd();
00202 }
00203 
00204 /**
00205   * @brief  Writes more than one byte to the FLASH with a single WRITE cycle 
00206   *         (Page WRITE sequence).
00207   * @note   The number of byte can't exceed the FLASH page size.
00208   * @param  pBuffer: pointer to the buffer  containing the data to be written
00209   *         to the FLASH.
00210   * @param  WriteAddr: FLASH's internal address to write to.
00211   * @param  NumByteToWrite: number of bytes to write to the FLASH, must be equal
00212   *         or less than "sFLASH_PAGESIZE" value.
00213   * @retval None
00214   */
00215 void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
00216 {
00217   /*!< Enable the write access to the FLASH */
00218   sFLASH_WriteEnable();
00219 
00220   /*!< Select the FLASH: Chip Select low */
00221   sFLASH_CS_LOW();
00222   /*!< Send "Write to Memory " instruction */
00223   sFLASH_SendByte(sFLASH_CMD_WRITE);
00224   /*!< Send WriteAddr high nibble address byte to write to */
00225   sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
00226   /*!< Send WriteAddr medium nibble address byte to write to */
00227   sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
00228   /*!< Send WriteAddr low nibble address byte to write to */
00229   sFLASH_SendByte(WriteAddr & 0xFF);
00230 
00231   /*!< while there is data to be written on the FLASH */
00232   while (NumByteToWrite--)
00233   {
00234     /*!< Send the current byte */
00235     sFLASH_SendByte(*pBuffer);
00236     /*!< Point on the next byte to be written */
00237     pBuffer++;
00238   }
00239 
00240   /*!< Deselect the FLASH: Chip Select high */
00241   sFLASH_CS_HIGH();
00242 
00243   /*!< Wait the end of Flash writing */
00244   sFLASH_WaitForWriteEnd();
00245 }
00246 
00247 /**
00248   * @brief  Writes block of data to the FLASH. In this function, the number of
00249   *         WRITE cycles are reduced, using Page WRITE sequence.
00250   * @param  pBuffer: pointer to the buffer  containing the data to be written
00251   *         to the FLASH.
00252   * @param  WriteAddr: FLASH's internal address to write to.
00253   * @param  NumByteToWrite: number of bytes to write to the FLASH.
00254   * @retval None
00255   */
00256 void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
00257 {
00258   uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
00259 
00260   Addr = WriteAddr % sFLASH_SPI_PAGESIZE;
00261   count = sFLASH_SPI_PAGESIZE - Addr;
00262   NumOfPage =  NumByteToWrite / sFLASH_SPI_PAGESIZE;
00263   NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;
00264 
00265   if (Addr == 0) /*!< WriteAddr is sFLASH_PAGESIZE aligned  */
00266   {
00267     if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */
00268     {
00269       sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
00270     }
00271     else /*!< NumByteToWrite > sFLASH_PAGESIZE */
00272     {
00273       while (NumOfPage--)
00274       {
00275         sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
00276         WriteAddr +=  sFLASH_SPI_PAGESIZE;
00277         pBuffer += sFLASH_SPI_PAGESIZE;
00278       }
00279 
00280       sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
00281     }
00282   }
00283   else /*!< WriteAddr is not sFLASH_PAGESIZE aligned  */
00284   {
00285     if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */
00286     {
00287       if (NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > sFLASH_PAGESIZE */
00288       {
00289         temp = NumOfSingle - count;
00290 
00291         sFLASH_WritePage(pBuffer, WriteAddr, count);
00292         WriteAddr +=  count;
00293         pBuffer += count;
00294 
00295         sFLASH_WritePage(pBuffer, WriteAddr, temp);
00296       }
00297       else
00298       {
00299         sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
00300       }
00301     }
00302     else /*!< NumByteToWrite > sFLASH_PAGESIZE */
00303     {
00304       NumByteToWrite -= count;
00305       NumOfPage =  NumByteToWrite / sFLASH_SPI_PAGESIZE;
00306       NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;
00307 
00308       sFLASH_WritePage(pBuffer, WriteAddr, count);
00309       WriteAddr +=  count;
00310       pBuffer += count;
00311 
00312       while (NumOfPage--)
00313       {
00314         sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
00315         WriteAddr +=  sFLASH_SPI_PAGESIZE;
00316         pBuffer += sFLASH_SPI_PAGESIZE;
00317       }
00318 
00319       if (NumOfSingle != 0)
00320       {
00321         sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
00322       }
00323     }
00324   }
00325 }
00326 
00327 /**
00328   * @brief  Reads a block of data from the FLASH.
00329   * @param  pBuffer: pointer to the buffer that receives the data read from the FLASH.
00330   * @param  ReadAddr: FLASH's internal address to read from.
00331   * @param  NumByteToRead: number of bytes to read from the FLASH.
00332   * @retval None
00333   */
00334 void sFLASH_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
00335 {
00336   /*!< Select the FLASH: Chip Select low */
00337   sFLASH_CS_LOW();
00338 
00339   /*!< Send "Read from Memory " instruction */
00340   sFLASH_SendByte(sFLASH_CMD_READ);
00341 
00342   /*!< Send ReadAddr high nibble address byte to read from */
00343   sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
00344   /*!< Send ReadAddr medium nibble address byte to read from */
00345   sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
00346   /*!< Send ReadAddr low nibble address byte to read from */
00347   sFLASH_SendByte(ReadAddr & 0xFF);
00348 
00349   while (NumByteToRead--) /*!< while there is data to be read */
00350   {
00351     /*!< Read a byte from the FLASH */
00352     *pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
00353     /*!< Point to the next location where the byte read will be saved */
00354     pBuffer++;
00355   }
00356 
00357   /*!< Deselect the FLASH: Chip Select high */
00358   sFLASH_CS_HIGH();
00359 }
00360 
00361 /**
00362   * @brief  Reads FLASH identification.
00363   * @param  None
00364   * @retval FLASH identification
00365   */
00366 uint32_t sFLASH_ReadID(void)
00367 {
00368   uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
00369 
00370   /*!< Select the FLASH: Chip Select low */
00371   sFLASH_CS_LOW();
00372 
00373   /*!< Send "RDID " instruction */
00374   sFLASH_SendByte(0x9F);
00375 
00376   /*!< Read a byte from the FLASH */
00377   Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
00378 
00379   /*!< Read a byte from the FLASH */
00380   Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
00381 
00382   /*!< Read a byte from the FLASH */
00383   Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
00384 
00385   /*!< Deselect the FLASH: Chip Select high */
00386   sFLASH_CS_HIGH();
00387 
00388   Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
00389 
00390   return Temp;
00391 }
00392 
00393 /**
00394   * @brief  Initiates a read data byte (READ) sequence from the Flash.
00395   *   This is done by driving the /CS line low to select the device, then the READ
00396   *   instruction is transmitted followed by 3 bytes address. This function exit
00397   *   and keep the /CS line low, so the Flash still being selected. With this
00398   *   technique the whole content of the Flash is read with a single READ instruction.
00399   * @param  ReadAddr: FLASH's internal address to read from.
00400   * @retval None
00401   */
00402 void sFLASH_StartReadSequence(uint32_t ReadAddr)
00403 {
00404   /*!< Select the FLASH: Chip Select low */
00405   sFLASH_CS_LOW();
00406 
00407   /*!< Send "Read from Memory " instruction */
00408   sFLASH_SendByte(sFLASH_CMD_READ);
00409 
00410   /*!< Send the 24-bit address of the address to read from -------------------*/
00411   /*!< Send ReadAddr high nibble address byte */
00412   sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
00413   /*!< Send ReadAddr medium nibble address byte */
00414   sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
00415   /*!< Send ReadAddr low nibble address byte */
00416   sFLASH_SendByte(ReadAddr & 0xFF);
00417 }
00418 
00419 /**
00420   * @brief  Reads a byte from the SPI Flash.
00421   * @note   This function must be used only if the Start_Read_Sequence function
00422   *         has been previously called.
00423   * @param  None
00424   * @retval Byte Read from the SPI Flash.
00425   */
00426 uint8_t sFLASH_ReadByte(void)
00427 {
00428   return (sFLASH_SendByte(sFLASH_DUMMY_BYTE));
00429 }
00430 
00431 /**
00432   * @brief  Sends a byte through the SPI interface and return the byte received
00433   *         from the SPI bus.
00434   * @param  byte: byte to send.
00435   * @retval The value of the received byte.
00436   */
00437 uint8_t sFLASH_SendByte(uint8_t byte)
00438 {
00439   /*!< Loop while DR register in not emplty */
00440   while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
00441 
00442   /*!< Send byte through the SPI1 peripheral */
00443   SPI_I2S_SendData(sFLASH_SPI, byte);
00444 
00445   /*!< Wait to receive a byte */
00446   while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);
00447 
00448   /*!< Return the byte read from the SPI bus */
00449   return SPI_I2S_ReceiveData(sFLASH_SPI);
00450 }
00451 
00452 /**
00453   * @brief  Sends a Half Word through the SPI interface and return the Half Word
00454   *         received from the SPI bus.
00455   * @param  HalfWord: Half Word to send.
00456   * @retval The value of the received Half Word.
00457   */
00458 uint16_t sFLASH_SendHalfWord(uint16_t HalfWord)
00459 {
00460   /*!< Loop while DR register in not emplty */
00461   while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
00462 
00463   /*!< Send Half Word through the sFLASH peripheral */
00464   SPI_I2S_SendData(sFLASH_SPI, HalfWord);
00465 
00466   /*!< Wait to receive a Half Word */
00467   while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);
00468 
00469   /*!< Return the Half Word read from the SPI bus */
00470   return SPI_I2S_ReceiveData(sFLASH_SPI);
00471 }
00472 
00473 /**
00474   * @brief  Enables the write access to the FLASH.
00475   * @param  None
00476   * @retval None
00477   */
00478 void sFLASH_WriteEnable(void)
00479 {
00480   /*!< Select the FLASH: Chip Select low */
00481   sFLASH_CS_LOW();
00482 
00483   /*!< Send "Write Enable" instruction */
00484   sFLASH_SendByte(sFLASH_CMD_WREN);
00485 
00486   /*!< Deselect the FLASH: Chip Select high */
00487   sFLASH_CS_HIGH();
00488 }
00489 
00490 /**
00491   * @brief  Polls the status of the Write In Progress (WIP) flag in the FLASH's
00492   *         status register and loop until write opertaion has completed.
00493   * @param  None
00494   * @retval None
00495   */
00496 void sFLASH_WaitForWriteEnd(void)
00497 {
00498   uint8_t flashstatus = 0;
00499 
00500   /*!< Select the FLASH: Chip Select low */
00501   sFLASH_CS_LOW();
00502 
00503   /*!< Send "Read Status Register" instruction */
00504   sFLASH_SendByte(sFLASH_CMD_RDSR);
00505 
00506   /*!< Loop as long as the memory is busy with a write cycle */
00507   do
00508   {
00509     /*!< Send a dummy byte to generate the clock needed by the FLASH
00510     and put the value of the status register in FLASH_Status variable */
00511     flashstatus = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
00512 
00513   }
00514   while ((flashstatus & sFLASH_WIP_FLAG) == SET); /* Write in progress */
00515 
00516   /*!< Deselect the FLASH: Chip Select high */
00517   sFLASH_CS_HIGH();
00518 }
00519 
00520 /**
00521   * @}
00522   */
00523 
00524 /**
00525   * @}
00526   */
00527 
00528 /**
00529   * @}
00530   */
00531 
00532 /**
00533   * @}
00534   */
00535 
00536 /**
00537   * @}
00538   */  
00539 
00540 /******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
STM32F10x Standard Peripherals Library: Footer

 

 

 

      For complete documentation on STM32(CORTEX M3) 32-bit Microcontrollers platform visit  www.st.com/STM32