diff libs/STM32F10x_StdPeriph_Lib_V3.5.0/Utilities/STM32_EVAL/Common/stm32_eval_i2c_ee.c @ 0:c59513fd84fb

Initial commit of STM32 test code.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 03 Oct 2011 21:19:15 +1030
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/STM32F10x_StdPeriph_Lib_V3.5.0/Utilities/STM32_EVAL/Common/stm32_eval_i2c_ee.c	Mon Oct 03 21:19:15 2011 +1030
@@ -0,0 +1,854 @@
+/**
+  ******************************************************************************
+  * @file    stm32_eval_i2c_ee.c
+  * @author  MCD Application Team
+  * @version V4.5.0
+  * @date    07-March-2011
+  * @brief   This file provides a set of functions needed to manage the I2C M24CXX 
+  *          EEPROM memory mounted on STM32xx-EVAL board (refer to stm32_eval.h
+  *          to know about the boards supporting this memory). 
+  *          
+  *          ===================================================================      
+  *          Note: This driver is intended for STM32F10x families devices only.
+  *          ===================================================================
+  *            
+  *          It implements a high level communication layer for read and write 
+  *          from/to this memory. The needed STM32 hardware resources (I2C and 
+  *          GPIO) are defined in stm32xx_eval.h file, and the initialization is 
+  *          performed in sEE_LowLevel_Init() function declared in stm32xx_eval.c 
+  *          file.
+  *          You can easily tailor this driver to any other development board, 
+  *          by just adapting the defines for hardware resources and 
+  *          sEE_LowLevel_Init() function. 
+  *        
+  *          @note In this driver, basic read and write functions (sEE_ReadBuffer() 
+  *                and sEE_WritePage()) use the DMA to perform the data transfer 
+  *                to/from EEPROM memory (except when number of requested data is
+  *                equal to 1). Thus, after calling these two functions, user 
+  *                application may perform other tasks while DMA is transferring
+  *                data. The application should then monitor the variable holding 
+  *                the number of data in order to determine when the transfer is
+  *                completed (variable decremented to 0). Stopping transfer tasks
+  *                are performed into DMA interrupt handlers (which are integrated
+  *                into this driver).
+  *            
+  *     +-----------------------------------------------------------------+
+  *     |                        Pin assignment                           |                 
+  *     +---------------------------------------+-----------+-------------+
+  *     |  STM32 I2C Pins                       |   sEE     |   Pin       |
+  *     +---------------------------------------+-----------+-------------+
+  *     | .                                     |   E0(GND) |    1  (0V)  |
+  *     | .                                     |   E1(GND) |    2  (0V)  |
+  *     | .                                     |   E2(GND) |    3  (0V)  |
+  *     | .                                     |   E0(VSS) |    4  (0V)  |
+  *     | sEE_I2C_SDA_PIN/ SDA                  |   SDA     |    5        |
+  *     | sEE_I2C_SCL_PIN/ SCL                  |   SCL     |    6        |
+  *     | .                                     |   /WC(VDD)|    7 (3.3V) |
+  *     | .                                     |   VDD     |    8 (3.3V) |
+  *     +---------------------------------------+-----------+-------------+  
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_eval_i2c_ee.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL
+  * @{
+  */ 
+
+/** @addtogroup Common
+  * @{
+  */
+  
+/** @addtogroup STM32_EVAL_I2C_EE
+  * @brief      This file includes the I2C EEPROM driver of STM32-EVAL boards.
+  * @{
+  */ 
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Defines
+  * @{
+  */  
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Variables
+  * @{
+  */
+__IO uint16_t  sEEAddress = 0;   
+__IO uint32_t  sEETimeout = sEE_LONG_TIMEOUT;   
+__IO uint16_t* sEEDataReadPointer;   
+__IO uint8_t*  sEEDataWritePointer;  
+__IO uint8_t   sEEDataNum;
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32_EVAL_I2C_EE_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  DeInitializes peripherals used by the I2C EEPROM driver.
+  * @param  None
+  * @retval None
+  */
+void sEE_DeInit(void)
+{
+  sEE_LowLevel_DeInit(); 
+}
+
+/**
+  * @brief  Initializes peripherals used by the I2C EEPROM driver.
+  * @param  None
+  * @retval None
+  */
+void sEE_Init(void)
+{ 
+  I2C_InitTypeDef  I2C_InitStructure;
+  
+  sEE_LowLevel_Init();
+  
+  /*!< I2C configuration */
+  /* sEE_I2C configuration */
+  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
+  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
+  I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7;
+  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
+  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
+  I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
+  
+  /* sEE_I2C Peripheral Enable */
+  I2C_Cmd(sEE_I2C, ENABLE);
+  /* Apply sEE_I2C configuration after enabling it */
+  I2C_Init(sEE_I2C, &I2C_InitStructure);
+
+  /* Enable the sEE_I2C peripheral DMA requests */
+  I2C_DMACmd(sEE_I2C, ENABLE);
+  
+#if defined (sEE_M24C64_32)
+  /*!< Select the EEPROM address according to the state of E0, E1, E2 pins */
+  sEEAddress = sEE_HW_ADDRESS;  
+#elif defined (sEE_M24C08)
+  /*!< depending on the sEE Address selected in the i2c_ee.h file */
+ #ifdef sEE_Block0_ADDRESS
+  /*!< Select the sEE Block0 to write on */
+  sEEAddress = sEE_Block0_ADDRESS;
+ #endif
+  
+ #ifdef sEE_Block1_ADDRESS
+  /*!< Select the sEE Block1 to write on */
+  sEEAddress = sEE_Block1_ADDRESS;
+ #endif
+
+ #ifdef sEE_Block2_ADDRESS
+  /*!< Select the sEE Block2 to write on */
+  sEEAddress = sEE_Block2_ADDRESS;
+ #endif
+  
+ #ifdef sEE_Block3_ADDRESS
+  /*!< Select the sEE Block3 to write on */
+  sEEAddress = sEE_Block3_ADDRESS;
+ #endif 
+#endif /*!< sEE_M24C64_32 */    
+}
+
+/**
+  * @brief  Reads a block of data from the EEPROM.
+  * @param  pBuffer : pointer to the buffer that receives the data read from 
+  *         the EEPROM.
+  * @param  ReadAddr : EEPROM's internal address to start reading from.
+  * @param  NumByteToRead : pointer to the variable holding number of bytes to 
+  *         be read from the EEPROM.
+  * 
+  *        @note The variable pointed by NumByteToRead is reset to 0 when all the 
+  *              data are read from the EEPROM. Application should monitor this 
+  *              variable in order know when the transfer is complete.
+  * 
+  * @note When number of data to be read is higher than 1, this function just 
+  *       configures the communication and enable the DMA channel to transfer data.
+  *       Meanwhile, the user application may perform other tasks.
+  *       When number of data to be read is 1, then the DMA is not used. The byte
+  *       is read in polling mode.
+  * 
+  * @retval sEE_OK (0) if operation is correctly performed, else return value 
+  *         different from sEE_OK (0) or the timeout user callback.
+  */
+uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
+{  
+  /* Set the pointer to the Number of data to be read. This pointer will be used 
+      by the DMA Transfer Completer interrupt Handler in order to reset the 
+      variable to 0. User should check on this variable in order to know if the 
+      DMA transfer has been complete or not. */
+  sEEDataReadPointer = NumByteToRead;
+  
+  /*!< While the bus is busy */
+  sEETimeout = sEE_LONG_TIMEOUT;
+  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send START condition */
+  I2C_GenerateSTART(sEE_I2C, ENABLE);
+  
+  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send EEPROM address for write */
+  I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);
+
+  /*!< Test on EV6 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  } 
+
+#ifdef sEE_M24C08  
+  
+  /*!< Send the EEPROM's internal address to read from: Only one byte address */
+  I2C_SendData(sEE_I2C, ReadAddr);  
+
+#elif defined (sEE_M24C64_32)
+
+  /*!< Send the EEPROM's internal address to read from: MSB of the address first */
+  I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8));    
+
+  /*!< Test on EV8 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+
+  /*!< Send the EEPROM's internal address to read from: LSB of the address */
+  I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF));    
+  
+#endif /*!< sEE_M24C08 */
+
+  /*!< Test on EV8 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF) == RESET)
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send STRAT condition a second time */  
+  I2C_GenerateSTART(sEE_I2C, ENABLE);
+  
+  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  } 
+  
+  /*!< Send EEPROM address for read */
+  I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver);  
+  
+  /* If number of data to be read is 1, then DMA couldn't be used */
+  /* One Byte Master Reception procedure (POLLING) ---------------------------*/
+  if ((uint16_t)(*NumByteToRead) < 2)
+  {
+    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
+    sEETimeout = sEE_FLAG_TIMEOUT;
+    while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_ADDR) == RESET)
+    {
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }     
+    
+    /*!< Disable Acknowledgement */
+    I2C_AcknowledgeConfig(sEE_I2C, DISABLE);   
+
+    /* Call User callback for critical section start (should typically disable interrupts) */
+    sEE_EnterCriticalSection_UserCallback();
+    
+    /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
+    (void)sEE_I2C->SR2;
+    
+    /*!< Send STOP Condition */
+    I2C_GenerateSTOP(sEE_I2C, ENABLE);
+   
+    /* Call User callback for critical section end (should typically re-enable interrupts) */
+    sEE_ExitCriticalSection_UserCallback();
+    
+    /* Wait for the byte to be received */
+    sEETimeout = sEE_FLAG_TIMEOUT;
+    while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_RXNE) == RESET)
+    {
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }
+    
+    /*!< Read the byte received from the EEPROM */
+    *pBuffer = I2C_ReceiveData(sEE_I2C);
+    
+    /*!< Decrement the read bytes counter */
+    (uint16_t)(*NumByteToRead)--;        
+    
+    /* Wait to make sure that STOP control bit has been cleared */
+    sEETimeout = sEE_FLAG_TIMEOUT;
+    while(sEE_I2C->CR1 & I2C_CR1_STOP)
+    {
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }  
+    
+    /*!< Re-Enable Acknowledgement to be ready for another reception */
+    I2C_AcknowledgeConfig(sEE_I2C, ENABLE);    
+  }
+  else/* More than one Byte Master Reception procedure (DMA) -----------------*/
+  {
+    /*!< Test on EV6 and clear it */
+    sEETimeout = sEE_FLAG_TIMEOUT;
+    while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
+    {
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }  
+    
+    /* Configure the DMA Rx Channel with the buffer address and the buffer size */
+    sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), sEE_DIRECTION_RX);
+    
+    /* Inform the DMA that the next End Of Transfer Signal will be the last one */
+    I2C_DMALastTransferCmd(sEE_I2C, ENABLE); 
+    
+    /* Enable the DMA Rx Channel */
+    DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, ENABLE);  
+  }
+  
+  /* If all operations OK, return sEE_OK (0) */
+  return sEE_OK;
+}
+
+/**
+  * @brief  Writes more than one byte to the EEPROM with a single WRITE cycle.
+  *
+  * @note   The number of bytes (combined to write start address) must not 
+  *         cross the EEPROM page boundary. This function can only write into
+  *         the boundaries of an EEPROM page.
+  *         This function doesn't check on boundaries condition (in this driver 
+  *         the function sEE_WriteBuffer() which calls sEE_WritePage() is 
+  *         responsible of checking on Page boundaries).
+  * 
+  * @param  pBuffer : pointer to the buffer containing the data to be written to 
+  *         the EEPROM.
+  * @param  WriteAddr : EEPROM's internal address to write to.
+  * @param  NumByteToWrite : pointer to the variable holding number of bytes to 
+  *         be written into the EEPROM. 
+  * 
+  *        @note The variable pointed by NumByteToWrite is reset to 0 when all the 
+  *              data are written to the EEPROM. Application should monitor this 
+  *              variable in order know when the transfer is complete.
+  * 
+  * @note This function just configure the communication and enable the DMA 
+  *       channel to transfer data. Meanwhile, the user application may perform 
+  *       other tasks in parallel.
+  * 
+  * @retval sEE_OK (0) if operation is correctly performed, else return value 
+  *         different from sEE_OK (0) or the timeout user callback.
+  */
+uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite)
+{ 
+  /* Set the pointer to the Number of data to be written. This pointer will be used 
+      by the DMA Transfer Completer interrupt Handler in order to reset the 
+      variable to 0. User should check on this variable in order to know if the 
+      DMA transfer has been complete or not. */
+  sEEDataWritePointer = NumByteToWrite;  
+  
+  /*!< While the bus is busy */
+  sEETimeout = sEE_LONG_TIMEOUT;
+  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send START condition */
+  I2C_GenerateSTART(sEE_I2C, ENABLE);
+  
+  /*!< Test on EV5 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send EEPROM address for write */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);
+
+  /*!< Test on EV6 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+
+#ifdef sEE_M24C08
+  
+  /*!< Send the EEPROM's internal address to write to : only one byte Address */
+  I2C_SendData(sEE_I2C, WriteAddr);
+  
+#elif defined(sEE_M24C64_32)
+  
+  /*!< Send the EEPROM's internal address to write to : MSB of the address first */
+  I2C_SendData(sEE_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8));
+
+  /*!< Test on EV8 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT;  
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }  
+  
+  /*!< Send the EEPROM's internal address to write to : LSB of the address */
+  I2C_SendData(sEE_I2C, (uint8_t)(WriteAddr & 0x00FF));
+  
+#endif /*!< sEE_M24C08 */  
+  
+  /*!< Test on EV8 and clear it */
+  sEETimeout = sEE_FLAG_TIMEOUT; 
+  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }  
+  
+  /* Configure the DMA Tx Channel with the buffer address and the buffer size */
+  sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint8_t)(*NumByteToWrite), sEE_DIRECTION_TX);
+    
+  /* Enable the DMA Tx Channel */
+  DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, ENABLE);
+  
+  /* If all operations OK, return sEE_OK (0) */
+  return sEE_OK;
+}
+
+/**
+  * @brief  Writes buffer of data to the I2C EEPROM.
+  * @param  pBuffer : pointer to the buffer  containing the data to be written 
+  *         to the EEPROM.
+  * @param  WriteAddr : EEPROM's internal address to write to.
+  * @param  NumByteToWrite : number of bytes to write to the EEPROM.
+  * @retval None
+  */
+void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
+{
+  uint8_t NumOfPage = 0, NumOfSingle = 0, count = 0;
+  uint16_t Addr = 0;
+
+  Addr = WriteAddr % sEE_PAGESIZE;
+  count = sEE_PAGESIZE - Addr;
+  NumOfPage =  NumByteToWrite / sEE_PAGESIZE;
+  NumOfSingle = NumByteToWrite % sEE_PAGESIZE;
+ 
+  /*!< If WriteAddr is sEE_PAGESIZE aligned  */
+  if(Addr == 0) 
+  {
+    /*!< If NumByteToWrite < sEE_PAGESIZE */
+    if(NumOfPage == 0) 
+    {
+      /* Store the number of data to be written */
+      sEEDataNum = NumOfSingle;
+      /* Start writing data */
+      sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+      /* Wait transfer through DMA to be complete */
+      sEETimeout = sEE_LONG_TIMEOUT;
+      while (sEEDataNum > 0)
+      {
+        if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+      }
+      sEE_WaitEepromStandbyState();
+    }
+    /*!< If NumByteToWrite > sEE_PAGESIZE */
+    else  
+    {
+      while(NumOfPage--)
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = sEE_PAGESIZE;        
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); 
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }      
+        sEE_WaitEepromStandbyState();
+        WriteAddr +=  sEE_PAGESIZE;
+        pBuffer += sEE_PAGESIZE;
+      }
+
+      if(NumOfSingle!=0)
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = NumOfSingle;          
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }    
+        sEE_WaitEepromStandbyState();
+      }
+    }
+  }
+  /*!< If WriteAddr is not sEE_PAGESIZE aligned  */
+  else 
+  {
+    /*!< If NumByteToWrite < sEE_PAGESIZE */
+    if(NumOfPage== 0) 
+    {
+      /*!< If the number of data to be written is more than the remaining space 
+      in the current page: */
+      if (NumByteToWrite > count)
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = count;        
+        /*!< Write the data conained in same page */
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }          
+        sEE_WaitEepromStandbyState();      
+        
+        /* Store the number of data to be written */
+        sEEDataNum = (NumByteToWrite - count);          
+        /*!< Write the remaining data in the following page */
+        sEE_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + count), (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }     
+        sEE_WaitEepromStandbyState();        
+      }      
+      else      
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = NumOfSingle;         
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }          
+        sEE_WaitEepromStandbyState();        
+      }     
+    }
+    /*!< If NumByteToWrite > sEE_PAGESIZE */
+    else
+    {
+      NumByteToWrite -= count;
+      NumOfPage =  NumByteToWrite / sEE_PAGESIZE;
+      NumOfSingle = NumByteToWrite % sEE_PAGESIZE;
+      
+      if(count != 0)
+      {  
+        /* Store the number of data to be written */
+        sEEDataNum = count;         
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }     
+        sEE_WaitEepromStandbyState();
+        WriteAddr += count;
+        pBuffer += count;
+      } 
+      
+      while(NumOfPage--)
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = sEE_PAGESIZE;          
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }        
+        sEE_WaitEepromStandbyState();
+        WriteAddr +=  sEE_PAGESIZE;
+        pBuffer += sEE_PAGESIZE;  
+      }
+      if(NumOfSingle != 0)
+      {
+        /* Store the number of data to be written */
+        sEEDataNum = NumOfSingle;           
+        sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); 
+        /* Wait transfer through DMA to be complete */
+        sEETimeout = sEE_LONG_TIMEOUT;
+        while (sEEDataNum > 0)
+        {
+          if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
+        }         
+        sEE_WaitEepromStandbyState();
+      }
+    }
+  }  
+}
+
+/**
+  * @brief  Wait for EEPROM Standby state.
+  * 
+  * @note  This function allows to wait and check that EEPROM has finished the 
+  *        last Write operation. It is mostly used after Write operation: after 
+  *        receiving the buffer to be written, the EEPROM may need additional 
+  *        time to actually perform the write operation. During this time, it 
+  *        doesn't answer to I2C packets addressed to it. Once the write operation 
+  *        is complete the EEPROM responds to its address.
+  *        
+  * @note  It is not necessary to call this function after sEE_WriteBuffer() 
+  *        function (sEE_WriteBuffer() already calls this function after each
+  *        write page operation).    
+  * 
+  * @param  None
+  * @retval sEE_OK (0) if operation is correctly performed, else return value 
+  *         different from sEE_OK (0) or the timeout user callback.
+  */
+uint32_t sEE_WaitEepromStandbyState(void)      
+{
+  __IO uint16_t tmpSR1 = 0;
+  __IO uint32_t sEETrials = 0;
+
+  /*!< While the bus is busy */
+  sEETimeout = sEE_LONG_TIMEOUT;
+  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))
+  {
+    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+  }
+
+  /* Keep looping till the slave acknowledge his address or maximum number 
+     of trials is reached (this number is defined by sEE_MAX_TRIALS_NUMBER define
+     in stm32_eval_i2c_ee.h file) */
+  while (1)
+  {
+    /*!< Send START condition */
+    I2C_GenerateSTART(sEE_I2C, ENABLE);
+
+    /*!< Test on EV5 and clear it */
+    sEETimeout = sEE_FLAG_TIMEOUT;
+    while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+    {
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }    
+
+    /*!< Send EEPROM address for write */
+    I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);
+    
+    /* Wait for ADDR flag to be set (Slave acknowledged his address) */
+    sEETimeout = sEE_LONG_TIMEOUT;
+    do
+    {     
+      /* Get the current value of the SR1 register */
+      tmpSR1 = sEE_I2C->SR1;
+      
+      /* Update the timeout value and exit if it reach 0 */
+      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
+    }
+    /* Keep looping till the Address is acknowledged or the AF flag is 
+       set (address not acknowledged at time) */
+    while((tmpSR1 & (I2C_SR1_ADDR | I2C_SR1_AF)) == 0);
+     
+    /* Check if the ADDR flag has been set */
+    if (tmpSR1 & I2C_SR1_ADDR)
+    {
+      /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already 
+         been read) */
+      (void)sEE_I2C->SR2;
+      
+      /*!< STOP condition */    
+      I2C_GenerateSTOP(sEE_I2C, ENABLE);
+        
+      /* Exit the function */
+      return sEE_OK;
+    }
+    else
+    {
+      /*!< Clear AF flag */
+      I2C_ClearFlag(sEE_I2C, I2C_FLAG_AF);                  
+    }
+    
+    /* Check if the maximum allowed numbe of trials has bee reached */
+    if (sEETrials++ == sEE_MAX_TRIALS_NUMBER)
+    {
+      /* If the maximum number of trials has been reached, exit the function */
+      return sEE_TIMEOUT_UserCallback();
+    }
+  }
+}
+
+/**
+  * @brief  This function handles the DMA Tx Channel interrupt Handler.
+  * @param  None
+  * @retval None
+  */
+void sEE_I2C_DMA_TX_IRQHandler(void)
+{
+  /* Check if the DMA transfer is complete */ 
+  if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_TX_TC) != RESET)
+  {  
+    /* Disable the DMA Tx Channel and Clear all its Flags */  
+    DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, DISABLE);
+    DMA_ClearFlag(sEE_I2C_DMA_FLAG_TX_GL);
+
+    /*!< Wait till all data have been physically transferred on the bus */
+    sEETimeout = sEE_LONG_TIMEOUT;
+    while(!I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF))
+    {
+      if((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback();
+    }
+    
+    /*!< Send STOP condition */
+    I2C_GenerateSTOP(sEE_I2C, ENABLE);
+    
+    /* Perform a read on SR1 and SR2 register to clear eventualaly pending flags */
+    (void)sEE_I2C->SR1;
+    (void)sEE_I2C->SR2;
+    
+    /* Reset the variable holding the number of data to be written */
+    *sEEDataWritePointer = 0;  
+  }
+}
+
+/**
+  * @brief  This function handles the DMA Rx Channel interrupt Handler.
+  * @param  None
+  * @retval None
+  */
+void sEE_I2C_DMA_RX_IRQHandler(void)
+{
+  /* Check if the DMA transfer is complete */
+  if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_RX_TC) != RESET)
+  {      
+    /*!< Send STOP Condition */
+    I2C_GenerateSTOP(sEE_I2C, ENABLE);    
+    
+    /* Disable the DMA Rx Channel and Clear all its Flags */  
+    DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, DISABLE);
+    DMA_ClearFlag(sEE_I2C_DMA_FLAG_RX_GL);
+    
+    /* Reset the variable holding the number of data to be read */
+    *sEEDataReadPointer = 0;
+  }
+}
+
+#ifdef USE_DEFAULT_TIMEOUT_CALLBACK
+/**
+  * @brief  Basic management of the timeout situation.
+  * @param  None.
+  * @retval None.
+  */
+uint32_t sEE_TIMEOUT_UserCallback(void)
+{
+  /* Block communication and all processes */
+  while (1)
+  {   
+  }
+}
+#endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
+
+#ifdef USE_DEFAULT_CRITICAL_CALLBACK
+/**
+  * @brief  Start critical section: these callbacks should be typically used
+  *         to disable interrupts when entering a critical section of I2C communication
+  *         You may use default callbacks provided into this driver by uncommenting the 
+  *         define USE_DEFAULT_CRITICAL_CALLBACK.
+  *         Or you can comment that line and implement these callbacks into your 
+  *         application.
+  * @param  None.
+  * @retval None.
+  */
+void sEE_EnterCriticalSection_UserCallback(void)
+{
+  __disable_irq();  
+}
+
+/**
+  * @brief  Start and End of critical section: these callbacks should be typically used
+  *         to re-enable interrupts when exiting a critical section of I2C communication
+  *         You may use default callbacks provided into this driver by uncommenting the 
+  *         define USE_DEFAULT_CRITICAL_CALLBACK.
+  *         Or you can comment that line and implement these callbacks into your 
+  *         application.
+  * @param  None.
+  * @retval None.
+  */
+void sEE_ExitCriticalSection_UserCallback(void)
+{
+  __enable_irq();
+}
+#endif /* USE_DEFAULT_CRITICAL_CALLBACK */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */  
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/