/**
******************************************************************************
* @file stm320518_eval_i2c_ee_cpal.c
* @author MCD Application Team
* @version V1.0.0
* @date 20-April-2012
* @brief This file provides a set of functions needed to manage I2C
* EEPROM memory.
*
* ===================================================================
* Notes:
* - This driver is a modified version of stm320518_eval_i2c_ee.c file;
* I2C CPAL library drivers are used instead of the Standard Peripherals
* I2C driver.
* - This driver is intended for STM32F0xx families devices only.
* - The I2C EEPROM memory (M24LR64) is available in RF EEPROM daughter
* board (ANT7-M24LR-A) provided with the EVAL board, to use this
* driver you have to connect the ANT7-M24LR-A to CN12 connector.
* ===================================================================
*
* It implements a high level communication layer for read and write
* from/to this memory.
*
* @note In this driver, basic read and write functions (sEE_ReadBuffer()
* and sEE_WritePage()) use the DMA or Interrupt to perform the
* data transfer to/from EEPROM memory.
* Thus, after calling these two functions, user application may
* perform other tasks while data transfer is ongoing.
* The application should then monitor the variable holding
* the state of EEPROM in order to determine when the transfer is
* completed . Stopping transfer tasks are performed into DMA or I2C
* interrupt handlers (which are integrated into this driver).
******************************************************************************
* @attention
*
*
© COPYRIGHT 2012 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm320518_eval_i2c_ee_cpal.h"
/* Private typedef -----------------------------------------------------------*/
/*========= sEE_Write_TypeDef =========*/
/* sEE Write parameter structure definition */
typedef struct
{
__IO uint32_t sEEDataNum; /*!< The number of data that will be written in next transfer */
uint32_t sEEWriteAddr; /*!< Physical memory address of EEPROM where data will be written */
__IO uint8_t *sEEpBuffer; /*!< The address of the buffer from which data transfer should start */
__IO uint16_t sEENumOfPage; /*!< The number of page that will be written */
__IO uint8_t sEENumOfSingle; /*!< The number of single data that will be written */
__IO uint8_t sEENextWrite; /*!< This member indicates there is remaining transfers */
} sEE_WriteTypeDef;
/* Private defines -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*========= Local Structures declaration =========*/
#ifdef CPAL_USE_I2C1
sEE_InitTypeDef sEE1_DevStructure = {&I2C1_DevStructure, 0, 0, 0, sEE_STATE_IDLE}; /* Initialize All structure parameters to 0 */
#endif /* CPAL_USE_I2C1 */
#ifdef CPAL_USE_I2C2
sEE_InitTypeDef sEE2_DevStructure = {&I2C2_DevStructure, 0, 0, 0, sEE_STATE_IDLE}; /* Initialize All structure parameters to 0 */
#endif /* CPAL_USE_I2C2 */
sEE_InitTypeDef* sEE_DevStructures[CPAL_I2C_DEV_NUM] =
{
#ifdef CPAL_USE_I2C1
&sEE1_DevStructure,
#else
pNULL,
#endif
#ifdef CPAL_USE_I2C2
&sEE2_DevStructure,
#else
pNULL,
#endif
};
#ifdef CPAL_USE_I2C1
sEE_WriteTypeDef sEE1_WriteStructure = {0, 0, pNULL, 0, 0, 0}; /* Initialize All structure parameters to 0 */
#endif /* CPAL_USE_I2C1 */
#ifdef CPAL_USE_I2C2
sEE_WriteTypeDef sEE2_WriteStructure = {0, 0, pNULL, 0, 0, 0}; /* Initialize All structure parameters to 0 */
#endif /* CPAL_USE_I2C2 */
sEE_WriteTypeDef* sEE_WriteStructures[CPAL_I2C_DEV_NUM] =
{
#ifdef CPAL_USE_I2C1
&sEE1_WriteStructure,
#else
pNULL,
#endif
#ifdef CPAL_USE_I2C2
&sEE2_WriteStructure,
#else
pNULL,
#endif
};
#ifdef CPAL_USE_I2C1
CPAL_TransferTypeDef sEE1_TXTransfer = {
/* Initialize TX Transfer structure */
pNULL,
0,
0,
0};
CPAL_TransferTypeDef sEE1_RXTransfer = {
/* Initialize RX Transfer structure */
pNULL,
0,
0,
0};
#endif /* CPAL_USE_I2C1 */
#ifdef CPAL_USE_I2C2
CPAL_TransferTypeDef sEE2_TXTransfer = {
/* Initialize TX Transfer structure */
pNULL,
0,
0,
0};
CPAL_TransferTypeDef sEE2_RXTransfer = {
/* Initialize RX Transfer structure */
pNULL,
0,
0,
0};
#endif /* CPAL_USE_I2C2 */
CPAL_TransferTypeDef* sEE_TXTransfer[CPAL_I2C_DEV_NUM] =
{
#ifdef CPAL_USE_I2C1
&sEE1_TXTransfer,
#else
pNULL,
#endif
#ifdef CPAL_USE_I2C2
&sEE2_TXTransfer,
#else
pNULL,
#endif
};
CPAL_TransferTypeDef* sEE_RXTransfer[CPAL_I2C_DEV_NUM] =
{
#ifdef CPAL_USE_I2C1
&sEE1_RXTransfer,
#else
pNULL,
#endif
#ifdef CPAL_USE_I2C2
&sEE2_RXTransfer,
#else
pNULL,
#endif
};
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
static uint32_t sEE_WritePage(sEE_InitTypeDef* sEEInitStruct, uint8_t* pBuffer, \
uint16_t WriteAddr, uint32_t NumByteToWrite);
/* Private functions ---------------------------------------------------------*/
/**
* @brief DeInitialize peripherals used by the I2C EEPROM driver.
* @param sEEInitStruct: Pointer to sEE Device structure
* @retval None
*/
void sEE_DeInit(sEE_InitTypeDef* sEEInitStruct)
{
/* Deinitialize CPAL peripheral */
CPAL_I2C_DeInit(sEEInitStruct->sEE_CPALStructure);
}
/**
* @brief Initialize peripherals used by the I2C EEPROM driver.
* @param sEEInitStruct: Pointer to sEE Device structure
* @retval None
*/
void sEE_Init(sEE_InitTypeDef* sEEInitStruct)
{
/* Initialize CPAL peripheral */
CPAL_I2C_Init(sEEInitStruct->sEE_CPALStructure);
}
/**
* @brief Initialize sEE CPAL Structure used by the I2C EEPROM driver.
* @param sEEInitStruct: Pointer to sEE Device structure
* @retval None
*/
void sEE_StructInit(sEE_InitTypeDef* sEEInitStruct)
{
/* Set CPAL structure parameters to their default values */
CPAL_I2C_StructInit(sEEInitStruct->sEE_CPALStructure);
/* Set I2C clock speed */
sEEInitStruct->sEE_CPALStructure->pCPAL_I2C_Struct->I2C_Timing = sEE_I2C_TIMING;
#ifdef sEE_IT
/* Select Interrupt programming model and disable all options */
sEEInitStruct->sEE_CPALStructure->CPAL_ProgModel = CPAL_PROGMODEL_INTERRUPT;
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = 0;
#else
/* Select DMA programming model and activate TX_DMA_TC and RX_DMA_TC interrupts */
sEEInitStruct->sEE_CPALStructure->CPAL_ProgModel = CPAL_PROGMODEL_DMA;
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = CPAL_OPT_DMATX_TCIT | CPAL_OPT_DMARX_TCIT;
#endif /* sEE_IT */
}
/**
* @brief Reads a block of data from the EEPROM.
* @param sEEInitStruct: Pointer to sEE Device structure
* @param pBuffer: pointer to the buffer that receives the data read from
* the EEPROM.
* @param ReadAddr: EEPROM's internal address to read from.
* @param NumByteToRead: pointer to the variable holding number of bytes to
* 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
* configure 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.
*
* @retval None
*/
uint32_t sEE_ReadBuffer(sEE_InitTypeDef* sEEInitStruct, uint8_t* pBuffer, \
uint16_t ReadAddr, uint32_t NumByteToRead)
{
if (sEEInitStruct->sEEState == sEE_STATE_IDLE)
{
sEEInitStruct->sEEState = sEE_STATE_READING;
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = 0;
/* Enable 16Bit memory register option on CPAL */
if (sEEInitStruct->sEEMemoryAddrMode & sEE_OPT_16BIT_REG)
{
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = CPAL_OPT_16BIT_REG;
}
/* Enable no memory addressing mode option on CPAL */
if (sEEInitStruct->sEEMemoryAddrMode & sEE_OPT_NO_MEM_ADDR)
{
sEEInitStruct->sEE_CPALStructure->wCPAL_Options |= CPAL_OPT_NO_MEM_ADDR;
}
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferRx = sEE_RXTransfer[sEEInitStruct->sEE_CPALStructure->CPAL_Dev];
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferRx->wNumData = (uint32_t)(NumByteToRead);
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferRx->pbBuffer = pBuffer;
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferRx->wAddr1 = (uint32_t)((uint8_t)sEEInitStruct->sEEAddress);
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferRx->wAddr2 = (uint32_t)((uint16_t)ReadAddr);
return CPAL_I2C_Read(sEEInitStruct->sEE_CPALStructure);
}
else
{
return CPAL_FAIL;
}
}
/**
* @brief Writes buffer of data to the I2C EEPROM.
* @param sEEInitStruct: Pointer to sEE Device structure
* @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
*/
uint32_t sEE_WriteBuffer(sEE_InitTypeDef* sEEInitStruct, uint8_t* pBuffer, \
uint16_t WriteAddr, uint32_t NumByteToWrite)
{
uint32_t DataNum = 0;
uint16_t count = 0;
uint16_t Addr = 0;
if (sEEInitStruct->sEEState == sEE_STATE_IDLE)
{
sEEInitStruct->sEEState = sEE_STATE_WRITING;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEDataNum = 0;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEWriteAddr = 0;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEpBuffer = pNULL;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfPage = 0;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENextWrite = 0;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfSingle = 0;
/* if one data will be written */
if (NumByteToWrite == 1)
{
/* Transfer complete */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENextWrite = 0;
/* update number od data for write */
DataNum = NumByteToWrite;
if(sEE_WritePage(sEEInitStruct, pBuffer, WriteAddr, DataNum) != CPAL_PASS)
{
return CPAL_FAIL;
}
}
/* Use Write page */
else
{
/* if Address aligned reset count value to 0 */
Addr = WriteAddr % sEEInitStruct->sEEPageSize;
if (Addr == 0)
{
count = 0;
}
else
{
count = sEEInitStruct->sEEPageSize - Addr;
if (NumByteToWrite <= count)
{
count = NumByteToWrite;
}
}
/* Get Number of page for write and number of single byte */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfPage = \
(uint16_t)((NumByteToWrite - count) / sEEInitStruct->sEEPageSize);
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfSingle = \
(uint8_t)((NumByteToWrite - count) % sEEInitStruct->sEEPageSize);
/* If WriteAddr is sEE_PAGESIZE is not aligned */
if (Addr != 0)
{
/* Update Number of data to write */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEDataNum = count;
}
/* If WriteAddr is sEE_PAGESIZE is aligned */
else
{
/* if only single byte must be written */
if (sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfPage == 0)
{
/* update number of data to write */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEDataNum = \
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfSingle;
/* reset number of single */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfSingle = 0;
}
else
{
/* update number of data to write */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEDataNum = (uint32_t)((uint16_t)sEEInitStruct->sEEPageSize);
/* update number of page */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfPage--;
}
}
/* update global variable */
DataNum = sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEDataNum;
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEWriteAddr = (uint32_t)((uint16_t)WriteAddr);
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEEpBuffer = pBuffer;
/* If there are remaining data to transfer */
if ((sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfPage != 0)
|| (sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENumOfSingle != 0))
{
/* update global variable */
sEE_WriteStructures[sEEInitStruct->sEE_CPALStructure->CPAL_Dev]->sEENextWrite = 1;
}
/* Write data on EEPROM */
if (sEE_WritePage(sEEInitStruct, pBuffer, WriteAddr, DataNum) != CPAL_PASS)
{
return CPAL_FAIL;
}
}
return CPAL_PASS;
}
else
{
return CPAL_FAIL;
}
}
/**
* @brief Handle EEPROM Write operation
* @param Device: sEE CPAL device instance
* @retval None
*/
uint32_t sEE_WriteHandler(CPAL_DevTypeDef Device)
{
uint32_t DataNum = 0;
/* wait until EEPROM ready for transfer */
while (sEE_WaitEepromStandbyState(Device) == CPAL_FAIL);
/* if there are remaining data for write */
if (sEE_WriteStructures[Device]->sEENextWrite != 0)
{
sEE_WriteStructures[Device]->sEEWriteAddr += sEE_WriteStructures[Device]->sEEDataNum;
sEE_WriteStructures[Device]->sEEpBuffer += sEE_WriteStructures[Device]->sEEDataNum;
sEE_WriteStructures[Device]->sEENextWrite = 0;
/* if page must be written in EEPROM */
if(sEE_WriteStructures[Device]->sEENumOfPage != 0)
{
sEE_WriteStructures[Device]->sEEDataNum = (uint32_t)((uint16_t)sEE_DevStructures[Device]->sEEPageSize);
sEE_WriteStructures[Device]->sEENumOfPage--;
}
/* if single byte must be written in EEPROM */
else if (sEE_WriteStructures[Device]->sEENumOfSingle != 0)
{
sEE_WriteStructures[Device]->sEEDataNum = (uint32_t)((uint8_t)sEE_WriteStructures[Device]->sEENumOfSingle);
sEE_WriteStructures[Device]->sEENumOfSingle = 0;
sEE_WriteStructures[Device]->sEENextWrite = 0;
}
/* update number of date for write */
DataNum = sEE_WriteStructures[Device]->sEEDataNum;
/* if another data must be written */
if ((sEE_WriteStructures[Device]->sEENumOfPage != 0)
|| (sEE_WriteStructures[Device]->sEENumOfSingle != 0))
{
sEE_WriteStructures[Device]->sEENextWrite = 1;
}
/* write data in EEPROM */
sEE_WritePage(sEE_DevStructures[Device],(uint8_t*)sEE_WriteStructures[Device]->sEEpBuffer, \
sEE_WriteStructures[Device]->sEEWriteAddr, DataNum);
}
else
{
if (sEE_DevStructures[Device]->sEEState != sEE_STATE_ERROR)
{
/* Reset EEPROM State */
sEE_DevStructures[Device]->sEEState = sEE_STATE_IDLE;
}
}
return CPAL_PASS;
}
/**
* @brief Handle EEPROM Read operation
* @param Device: sEE CPAL device instance
* @retval None
*/
uint32_t sEE_ReadHandler(CPAL_DevTypeDef Device)
{
if (sEE_DevStructures[Device]->sEEState != sEE_STATE_ERROR)
{
/* Reset EEPROM State */
sEE_DevStructures[Device]->sEEState = sEE_STATE_IDLE;
}
return CPAL_PASS;
}
/**
* @brief Writes more than one byte to the EEPROM with a single WRITE cycle.
* @note The number of byte can't exceed the EEPROM page size.
* @param sEEInitStruct: Pointer to sEE Device structure
* @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
* written to the EEPROM.
*
* @note The variable pointed by NumByteToWrite 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 written is higher than 1, this function just
* configure the communication and enable the DMA channel to transfer data.
* Meanwhile, the user application may perform other tasks.
* When number of data to be written is 1, then the DMA is not used.
*
* @retval None
*/
static uint32_t sEE_WritePage(sEE_InitTypeDef* sEEInitStruct, uint8_t* pBuffer, \
uint16_t WriteAddr, uint32_t NumByteToWrite)
{
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = 0;
/* Enable 16Bit memory register option on CPAL */
if (sEEInitStruct->sEEMemoryAddrMode & sEE_OPT_16BIT_REG)
{
sEEInitStruct->sEE_CPALStructure->wCPAL_Options = CPAL_OPT_16BIT_REG;
}
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferTx = sEE_TXTransfer[sEEInitStruct->sEE_CPALStructure->CPAL_Dev];
/* Configure transfer parameters */
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferTx->wNumData = (uint32_t)(NumByteToWrite);
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferTx->pbBuffer = pBuffer;
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferTx->wAddr1 = (uint32_t)((uint8_t)sEEInitStruct->sEEAddress);
sEEInitStruct->sEE_CPALStructure->pCPAL_TransferTx->wAddr2 = (uint32_t)((uint16_t)WriteAddr);
/* Write Operation */
return CPAL_I2C_Write(sEEInitStruct->sEE_CPALStructure);
}
/**
* @brief Wait for EEPROM Standby state
* @param Device: sEE CPAL device instance
* @retval None
*/
uint32_t sEE_WaitEepromStandbyState(CPAL_DevTypeDef Device)
{
sEE_DevStructures[Device]->sEE_CPALStructure->pCPAL_TransferTx = sEE_TXTransfer[Device];
sEE_DevStructures[Device]->sEE_CPALStructure->pCPAL_TransferTx->wAddr1 = \
(uint32_t)((uint8_t)sEE_DevStructures[Device]->sEEAddress);
return CPAL_I2C_IsDeviceReady(sEE_DevStructures[Device]->sEE_CPALStructure);
}
/**
* @brief Wait for EEPROM Standby state
* @param sEEInitStruct: Pointer to sEE Device structure
* @retval None
*/
uint32_t sEE_GetEepromState(sEE_InitTypeDef* sEEInitStruct)
{
return sEEInitStruct->sEEState;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/