STM8S/A Standard Peripherals Firmware Library: stm8s_eval_i2c_ee.c Source File

STM8S/A

stm8s_eval_i2c_ee.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm8s_eval_i2c_ee.c
00004   * @author  MCD Application Team
00005   * @version V1.0.1
00006   * @date    30-September-2014
00007   * @brief   This file provides a set of functions needed to manage the I2C M24CXX
00008   *          EEPROM memory mounted on STM8Sxx-EVAL board (refer to stm8s_eval.h
00009   *          to know about the boards supporting this memory).
00010   *          
00011   *          ===================================================================      
00012   *          Note: This driver is intended for STM8S families devices only.
00013   *          ===================================================================
00014   *                        
00015   *          It implements a high level communication layer for read and write
00016   *          from/to this memory. The needed STM8S hardware resources (I2C and
00017   *          GPIO) are defined in stm8s_eval.h file, and the initialization is
00018   *          performed in sEE_LowLevel_Init() function declared in stm8s_eval.c
00019   *          file.
00020   *          You can easily tailor this driver to any other development board,
00021   *          by just adapting the defines for hardware resources and
00022   *          sEE_LowLevel_Init() function.
00023   *
00024   *          @note In this driver, basic read and write functions (sEE_ReadBuffer()
00025   *                and sEE_WritePage()) use the I2C in polling mode to perform 
00026   *                the data transfer to/from EEPROM memory 
00027   *                Safe procedure is implemented to handle the read operation, 
00028   *                ensuring safe data reception in case of 1, 2, 3 or more bytes
00029   *                The application should then monitor the variable holding
00030   *                the number of data in order to determine when the transfer is
00031   *                completed (variable decremented to 0). 
00032   *                For more details on the use of this driver you can refer to 
00033   *                the I2C_EEPROM example provided within the STM8SS_StdPeriph_Lib 
00034   *                package.      
00035   *
00036   *     +-----------------------------------------------------------------+
00037   *     |                        Pin assignment                           |
00038   *     +---------------------------------------+-----------+-------------+
00039   *     |  STM8S I2C Pins                       |   sEE     |   Pin       |
00040   *     +---------------------------------------+-----------+-------------+
00041   *     | .                                     |   E0(GND) |    1  (0V)  |
00042   *     | .                                     |   E1(GND) |    2  (0V)  |
00043   *     | .                                     |   E2(GND) |    3  (0V)  |
00044   *     | .                                     |   E0(VSS) |    4  (0V)  |
00045   *     | sEE_I2C_SDA_PIN/ SDA                  |   SDA     |    5        |
00046   *     | sEE_I2C_SCL_PIN/ SCL                  |   SCL     |    6        |
00047   *     | .                                     |   /WC(VDD)|    7 (3.3V) |
00048   *     | .                                     |   VDD     |    8 (3.3V) |
00049   *     +---------------------------------------+-----------+-------------+
00050   ******************************************************************************
00051   *
00052   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
00053   * You may not use this file except in compliance with the License.
00054   * You may obtain a copy of the License at:
00055   *
00056   *        http://www.st.com/software_license_agreement_liberty_v2
00057   *
00058   * Unless required by applicable law or agreed to in writing, software 
00059   * distributed under the License is distributed on an "AS IS" BASIS, 
00060   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00061   * See the License for the specific language governing permissions and
00062   * limitations under the License.
00063   *
00064   ******************************************************************************
00065   */
00066 
00067 /* Includes ------------------------------------------------------------------*/
00068 #include "stm8s_eval_i2c_ee.h"
00069 
00070 /** @addtogroup Utilities
00071   * @{
00072   */
00073 
00074 /** @addtogroup STM8S_EVAL
00075   * @{
00076   */
00077 
00078 /** @addtogroup Common
00079   * @{
00080   */
00081 
00082 /** @addtogroup STM8S_EVAL_I2C_EE
00083   * @brief      This file includes the I2C EEPROM driver of STM8S-EVAL boards.
00084   * @{
00085   */
00086 
00087 /* Private types -------------------------------------------------------------*/
00088 /* Private define ------------------------------------------------------------*/
00089 /* Private macro -------------------------------------------------------------*/
00090 
00091 /** @defgroup STM8S_EVAL_I2C_EE_Private_Variables
00092   * @{
00093   */
00094 __IO uint16_t  sEEAddress = 0;   
00095 __IO uint32_t  sEETimeout = sEE_LONG_TIMEOUT;   
00096 __IO uint8_t*  sEEDataWritePointer;  
00097 __IO uint8_t   sEEDataNum;
00098 /**
00099   * @}
00100   */
00101 
00102 /* Private function prototypes -----------------------------------------------*/
00103 
00104 
00105 /** @defgroup STM8S_EVAL_I2C_EE_Private_Functions
00106   * @{
00107   */
00108 
00109 /**
00110   * @brief  DeInitializes peripherals used by the I2C EEPROM driver.
00111   * @param  None
00112   * @retval None
00113   */
00114 void sEE_DeInit(void)
00115 {
00116   sEE_LowLevel_DeInit();
00117 }
00118 
00119 /**
00120   * @brief  Initializes peripherals used by the I2C EEPROM driver.
00121   * @param  None
00122   * @retval None
00123   */
00124 void sEE_Init(void)
00125 {
00126   sEE_LowLevel_Init();
00127 
00128   /* I2C configuration */
00129   /* sEE_I2C Peripheral Enable */
00130   I2C_Cmd( ENABLE);
00131   /* sEE_I2C configuration after enabling it */
00132   I2C_Init(I2C_SPEED, I2C_SLAVE_ADDRESS7, I2C_DUTYCYCLE_2, I2C_ACK_CURR, 
00133            I2C_ADDMODE_7BIT, 16);
00134 
00135 #if defined (sEE_M24C64_32)
00136   /* Select the EEPROM address according to the state of E0, E1, E2 pins */
00137   sEEAddress = sEE_HW_ADDRESS;
00138 #endif /* sEE_M24C64_32 */
00139 }
00140 
00141 /**
00142   * @brief  Reads a block of data from the EEPROM.
00143   * @param  pBuffer : pointer to the buffer that receives the data read from 
00144   *         the EEPROM.
00145   * @param  ReadAddr : EEPROM's internal address to start reading from.
00146   * @param  NumByteToRead : pointer to the variable holding number of bytes to 
00147   *         be read from the EEPROM.
00148   * 
00149   *        @note The variable pointed by NumByteToRead is reset to 0 when all the 
00150   *              data are read from the EEPROM. Application should monitor this 
00151   *              variable in order to know when the transfer is complete.
00152   * 
00153   * @note This function ensures data reading from EEPROM, it assumes that I2C is 
00154   *       used with polling or its interrupt priority is not the highest in the 
00155   *       application. 
00156   *       Method 2 transfer sequence is implemented in this function(refer to RM0016
00157   *       for more details). 3 bytes, 2bytes and 1 byte reception cases are handled.           
00158   * 
00159   * @retval sEE_OK (0) if operation is correctly performed, else return value 
00160   *         different from sEE_OK (0) or the timeout user callback.
00161   */
00162 uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
00163 {
00164 
00165   /* While the bus is busy */
00166   sEETimeout = sEE_LONG_TIMEOUT;
00167   while(I2C_GetFlagStatus( I2C_FLAG_BUSBUSY))
00168   {
00169     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00170   }
00171 
00172   /* Send START condition */
00173   I2C_GenerateSTART(ENABLE);
00174 
00175   /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
00176   sEETimeout = sEE_FLAG_TIMEOUT;
00177   while(!I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT))
00178   {
00179     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00180   }
00181 
00182   /* Send EEPROM address for write */
00183   I2C_Send7bitAddress( (uint8_t)sEEAddress, I2C_DIRECTION_TX);
00184 
00185   /* Test on EV6 and clear it */
00186   sEETimeout = sEE_FLAG_TIMEOUT;
00187   while(!I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
00188   {
00189     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00190   } 
00191 
00192 #ifdef sEE_M24C64_32
00193 
00194   /* Send the EEPROM's internal address to read from: MSB of the address first */
00195   I2C_SendData( (uint8_t)((ReadAddr & 0xFF00) >> 8));    
00196 
00197   /* Test on EV8 and clear it */
00198   sEETimeout = sEE_FLAG_TIMEOUT;
00199   while(!I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED))
00200   {
00201     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00202   }
00203 
00204   /* Send the EEPROM's internal address to read from: LSB of the address */
00205   I2C_SendData( (uint8_t)(ReadAddr & 0x00FF));    
00206 
00207 #endif /* sEE_M24C64_32 */
00208 
00209   /* Test on EV8 and clear it */
00210   sEETimeout = sEE_FLAG_TIMEOUT;
00211   while(I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET)
00212   {
00213     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00214   }
00215   
00216   /* Send START condition a second time */  
00217   I2C_GenerateSTART( ENABLE);
00218   
00219   /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
00220   sEETimeout = sEE_FLAG_TIMEOUT;
00221   while(!I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT))
00222   {
00223     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00224   } 
00225   
00226   /* Send EEPROM address for read */
00227   I2C_Send7bitAddress((uint8_t)sEEAddress, I2C_DIRECTION_RX);
00228 
00229   /* Read data from first byte until byte N-3 */
00230   if ((uint16_t)(*NumByteToRead)> 3) 
00231     {
00232       /* Poll on BTF */
00233       sEETimeout = sEE_FLAG_TIMEOUT;
00234       while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
00235       {
00236         if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00237       } 
00238 
00239       /* Read a byte from the EEPROM */
00240       *pBuffer = I2C_ReceiveData();
00241 
00242       /* Point to the next location where the byte read will be saved */
00243       *pBuffer++;
00244 
00245       /* Decrement the read bytes counter */
00246       (uint16_t)(*NumByteToRead)--;
00247     }
00248 
00249   /*  Remains three data for read: data N-2, data N-1, Data N */
00250   /* Three Bytes Master Reception procedure (POLLING) ------------------------*/
00251   if ((uint16_t)(*NumByteToRead) == 3)  
00252   {
00253     /* Data N-2 in DR and data N -1 in shift register */
00254     /* Poll on BTF */
00255       sEETimeout = sEE_FLAG_TIMEOUT;
00256       while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
00257       {
00258         if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00259       } 
00260 
00261       /* Clear ACK */
00262       I2C_AcknowledgeConfig(I2C_ACK_NONE);
00263 
00264       /* Call User callback for critical section start (should typically disable interrupts) */
00265       sEE_EnterCriticalSection_UserCallback();
00266 
00267       /* Read Data N-2 */
00268       *pBuffer = I2C_ReceiveData();
00269 
00270       /* Point to the next location where the byte read will be saved */
00271       *pBuffer++;
00272 
00273       /* Program the STOP */
00274       I2C_GenerateSTOP(ENABLE);
00275 
00276       /* Read DataN-1 */
00277       *pBuffer = I2C_ReceiveData();
00278 
00279        /* Call User callback for critical section end (should typically re-enable interrupts) */
00280        sEE_ExitCriticalSection_UserCallback();
00281 
00282       /* Point to the next location where the byte read will be saved */
00283       *pBuffer++;
00284 
00285       /* Poll on RxNE */
00286       sEETimeout = sEE_FLAG_TIMEOUT;
00287       while (I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET)
00288       {
00289         if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00290       }
00291       /* Read DataN */
00292       *pBuffer = I2C_ReceiveData();
00293 
00294       /* Reset the number of bytes to be read from the EEPROM */
00295       NumByteToRead = 0;
00296 
00297     }
00298   
00299   /* If number of data to be read is 2 */
00300   /* Tow Bytes Master Reception procedure (POLLING) ---------------------------*/
00301   if ((uint16_t)(*NumByteToRead) == 2)
00302   {
00303     /* Enable acknowledgement on next byte (set POS and ACK bits)*/
00304     I2C_AcknowledgeConfig(I2C_ACK_NEXT);
00305     
00306     /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
00307     sEETimeout = sEE_FLAG_TIMEOUT;
00308     while(I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET)
00309     {
00310       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00311     }
00312     
00313     /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
00314      (void)I2C->SR3;
00315         
00316     /* Disable Acknowledgement */
00317     I2C_AcknowledgeConfig(I2C_ACK_NONE);
00318     
00319     /* Wait for BTF flag to be set */
00320       sEETimeout = sEE_FLAG_TIMEOUT;
00321       while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
00322       {
00323         if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00324       } 
00325     
00326     /* Call User callback for critical section start (should typically disable interrupts) */
00327     sEE_EnterCriticalSection_UserCallback();
00328     
00329     /* Program the STOP */
00330       I2C_GenerateSTOP(ENABLE);
00331       
00332     /* Read Data N-1 */
00333       *pBuffer = I2C_ReceiveData();
00334 
00335       /* Point to the next location where the byte read will be saved */
00336       *pBuffer++;  
00337            
00338     /* Call User callback for critical section end (should typically re-enable interrupts) */
00339        sEE_ExitCriticalSection_UserCallback();
00340        
00341     /* Read Data N */
00342       *pBuffer = I2C_ReceiveData();
00343           
00344     /* Reset the number of bytes to be read from the EEPROM */
00345       NumByteToRead = 0;   
00346   }
00347   
00348   /* If number of data to be read is 1 */
00349   /* One Byte Master Reception procedure (POLLING) ---------------------------*/
00350   if ((uint16_t)(*NumByteToRead) < 2)
00351   {
00352     /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
00353     sEETimeout = sEE_FLAG_TIMEOUT;
00354     while(I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET)
00355     {
00356       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00357     } 
00358        
00359     /* Disable Acknowledgement */
00360     I2C_AcknowledgeConfig(I2C_ACK_NONE);   
00361 
00362     /* Call User callback for critical section start (should typically disable interrupts) */
00363     sEE_EnterCriticalSection_UserCallback();
00364     
00365     /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
00366     (void)sEE_I2C->SR3;
00367     
00368     /* Send STOP Condition */
00369     I2C_GenerateSTOP( ENABLE);
00370    
00371     /* Call User callback for critical section end (should typically re-enable interrupts) */
00372     sEE_ExitCriticalSection_UserCallback();
00373     
00374     /* Wait for the byte to be received */
00375     sEETimeout = sEE_FLAG_TIMEOUT;
00376     while(I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET)
00377     {
00378       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00379     }
00380     
00381     /* Read the byte received from the EEPROM */
00382     *pBuffer = I2C_ReceiveData();
00383     
00384     /* Decrement the read bytes counter */
00385     (uint16_t)(*NumByteToRead)--;        
00386     
00387     /* Wait to make sure that STOP control bit has been cleared */
00388     sEETimeout = sEE_FLAG_TIMEOUT;
00389     while(sEE_I2C->CR2 & I2C_CR2_STOP)
00390     {
00391       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00392     }  
00393     
00394     /* Re-Enable Acknowledgement to be ready for another reception */
00395     I2C_AcknowledgeConfig( I2C_ACK_CURR);    
00396   }
00397   /* If all operations OK, return sEE_OK (0) */
00398   return sEE_OK;  
00399 }
00400 
00401 /**
00402   * @brief  Writes buffer of data to the I2C EEPROM.
00403   * @param  pBuffer : pointer to the buffer  containing the data to be written
00404   *         to the EEPROM.
00405   * @param  WriteAddr : EEPROM's internal address to write to.
00406   * @param  NumByteToWrite : number of bytes to write to the EEPROM.
00407   * @retval None
00408   */
00409 void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
00410 {
00411   uint8_t NumOfPage = 0, NumOfSingle = 0, count = 0;
00412   uint16_t Addr = 0;
00413 
00414   Addr = WriteAddr % sEE_PAGESIZE;
00415   count = (uint8_t)(sEE_PAGESIZE - (uint16_t)Addr);
00416   NumOfPage =  (uint8_t)(NumByteToWrite / sEE_PAGESIZE);
00417   NumOfSingle = (uint8_t)(NumByteToWrite % sEE_PAGESIZE);
00418 
00419   /* If WriteAddr is sEE_PAGESIZE aligned  */
00420   if (Addr == 0)
00421   {
00422     /* If NumByteToWrite < sEE_PAGESIZE */
00423     if (NumOfPage == 0)
00424     {
00425       /* Store the number of data to be written */
00426       sEEDataNum = NumOfSingle;
00427       /* Start writing data */
00428       sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00429       /* Wait data transfer to be complete */
00430       sEETimeout = sEE_LONG_TIMEOUT;
00431       while (sEEDataNum > 0)
00432       {
00433         if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00434       }
00435       sEE_WaitEepromStandbyState();
00436     }
00437     /* If NumByteToWrite > sEE_PAGESIZE */
00438     else
00439     {
00440       while (NumOfPage--)
00441       {
00442         /* Store the number of data to be written */
00443         sEEDataNum = sEE_PAGESIZE;
00444         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00445         /* Wait data transfer to be complete */
00446         sEETimeout = sEE_LONG_TIMEOUT;
00447         while (sEEDataNum > 0)
00448         {
00449           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00450         }
00451         sEE_WaitEepromStandbyState();
00452         WriteAddr +=  sEE_PAGESIZE;
00453         pBuffer += sEE_PAGESIZE;
00454       }
00455 
00456       if (NumOfSingle != 0)
00457       {
00458         /* Store the number of data to be written */
00459         sEEDataNum = NumOfSingle;
00460         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00461         /* Wait data transfer to be complete */
00462         sEETimeout = sEE_LONG_TIMEOUT;
00463         while (sEEDataNum > 0)
00464         {
00465           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00466         }
00467         sEE_WaitEepromStandbyState();
00468       }
00469     }
00470   }
00471   /* If WriteAddr is not sEE_PAGESIZE aligned  */
00472   else
00473   {
00474     /* If NumByteToWrite < sEE_PAGESIZE */
00475     if (NumOfPage == 0)
00476     {
00477       /* If the number of data to be written is more than the remaining space
00478       in the current page: */
00479       if (NumByteToWrite > count)
00480       {
00481         /* Store the number of data to be written */
00482         sEEDataNum = count;
00483         /* Write the data contained in the same page */
00484         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00485         /* Wait data transfer to be complete */
00486         sEETimeout = sEE_LONG_TIMEOUT;
00487         while (sEEDataNum > 0)
00488         {
00489           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00490         }
00491         sEE_WaitEepromStandbyState();
00492 
00493         /* Store the number of data to be written */
00494         sEEDataNum = (uint8_t)(NumByteToWrite - count);
00495         /* Write the remaining data in the following page */
00496         sEE_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + count), (uint8_t*)(&sEEDataNum));
00497         /* Wait data transfer to be complete */
00498         sEETimeout = sEE_LONG_TIMEOUT;
00499         while (sEEDataNum > 0)
00500         {
00501           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00502         }     
00503         sEE_WaitEepromStandbyState();
00504       }
00505       else
00506       {
00507         /* Store the number of data to be written */
00508         sEEDataNum = NumOfSingle;
00509         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00510         /* Wait data transfer to be complete */
00511         sEETimeout = sEE_LONG_TIMEOUT;
00512         while (sEEDataNum > 0)
00513         {
00514           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00515         }
00516         sEE_WaitEepromStandbyState();
00517       }
00518     }
00519     /* If NumByteToWrite > sEE_PAGESIZE */
00520     else
00521     {
00522       NumByteToWrite -= count;
00523       NumOfPage = (uint8_t)(NumByteToWrite / sEE_PAGESIZE);
00524       NumOfSingle = (uint8_t)(NumByteToWrite % sEE_PAGESIZE);
00525 
00526       if (count != 0)
00527       {
00528         /* Store the number of data to be written */
00529         sEEDataNum = count;
00530         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00531         /* Wait data transfer to be complete */
00532         sEETimeout = sEE_LONG_TIMEOUT;
00533         while (sEEDataNum > 0)
00534         {
00535           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00536         }
00537         sEE_WaitEepromStandbyState();
00538         WriteAddr += count;
00539         pBuffer += count;
00540       }
00541 
00542       while (NumOfPage--)
00543       {
00544         /* Store the number of data to be written */
00545         sEEDataNum = sEE_PAGESIZE;
00546         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00547         /* Wait data transfer to be complete */
00548         sEETimeout = sEE_LONG_TIMEOUT;
00549         while (sEEDataNum > 0)
00550         {
00551           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00552         } 
00553         sEE_WaitEepromStandbyState();
00554         WriteAddr +=  sEE_PAGESIZE;
00555         pBuffer += sEE_PAGESIZE;
00556       }
00557       if (NumOfSingle != 0)
00558       {
00559         /* Store the number of data to be written */
00560         sEEDataNum = NumOfSingle;
00561         sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum));
00562         /* Wait data transfer to be complete */
00563         sEETimeout = sEE_LONG_TIMEOUT;
00564         while (sEEDataNum > 0)
00565         {
00566           if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;};
00567         }
00568         sEE_WaitEepromStandbyState();
00569       }
00570     }
00571   }
00572 }
00573 
00574 /**
00575   * @brief  Writes more than one byte to the EEPROM.
00576   *   
00577   * @note   The number of bytes (combined to write start address) must not 
00578   *         cross the EEPROM page boundary. This function can only write into
00579   *         the boundaries of an EEPROM page.
00580   *         This function doesn't check on boundaries condition (in this driver 
00581   *         the function sEE_WriteBuffer() which calls sEE_WritePage() is 
00582   *         responsible of checking on Page boundaries).
00583   * 
00584   * @param  pBuffer : pointer to the buffer containing the data to be written to 
00585   *         the EEPROM.
00586   * @param  WriteAddr : EEPROM's internal address to write to.
00587   * @param  NumByteToWrite : pointer to the variable holding number of bytes to 
00588   *         be written into the EEPROM. 
00589   * 
00590   *        @note The variable pointed by NumByteToWrite is reset to 0 when all the 
00591   *              data are written to the EEPROM. Application should monitor this 
00592   *              variable in order know when the transfer is complete.
00593   *
00594   * @retval sEE_OK (0) if operation is correctly performed, else return value 
00595   *         different from sEE_OK (0) or the timeout user callback.
00596   */
00597 uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite)
00598 {
00599   /* Set the pointer to the Number of data to be written. 
00600      User should check on this variable in order to know if the 
00601       data transfer has been completed or not. */
00602   sEEDataWritePointer = NumByteToWrite;  
00603   
00604   /* While the bus is busy */
00605   sEETimeout = sEE_LONG_TIMEOUT;
00606   while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY))
00607   {
00608     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00609   }
00610   
00611   /* Send START condition */
00612   I2C_GenerateSTART( ENABLE);
00613   
00614   /* Test on EV5 and clear it */
00615   sEETimeout = sEE_FLAG_TIMEOUT;
00616   while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT))
00617   {
00618     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00619   }
00620   
00621   /* Send EEPROM address for write */
00622   sEETimeout = sEE_FLAG_TIMEOUT;
00623   I2C_Send7bitAddress((uint8_t)sEEAddress, I2C_DIRECTION_TX);
00624 
00625   /* Test on EV6 and clear it */
00626   sEETimeout = sEE_FLAG_TIMEOUT;
00627   while(!I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
00628   {
00629     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00630   }
00631 
00632 #ifdef sEE_M24C08
00633   
00634   /* Send the EEPROM's internal address to write to : only one byte Address */
00635   I2C_SendData( WriteAddr);
00636   
00637 #elif defined(sEE_M24C64_32)
00638   
00639   /* Send the EEPROM's internal address to write to : MSB of the address first */
00640   I2C_SendData( (uint8_t)((WriteAddr & 0xFF00) >> 8));
00641 
00642   /* Test on EV8 and clear it */
00643   sEETimeout = sEE_FLAG_TIMEOUT;  
00644   while(!I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED))
00645   {
00646     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00647   }  
00648   
00649   /* Send the EEPROM's internal address to write to : LSB of the address */
00650   I2C_SendData( (uint8_t)(WriteAddr & 0x00FF));
00651   
00652 #endif /* sEE_M24C08 */  
00653   
00654   /* Test on EV8 and clear it */
00655   sEETimeout = sEE_FLAG_TIMEOUT; 
00656   while(!I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED))
00657   {
00658     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00659   }
00660   
00661   /* While there is data to be written */
00662   while((uint16_t)(*sEEDataWritePointer) > 0)
00663   {
00664     /* Send the byte to be written */
00665     I2C_SendData( *pBuffer);
00666 
00667     /* Test on EV8 and clear it */
00668     /* Wait till all data have been physically transferred on the bus */
00669     sEETimeout = sEE_LONG_TIMEOUT;
00670     while(!I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED))
00671     {
00672       if((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback();
00673     }
00674     (uint16_t)(*sEEDataWritePointer)--;
00675   }
00676   
00677    /* Send STOP condition */
00678     I2C_GenerateSTOP(ENABLE);
00679     
00680     /* Perform a read on SR1 and SR3 register to clear eventually pending flags */
00681     (void)sEE_I2C->SR1;
00682     (void)sEE_I2C->SR3;
00683 
00684   /* If all operations OK, return sEE_OK (0) */
00685   return sEE_OK;  
00686 }
00687 
00688 /**
00689   * @brief  Wait for EEPROM Standby state.
00690   * 
00691   * @note  This function allows to wait and check that EEPROM has finished the 
00692   *        last Write operation. It is mostly used after a Write operation: after 
00693   *        receiving the buffer to be written, the EEPROM may need additional 
00694   *        time to actually perform the write operation. During this time, it 
00695   *        doesn't answer to I2C packets addressed to it. Once the write operation 
00696   *        is complete the EEPROM responds to its address.
00697   *        
00698   * @note  It is not necessary to call this function after sEE_WriteBuffer() 
00699   *        function (sEE_WriteBuffer() already calls this function after each
00700   *        write page operation).    
00701   * 
00702   * @param  None
00703   * @retval sEE_OK (0) if operation is correctly performed, else return value 
00704   *         different from sEE_OK (0) or the timeout user callback.
00705   */
00706 uint32_t sEE_WaitEepromStandbyState(void) 
00707 {
00708   __IO uint8_t tmpSR1 = 0;
00709   __IO uint32_t sEETrials = 0;
00710 
00711  /* While the bus is busy */
00712   sEETimeout = sEE_LONG_TIMEOUT;
00713   while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY))
00714   {
00715     if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00716   }
00717   
00718   /* Keep looping till the slave acknowledges his address or the maximum number 
00719      of trials is reached (this number is defined by sEE_MAX_TRIALS_NUMBER define
00720      in stm8s_eval_i2c_ee.h file) */
00721   while (1)
00722   {
00723     /* Send START condition */
00724     I2C_GenerateSTART(ENABLE);
00725 
00726     /* Test on EV5 and clear it */
00727     sEETimeout = sEE_FLAG_TIMEOUT;
00728     while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT))
00729     {
00730       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00731     }    
00732 
00733     /* Send EEPROM address for write */
00734     I2C_Send7bitAddress((uint8_t)sEEAddress, I2C_DIRECTION_TX);
00735     
00736     /* Wait for ADDR flag to be set (Slave acknowledged his address) */
00737     sEETimeout = sEE_LONG_TIMEOUT;
00738     do
00739     {     
00740       /* Get the current value of the SR1 register */
00741       tmpSR1 = sEE_I2C->SR1;
00742       
00743       /* Update the timeout value and exit if it reach 0 */
00744       if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
00745     }
00746     /* Keep looping till the Address is acknowledged or the AF flag is 
00747        set (address not acknowledged at time) */
00748     while((I2C_GetFlagStatus(I2C_FLAG_ADDRESSSENTMATCHED)== RESET) & 
00749           (I2C_GetFlagStatus(I2C_FLAG_ACKNOWLEDGEFAILURE)== RESET));
00750   tmpSR1 = sEE_I2C->SR1;   
00751     /* Check if the ADDR flag has been set */
00752     if (tmpSR1 & I2C_SR1_ADDR)
00753     {
00754       /* Clear ADDR Flag by reading SR1 then SR3 registers (SR1 have already 
00755          been read) */
00756       (void)sEE_I2C->SR3;
00757       
00758       /* STOP condition */    
00759       I2C_GenerateSTOP(ENABLE);
00760         
00761       /* Exit the function */
00762       return sEE_OK;
00763     }
00764     else
00765     {
00766       /* Clear AF flag */
00767       I2C_ClearFlag(I2C_FLAG_ACKNOWLEDGEFAILURE);                  
00768     }
00769     
00770     /* Check if the maximum allowed number of trials has bee reached */
00771     if (sEETrials++ == sEE_MAX_TRIALS_NUMBER)
00772     {
00773       /* If the maximum number of trials has been reached, exit the function */
00774       return sEE_TIMEOUT_UserCallback();
00775     }
00776   } 
00777 }
00778 
00779 #ifdef USE_DEFAULT_TIMEOUT_CALLBACK
00780 /**
00781   * @brief  Basic management of the timeout situation.
00782   * @param  None.
00783   * @retval None.
00784   */
00785 uint32_t sEE_TIMEOUT_UserCallback(void)
00786 {
00787   /* Block communication and all processes */
00788  while(1)
00789   {   
00790   }
00791 }
00792 #endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
00793 
00794 #ifdef USE_DEFAULT_CRITICAL_CALLBACK
00795 /**
00796   * @brief  Start critical section: this callbacks should be typically used
00797   *         to disable interrupts when entering a critical section of I2C communication
00798   *         You may use default callbacks provided into this driver by uncommenting the 
00799   *         define USE_DEFAULT_CRITICAL_CALLBACK.
00800   *         Or you can comment that line and implement these callbacks into your 
00801   *         application.
00802   * @param  None.
00803   * @retval None.
00804   */
00805 void sEE_EnterCriticalSection_UserCallback(void)
00806 {
00807   disableInterrupts();  
00808 }
00809 
00810 /**
00811   * @brief  End of critical section: this callbacks should be typically used
00812   *         to re-enable interrupts when exiting a critical section of I2C communication
00813   *         You may use default callbacks provided into this driver by uncommenting the 
00814   *         define USE_DEFAULT_CRITICAL_CALLBACK.
00815   *         Or you can comment that line and implement these callbacks into your 
00816   *         application.
00817   * @param  None.
00818   * @retval None.
00819   */
00820 void sEE_ExitCriticalSection_UserCallback(void)
00821 {
00822   enableInterrupts();
00823 }
00824 #endif /* USE_DEFAULT_CRITICAL_CALLBACK */
00825 
00826 
00827 
00828 /**
00829   * @}
00830   */
00831 
00832 /**
00833   * @}
00834   */
00835 
00836 /**
00837   * @}
00838   */
00839 
00840 /**
00841   * @}
00842   */
00843 
00844 /**
00845   * @}
00846   */
00847 
00848 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
STM8 Standard Peripherals Library: Footer

 

 

 

      For complete documentation on STM8 8-bit Microcontrollers platform visit www.st.com