/** ****************************************************************************** * @file stm32f0xx_i2c_cpal.c * @author MCD Application Team * @version V1.2.0 * @date 24-July-2014 * @brief This file provides all the CPAL firmware functions for I2C peripheral. ****************************************************************************** * @attention * *

© COPYRIGHT 2014 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 "stm32f0xx_i2c_cpal.h" /* Private typedef -----------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* This macro allows to test on a flag status and to start Timeout procedure if the waiting time exceeds the allowed timeout period. @note This macro has not been implemented as a function because the entered parameter 'cmd' itself can be a macro (if it was implemented as a function, the check on the flag would be done only once, while the required behavior is to check the flag continuously).*/ #define __CPAL_I2C_TIMEOUT_DETECT ((pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_MIN) ||\ (pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_DEFAULT)) #define __CPAL_I2C_TIMEOUT(cmd, timeout) pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_MIN + (timeout);\ while (((cmd) == 0) && (!__CPAL_I2C_TIMEOUT_DETECT));\ if (__CPAL_I2C_TIMEOUT_DETECT)\ {\ return CPAL_I2C_Timeout (pDevInitStruct); \ }\ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT /* Private variables ---------------------------------------------------------*/ /*========= Table Exported from HAL =========*/ extern I2C_TypeDef* CPAL_I2C_DEVICE[]; #ifdef CPAL_I2C_DMA_PROGMODEL extern DMA_TypeDef* CPAL_I2C_DMA[]; extern DMA_Channel_TypeDef* CPAL_I2C_DMA_TX_Channel[]; extern DMA_Channel_TypeDef* CPAL_I2C_DMA_RX_Channel[]; extern const uint32_t CPAL_I2C_DMA_TX_TC_FLAG[]; extern const uint32_t CPAL_I2C_DMA_RX_TC_FLAG[]; extern const uint32_t CPAL_I2C_DMA_TX_HT_FLAG[]; extern const uint32_t CPAL_I2C_DMA_RX_HT_FLAG[]; extern const uint32_t CPAL_I2C_DMA_TX_TE_FLAG[]; extern const uint32_t CPAL_I2C_DMA_RX_TE_FLAG[]; #endif /* CPAL_I2C_DMA_PROGMODEL */ /*========= Local structures used in CPAL_I2C_StructInit() function ==========*/ I2C_InitTypeDef I2C_InitStructure; __IO uint32_t Num_Data = 0; uint32_t CR2_tmp = 0; /* Private function prototypes -----------------------------------------------*/ /*========= Local Master events handlers =========*/ #ifdef CPAL_I2C_MASTER_MODE static uint32_t I2C_MASTER_TCR_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master TCR Interrupt event */ static uint32_t I2C_MASTER_TC_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master TC Interrupt event */ static uint32_t I2C_MASTER_STOP_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master STOP Interrupt event */ static uint32_t I2C_MASTER_NACK_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master NACK Interrupt event */ #ifdef CPAL_I2C_IT_PROGMODEL static uint32_t I2C_MASTER_TXIS_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master TXIS Interrupt event */ static uint32_t I2C_MASTER_RXNE_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Master RXNE Interrupt event */ #endif /* CPAL_I2C_IT_PROGMODEL */ #endif /* CPAL_I2C_MASTER_MODE */ /*========= Local Slave events handlers =========*/ #ifdef CPAL_I2C_SLAVE_MODE static uint32_t I2C_SLAVE_ADDR_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Slave ADDR Interrupt event */ static uint32_t I2C_SLAVE_STOP_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Slave STOPF Interrupt event */ static uint32_t I2C_SLAVE_NACK_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Slave NACK Interrupt event */ #ifdef CPAL_I2C_IT_PROGMODEL static uint32_t I2C_SLAVE_TXIS_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Slave TXIS Interrupt event */ static uint32_t I2C_SLAVE_RXNE_Handle(CPAL_InitTypeDef* pDevInitStruct); /* Handle Slave RXNE Interrupt event */ #endif /* CPAL_I2C_IT_PROGMODEL */ #endif /* CPAL_I2C_SLAVE_MODE */ #ifdef CPAL_I2C_DMA_PROGMODEL /*========= Local DMA Manager =========*/ static uint32_t I2C_Enable_DMA (CPAL_InitTypeDef* pDevInitStruct, CPAL_DirectionTypeDef Direction); #endif /* CPAL_I2C_DMA_PROGMODEL */ /*========= CPAL Timeout handler =========*/ static uint32_t CPAL_I2C_Timeout (CPAL_InitTypeDef* pDevInitStruct); /* Private functions ---------------------------------------------------------*/ /*================== USER CPAL Functions ==================*/ /** * @brief Initialize the peripheral and all related clocks, GPIOs, DMA and * Interrupts according to the specified parameters in the * CPAL_InitTypeDef structure. * @param pDevInitStruct : Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL */ uint32_t CPAL_I2C_Init(CPAL_InitTypeDef* pDevInitStruct) { CPAL_LOG("\n\r\n\rLOG : I2C Device Init"); /* If CPAL_State is not BUSY */ if ((pDevInitStruct->CPAL_State == CPAL_STATE_READY) || (pDevInitStruct->CPAL_State == CPAL_STATE_ERROR) || (pDevInitStruct->CPAL_State == CPAL_STATE_DISABLED)) { /* - If CPAL_State is CPAL_STATE_ERROR (an Error occurred in transaction): Perform the initialization routines (device will be deinitialized during initialization). - If CPAL_State is CPAL_STATE_READY: Perform the initialization routines - If CPAL_State is CPAL_STATE_DISABLED: Perform the Initialization routines */ #ifndef CPAL_I2C_DMA_PROGMODEL if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { /* Update CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* Exit Init function */ return CPAL_FAIL; } #endif /* CPAL_I2C_DMA_PROGMODEL */ #ifndef CPAL_I2C_IT_PROGMODEL if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Update CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* Exit Init function */ return CPAL_FAIL; } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Disable I2Cx device */ __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device Disabled"); /* Deinitialize I2Cx GPIO */ CPAL_I2C_HAL_GPIODeInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device IOs Deinit"); /* Deinitialize I2Cx clock */ CPAL_I2C_HAL_CLKDeInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device Clock Deinit"); #ifdef CPAL_I2C_DMA_PROGMODEL /* Deinitialize DMA Channels */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { CPAL_I2C_HAL_DMADeInit(pDevInitStruct->CPAL_Dev, pDevInitStruct->CPAL_Direction); CPAL_LOG("\n\rLOG : I2C Device DMA Deinit"); } #endif /* CPAL_I2C_DMA_PROGMODEL */ /*-------------------------------------------------------------------------- GPIO pins configuration ---------------------------------------------------------------------------*/ /* Initialize I2Cx GPIO */ CPAL_I2C_HAL_GPIOInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device IOs Init"); /*-------------------------------------------------------------------------- Peripheral Clock Initialization ---------------------------------------------------------------------------*/ /* Initialize I2Cx clock */ CPAL_I2C_HAL_CLKInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device Clock Init"); /*-------------------------------------------------------------------------- Peripheral Initialization ---------------------------------------------------------------------------*/ /* Initialize I2Cx device with parameters stored in pCPAL_I2C_Struct */ I2C_Init(CPAL_I2C_DEVICE[pDevInitStruct->CPAL_Dev], pDevInitStruct->pCPAL_I2C_Struct); CPAL_LOG("\n\rLOG : I2C Device Config"); /* If General Call mode option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_GENCALL) != 0) { /* Enable GENERAL CALL address mode */ __CPAL_I2C_HAL_ENABLE_GENCALL(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device GENCALL Mode Enabled"); } /* If OA2 Address mode option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_DUALADDR) != 0) { /* Configure OA2 */ __CPAL_I2C_HAL_OA2_CONF(pDevInitStruct->CPAL_Dev, (uint32_t)(pDevInitStruct->wCPAL_Options & 0x000000FE)); /* Configure OA2 masks */ __CPAL_I2C_HAL_OA2_MASK_CONF(pDevInitStruct->CPAL_Dev, (uint32_t)((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_OA2_MASK) >> 25)); /* Enable OA2 address mode */ __CPAL_I2C_HAL_ENABLE_OA2(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device OA2 ADDR Mode Enabled"); } /* If WakeUp from STOP option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_WAKEUP_STOP) != 0) { /* Enable WakeUp from STOP mode */ __CPAL_I2C_HAL_ENABLE_WAKEUP(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device WakeUp from Stop Mode Enabled"); } else { /* Disable WakeUp from STOP mode */ __CPAL_I2C_HAL_DISABLE_WAKEUP(pDevInitStruct->CPAL_Dev); } /* If NACK Slave Own Address option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0) { /* Disable Acknowledgement of own Address */ __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device NACK Own Address Mode Enabled"); } #ifdef CPAL_I2C_DMA_PROGMODEL /*---------------------------------------------------------------------------- DMA Initialization : ---------------------------------------------------------------------------*/ /* If DMA Programming model is selected*/ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { /* Initialize I2Cx DMA channels */ CPAL_I2C_HAL_DMAInit(pDevInitStruct->CPAL_Dev, pDevInitStruct->CPAL_Direction, pDevInitStruct->wCPAL_Options); CPAL_LOG("\n\rLOG : I2C Device DMA Init"); } #endif /* CPAL_I2C_DMA_PROGMODEL */ /*---------------------------------------------------------------------------- Peripheral and DMA interrupts Initialization ---------------------------------------------------------------------------*/ /* Initialize I2Cx interrupts */ CPAL_I2C_HAL_ITInit(pDevInitStruct->CPAL_Dev, pDevInitStruct->wCPAL_Options); CPAL_LOG("\n\rLOG : I2C Device IT Init"); /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; CPAL_LOG("\n\rLOG : I2C Device Ready"); /* Initialize Timeout procedure */ _CPAL_TIMEOUT_INIT(); return CPAL_PASS; } /* If CPAL_State is BUSY (a transaction is still on going) exit Init function */ else { CPAL_LOG("\n\rERROR : I2C Device Busy"); return CPAL_FAIL; } } /** * @brief Deinitialize the peripheral and all related clocks, GPIOs, DMA and NVIC * to their reset values. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL * @note The Peripheral clock is disabled but the GPIO Ports clocks remains * enabled after this deinitialization. */ uint32_t CPAL_I2C_DeInit(CPAL_InitTypeDef* pDevInitStruct) { CPAL_LOG("\n\r\n\rLOG : I2C Device Deinit"); /* If CPAL_State is not BUSY */ if ((pDevInitStruct->CPAL_State == CPAL_STATE_READY) || (pDevInitStruct->CPAL_State == CPAL_STATE_ERROR) || (pDevInitStruct->CPAL_State == CPAL_STATE_DISABLED)) { /* - If CPAL_State is CPAL_STATE_ERROR (an Error occurred in transaction): Perform the deinitialization routines - If CPAL_State is CPAL_STATE_READY: Perform the deinitialization routines - If CPAL_State is CPAL_STATE_DISABLED: Perform the deinitialization routines */ /*-------------------------------------------------------------------------- GPIO pins Deinitialization Note: The GPIO clock remains enabled after this deinitialization ---------------------------------------------------------------------------*/ /* Deinitialize I2Cx GPIO */ CPAL_I2C_HAL_GPIODeInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device IOs Deinit"); /*-------------------------------------------------------------------------- Peripheral Deinitialization ---------------------------------------------------------------------------*/ /* Disable I2Cx device */ __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device Disabled"); /*-------------------------------------------------------------------------- Peripheral Clock Deinitialization ---------------------------------------------------------------------------*/ /* Deinitialize I2Cx clock */ CPAL_I2C_HAL_CLKDeInit(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device Clock Deinit"); #ifdef CPAL_I2C_DMA_PROGMODEL /*-------------------------------------------------------------------------- DMA Deinitialization : if DMA Programming model is selected ---------------------------------------------------------------------------*/ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { CPAL_I2C_HAL_DMADeInit(pDevInitStruct->CPAL_Dev, pDevInitStruct->CPAL_Direction); CPAL_LOG("\n\rLOG : I2C Device DMA Deinit"); } #endif /* CPAL_I2C_DMA_PROGMODEL */ /*-------------------------------------------------------------------------- Interrupts Deinitialization ---------------------------------------------------------------------------*/ CPAL_I2C_HAL_ITDeInit(pDevInitStruct->CPAL_Dev, pDevInitStruct->wCPAL_Options); CPAL_LOG("\n\rLOG : I2C Device IT Deinit"); /*-------------------------------------------------------------------------- Structure fields initialization ----------------------------------------------------------------------------*/ /* Initialize pDevInitStruct state parameters to their default values */ pDevInitStruct-> CPAL_State = CPAL_STATE_DISABLED; /* Device Disabled */ pDevInitStruct-> wCPAL_DevError = CPAL_I2C_ERR_NONE; /* No Device Error */ pDevInitStruct-> wCPAL_Timeout = ((uint32_t)CPAL_I2C_TIMEOUT_DEFAULT); /* Set timeout value to CPAL_I2C_TIMEOUT_DEFAULT */ CPAL_LOG("\n\rLOG :Set State fields to default"); /*---------------------------------------------------------------------------- Deinitialize Timeout Procedure -----------------------------------------------------------------------------*/ _CPAL_TIMEOUT_DEINIT(); return CPAL_PASS; } /* If CPAL_State is BUSY (a transaction is still on going) Exit Init function */ else { CPAL_LOG("\n\rERROR : I2C Device Busy"); return CPAL_FAIL; } } /** * @brief Initialize the peripheral structure with default values according * to the specified parameters in the CPAL_I2CDevTypeDef structure. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_StructInit(CPAL_InitTypeDef* pDevInitStruct) { /* Initialize I2C_InitStructure to their default values */ I2C_InitStructure.I2C_Timing = 0; /* Initialize the I2C_Timing member */ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; /* Initialize the I2C_Mode member */ I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable; /* Initialize the I2C_AnalogFilter member */ I2C_InitStructure.I2C_DigitalFilter = 0x00; /* Initialize the I2C_DigitalFilter member */ I2C_InitStructure.I2C_OwnAddress1 = 0; /* Initialize the I2C_OwnAddress1 member */ I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; /* Initialize the I2C_Ack member */ I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* Initialize the I2C_AcknowledgedAddress member */ /* Initialize pDevInitStruct parameter to their default values */ pDevInitStruct->CPAL_Direction = CPAL_DIRECTION_TXRX; /* Transmitter and Receiver direction selected */ pDevInitStruct->CPAL_Mode = CPAL_MODE_MASTER; /* Mode Master selected */ pDevInitStruct->CPAL_ProgModel = CPAL_PROGMODEL_DMA; /* DMA Programming Model selected */ pDevInitStruct->pCPAL_TransferTx = pNULL; /* Point pCPAL_TransferTx to a Null pointer */ pDevInitStruct->pCPAL_TransferRx = pNULL; /* Point pCPAL_TransferRx to a Null pointer */ pDevInitStruct->CPAL_State = CPAL_STATE_DISABLED; /* Device Disabled */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_NONE; /* No Device Error */ pDevInitStruct->wCPAL_Options = ((uint32_t)0x00000000); /* No Options selected */ pDevInitStruct->wCPAL_Timeout = ((uint32_t)CPAL_I2C_TIMEOUT_DEFAULT); /* Set timeout value to CPAL_I2C_TIMEOUT_DEFAULT */ pDevInitStruct->pCPAL_I2C_Struct = &I2C_InitStructure; /* Point to I2C_InitStructure (with default values) */ CPAL_LOG("\n\r\n\rLOG : I2C Device Structure set to Default Value"); return CPAL_PASS; } #if defined (CPAL_I2C_MASTER_MODE) || ! defined (CPAL_I2C_LISTEN_MODE) /** * @brief Allows to send a data or a buffer of data through the peripheral to * a selected device in a selected location address. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_Write(CPAL_InitTypeDef* pDevInitStruct) { CR2_tmp = 0; /* Check I2C State: - If busy --> exit Write operation - If disabled --> exit Write operation - If error --> exit Write operation - If ready --> *- Update CPAL_State to CPAL_STATE_BUSY *- If CPAL_OPT_I2C_NOSTOP_MODE is not selected : - Check if device is busy. *- Update CPAL_State to CPAL_STATE_READY_TX *- If DMA Prog Model : - Configure and enable DMA *- If Master mode : - If 10Bit Mode : Enable ADD10 - Configure Slave address *- If Memory Address mode (master) - Send target and memory address *- Update CPAL_State to CPAL_STATE_BUSY_TX *- If Master mode : - Configure AUTOEND, RELOAD and NBYTES - If Interrupt Prog Model : - Generate start and enable interrupts - If DMA Prog Model : - Enable TX DMA request - Generate start and enable interrupts *- If Slave mode : - If Interrupt Prog Model : - Enable interrupts - If DMA Prog Model : - Enable TX DMA request - Enable interrupts */ CPAL_LOG("\n\r\n\rLOG : I2C Device Write OP"); /* If Device is Busy (a transaction is still on going) Exit Write function */ if (((pDevInitStruct->CPAL_State & CPAL_STATE_BUSY) != 0) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_TX) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_RX)) { CPAL_LOG("\n\rERROR : I2C Device Busy"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_DISABLED (device is not initialized) Exit Write function */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_DISABLED) { CPAL_LOG("\n\rERROR : I2C Device Not Initialized"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_ERROR (Error occurred ) */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_ERROR) { CPAL_LOG("\n\rERROR : I2C Device Error"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_READY ( Start Communication )*/ else { /* Update CPAL_State to CPAL_STATE_BUSY */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY; /* IF CPAL_OPT_I2C_NOSTOP_MODE is not selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP_MODE) == 0) { /* Wait until BUSY flag is reset */ __CPAL_I2C_TIMEOUT(!(__CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_BUSY); } /* Update CPAL_State to CPAL_STATE_READY_TX */ pDevInitStruct->CPAL_State = CPAL_STATE_READY_TX; CPAL_LOG("\n\rLOG : I2C Device Ready TX"); #ifdef CPAL_I2C_DMA_PROGMODEL /* If DMA programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { /* Configure and enable TX DMA channel */ I2C_Enable_DMA(pDevInitStruct, CPAL_DIRECTION_TX); } #endif /* CPAL_I2C_DMA_PROGMODEL */ #ifdef CPAL_I2C_MASTER_MODE /* If master mode selected */ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER) { #ifdef CPAL_I2C_10BIT_ADDR_MODE /* If 10 Bit addressing mode */ if (pDevInitStruct->pCPAL_I2C_Struct->I2C_AcknowledgedAddress == I2C_AcknowledgedAddress_10bit) { /* Enable 10Bit addressing mode */ CR2_tmp |= I2C_CR2_ADD10; } #endif /* CPAL_I2C_10BIT_ADDR_MODE */ /* Configure slave address */ CR2_tmp |= (uint32_t)((pDevInitStruct->pCPAL_TransferTx->wAddr1) & 0x000003FF); } #ifdef CPAL_I2C_MEM_ADDR /* If CPAL_OPT_NO_MEM_ADDR is not selected and master mode selected */ if (((pDevInitStruct->wCPAL_Options & CPAL_OPT_NO_MEM_ADDR) == 0) && (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER )) { CPAL_LOG("\n\rLOG : I2C Device Master Mem Addr Mode"); /* Enable reload */ CR2_tmp |= I2C_CR2_RELOAD; /* Disable error interrupt to manage error without interrupt */ __CPAL_I2C_HAL_DISABLE_ERRIT(pDevInitStruct->CPAL_Dev); /* If 8 Bit register mode */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_16BIT_REG) == 0) { /* Configure Nbytes */ CR2_tmp |= (uint32_t)((uint32_t)(1) << 16); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Generate start */ __CPAL_I2C_HAL_START(pDevInitStruct->CPAL_Dev); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)(pDevInitStruct->pCPAL_TransferTx->wAddr2)); } #ifdef CPAL_16BIT_REG_OPTION /* If 16 Bit register mode */ else { /* Configure Nbytes */ CR2_tmp |= (uint32_t)((uint32_t)(2) << 16); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Generate start */ __CPAL_I2C_HAL_START(pDevInitStruct->CPAL_Dev); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address (MSB) */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)(((pDevInitStruct->pCPAL_TransferTx->wAddr2)& 0xFF00) >> 8)); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address (LSB) */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)((pDevInitStruct->pCPAL_TransferTx->wAddr2)& 0x00FF)); } #endif /* CPAL_16BIT_REG_OPTION */ /* If I2C ERR Interrupt Option Bit not selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_ERRIT_DISABLE) == 0) { /* Enable I2C Error Interrupts */ __CPAL_I2C_HAL_ENABLE_ERRIT(pDevInitStruct->CPAL_Dev); } /* Wait until TCR flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_TCR(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_TCR); /* Set Nbytes to zero */ CR2_tmp &= ~I2C_CR2_NBYTES; } #endif /* CPAL_I2C_MEM_ADDR */ #endif /* CPAL_I2C_MASTER_MODE */ /* Update CPAL_State to CPAL_STATE_BUSY_TX */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY_TX; CPAL_LOG("\n\rLOG : I2C Device Busy TX"); #ifdef CPAL_I2C_MASTER_MODE /* If master mode selected */ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER) { CPAL_LOG("\n\rLOG : I2C Device Master"); /* If automatic end mode is selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_AUTOMATIC_END) != 0) { /* Enable automatic end mode */ CR2_tmp |= I2C_CR2_AUTOEND; } /* If number of data is equal or lower than 255 bytes */ if (pDevInitStruct->pCPAL_TransferTx->wNumData <= 0xFF ) { /* Update Num_Data */ Num_Data = pDevInitStruct->pCPAL_TransferTx->wNumData; /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(Num_Data) << 16); /* Disable reload */ CR2_tmp &= ~I2C_CR2_RELOAD; } /* If number of data is greater than 255 bytes */ else { /* Set Nbytes to 255 */ CR2_tmp |= (uint32_t)((uint32_t)(255) << 16); /* Enable reload */ CR2_tmp |= I2C_CR2_RELOAD; } /* If CPAL_OPT_NO_MEM_ADDR is selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_NO_MEM_ADDR) != 0) { /* Generate start */ CR2_tmp |= I2C_CR2_START; } /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* If interrupt programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { CPAL_LOG("\n\rLOG : I2C Device IT Enabled"); /* Enable master interrupts */ __CPAL_I2C_HAL_ENABLE_MASTER_TXIT(pDevInitStruct->CPAL_Dev); } /* If DMA programming model */ else { CPAL_LOG("\n\rLOG : I2C Device DMA TX Enabled"); /* Enable TX DMA request */ __CPAL_I2C_HAL_ENABLE_TXDMAREQ(pDevInitStruct->CPAL_Dev); /* Enable master interrupts */ __CPAL_I2C_HAL_ENABLE_MASTER_IT(pDevInitStruct->CPAL_Dev); } } /* If slave mode selected */ else #endif /* CPAL_I2C_MASTER_MODE */ { #ifdef CPAL_I2C_SLAVE_MODE CPAL_LOG("\n\rLOG : I2C Device Slave"); /* If NACK Slave Own Address option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0) { /* Enable Acknowledgement of Own address */ __CPAL_I2C_HAL_ENABLE_DEV(pDevInitStruct->CPAL_Dev); } /* If interrupt programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { CPAL_LOG("\n\rLOG : I2C Device IT Enabled"); /* Enable slave interrupts */ __CPAL_I2C_HAL_ENABLE_SLAVE_TXIT(pDevInitStruct->CPAL_Dev); } /* If DMA programming model */ else { CPAL_LOG("\n\rLOG : I2C Device DMA TX Enabled"); /* Enable TX DMA request */ __CPAL_I2C_HAL_ENABLE_TXDMAREQ(pDevInitStruct->CPAL_Dev); /* Enable slave interrupts */ __CPAL_I2C_HAL_ENABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_SLAVE_MODE */ } } return CPAL_PASS; } /** * @brief Allows to receive a data or a buffer of data through the peripheral * from a selected device in a selected location address. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_Read(CPAL_InitTypeDef* pDevInitStruct) { CR2_tmp = 0; /* Check I2C State: - If busy --> exit Read operation - If disabled --> exit Read operation - If error --> exit Read operation - If ready --> *- Update CPAL_State to CPAL_STATE_BUSY *- If CPAL_OPT_I2C_NOSTOP_MODE is not selected : - Check if device is busy *- Update CPAL_State to CPAL_STATE_READY_RX *- If DMA Prog Model : - Configure and enable DMA *- If Master mode : - If 10Bit Mode : Enable ADD10 - Configure Slave address *- If Memory Address mode (master) - Send target and memory address *- Update CPAL_State to CPAL_STATE_BUSY_RX *- If Master mode : - Configure HEADR10, AUTOEND, RELOAD and NBYTES - If Interrupt Prog Model : - Generate start and enable interrupts - If DMA Prog Model : - Enable RX DMA request - Generate start and enable interrupts *- If Slave mode : - If Interrupt Prog Model : - Enable interrupts - If DMA Prog Model : - Enable RX DMA request - Enable interrupts */ CPAL_LOG("\n\r\n\rLOG : I2C Device Perform Read OP"); /* If Device is Busy (a transaction is still on going) Exit Read function */ if (((pDevInitStruct->CPAL_State & CPAL_STATE_BUSY) != 0) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_TX) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_RX)) { CPAL_LOG("\n\rERROR : I2C Device Busy"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_DISABLED (device is not initialized) Exit Read function */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_DISABLED) { CPAL_LOG("\n\rERROR : I2C Device Not Initialized"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_ERROR (Error occurred ) */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_ERROR) { CPAL_LOG("\n\rERROR : I2C Device Error"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_READY */ else { /* Update CPAL_State to CPAL_STATE_BUSY */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY; /* If CPAL_OPT_I2C_NOSTOP_MODE is not selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP_MODE) == 0) { /* Wait until BUSY flag is reset */ __CPAL_I2C_TIMEOUT(!(__CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_BUSY); } /* Update CPAL_State to CPAL_STATE_READY_RX */ pDevInitStruct->CPAL_State = CPAL_STATE_READY_RX; CPAL_LOG("\n\rLOG : I2C Device Ready RX"); #ifdef CPAL_I2C_DMA_PROGMODEL /* If DMA programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { /* Configure and enable RX DMA channel */ I2C_Enable_DMA(pDevInitStruct, CPAL_DIRECTION_RX); } #endif /* CPAL_I2C_DMA_PROGMODEL */ #ifdef CPAL_I2C_MASTER_MODE /* If master mode selected */ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER) { #ifdef CPAL_I2C_10BIT_ADDR_MODE /* If 10 Bit addressing mode */ if (pDevInitStruct->pCPAL_I2C_Struct->I2C_AcknowledgedAddress == I2C_AcknowledgedAddress_10bit) { /* Enable 10Bit addressing mode */ CR2_tmp |= I2C_CR2_ADD10; } #endif /* CPAL_I2C_10BIT_ADDR_MODE */ /* Configure slave address */ CR2_tmp |= (uint32_t)((pDevInitStruct->pCPAL_TransferRx->wAddr1) & 0x000003FF); } #ifdef CPAL_I2C_MEM_ADDR /* If No Memory Address option bit is not selected and master mode selected */ if (((pDevInitStruct->wCPAL_Options & CPAL_OPT_NO_MEM_ADDR) == 0) && (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER )) { CPAL_LOG("\n\rLOG : I2C Device Master Mem Addr Mode"); /* Disable error interrupt to manage error without interrupt */ __CPAL_I2C_HAL_DISABLE_ERRIT(pDevInitStruct->CPAL_Dev); /* If 8 Bit register mode */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_16BIT_REG) == 0) { /* Configure Nbytes */ CR2_tmp |= (uint32_t)((uint32_t)(1) << 16); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Generate start */ __CPAL_I2C_HAL_START(pDevInitStruct->CPAL_Dev); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)(pDevInitStruct->pCPAL_TransferRx->wAddr2)); } #ifdef CPAL_16BIT_REG_OPTION /* If 16 Bit register mode */ else { /* Configure Nbytes */ CR2_tmp |= (uint32_t)((uint32_t)(2) << 16); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Generate start */ __CPAL_I2C_HAL_START(pDevInitStruct->CPAL_Dev); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address (MSB) */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)(((pDevInitStruct->pCPAL_TransferRx->wAddr2)& 0xFF00) >> 8)); /* Wait until TXIS flag is set or NACK is set */ __CPAL_I2C_TIMEOUT((__CPAL_I2C_HAL_GET_TXIS(pDevInitStruct->CPAL_Dev) || __CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_TXIS); /* If acknowledge failure detected generate stop and abort communication */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev)) { /* Generate stop if autoend option is disabled */ if((CPAL_I2C_DEVICE[(pDevInitStruct->CPAL_Dev)]->CR2 & I2C_CR2_AUTOEND) != I2C_CR2_AUTOEND) { /* Generate stop */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Wait until STOP flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_BUSY); /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; return CPAL_FAIL; } /* Send register address (LSB) */ __CPAL_I2C_HAL_SEND(pDevInitStruct->CPAL_Dev, (uint8_t)((pDevInitStruct->pCPAL_TransferRx->wAddr2)& 0x00FF)); } #endif /* CPAL_16BIT_REG_OPTION */ /* If I2C ERR Interrupt Option Bit not selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_ERRIT_DISABLE) == 0) { /* Enable I2C Error Interrupts */ __CPAL_I2C_HAL_ENABLE_ERRIT(pDevInitStruct->CPAL_Dev); } /* Wait until TC flag is set */ __CPAL_I2C_TIMEOUT(__CPAL_I2C_HAL_GET_TC(pDevInitStruct->CPAL_Dev), CPAL_I2C_TIMEOUT_TC); /* Set Nbytes to zero */ CR2_tmp &= ~I2C_CR2_NBYTES; } #endif /* CPAL_I2C_MEM_ADDR */ #endif /* CPAL_I2C_MASTER_MODE */ /* Update CPAL_State to CPAL_STATE_BUSY_RX */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY_RX; CPAL_LOG("\n\rLOG : I2C Device Busy RX"); #ifdef CPAL_I2C_MASTER_MODE /* If master mode selected */ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER) { CPAL_LOG("\n\rLOG : I2C Device Master"); /* Enable transfer request */ CR2_tmp |= I2C_CR2_RD_WRN; #ifdef CPAL_I2C_10BIT_ADDR_MODE /* If 10 Bit addressing mode */ if (pDevInitStruct->pCPAL_I2C_Struct->I2C_AcknowledgedAddress == I2C_AcknowledgedAddress_10bit) { /* If CPAL_OPT_NO_MEM_ADDR is not selected and CPAL_OPT_I2C_10BIT_HEADR option enabled */ if (((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_10BIT_HEADR) != 0) || ((pDevInitStruct->wCPAL_Options & CPAL_OPT_NO_MEM_ADDR) == 0)) { /* Disable 10Bit addressing complete sequence for Read */ CR2_tmp |= I2C_CR2_HEAD10R; } } #endif /* CPAL_I2C_10BIT_ADDR_MODE */ /* If automatic end mode is selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_AUTOMATIC_END) != 0) { /* Enable automatic end mode */ CR2_tmp |= I2C_CR2_AUTOEND; } /* If number of data is equal or lower than 255 bytes */ if (pDevInitStruct->pCPAL_TransferRx->wNumData <= 0xFF ) { /* Update Num_Data */ Num_Data = pDevInitStruct->pCPAL_TransferRx->wNumData; /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(Num_Data) << 16); /* Disable reload */ CR2_tmp &= ~I2C_CR2_RELOAD; } /* If number of data is greater than 255 bytes */ else { /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(255) << 16); /* Enaable reload */ CR2_tmp |= I2C_CR2_RELOAD; } /* Generate start */ CR2_tmp |= I2C_CR2_START; /* If interrupt programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { CPAL_LOG("\n\rLOG : I2C Device IT Enabled"); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Enable master interrupts */ __CPAL_I2C_HAL_ENABLE_MASTER_RXIT(pDevInitStruct->CPAL_Dev); } /* If DMA programming model */ else { CPAL_LOG("\n\rLOG : I2C Device DMA RX Enabled"); /* Enable RX DMA request */ __CPAL_I2C_HAL_ENABLE_RXDMAREQ(pDevInitStruct->CPAL_Dev); /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Enable master interrupt */ __CPAL_I2C_HAL_ENABLE_MASTER_IT(pDevInitStruct->CPAL_Dev); } } /* If slave mode selected */ else #endif /* CPAL_I2C_MASTER_MODE */ { #ifdef CPAL_I2C_SLAVE_MODE CPAL_LOG("\n\rLOG : I2C Device Slave"); /* If NACK Slave Own Address option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0) { /* Enable Acknowledgement of Own address */ __CPAL_I2C_HAL_ENABLE_DEV(pDevInitStruct->CPAL_Dev); } /* If interrupt programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { CPAL_LOG("\n\rLOG : I2C Device IT Enabled"); /* Enable slave interrupts */ __CPAL_I2C_HAL_ENABLE_SLAVE_RXIT(pDevInitStruct->CPAL_Dev); } /* If DMA programming model */ else { CPAL_LOG("\n\rLOG : I2C Device DMA RX Enabled"); /* Enable RX DMA request */ __CPAL_I2C_HAL_ENABLE_RXDMAREQ(pDevInitStruct->CPAL_Dev); /* Enable slave interrupt */ __CPAL_I2C_HAL_ENABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_SLAVE_MODE */ } } return CPAL_PASS; } #endif /* CPAL_I2C_MASTER_MODE || ! CPAL_I2C_LISTEN_MODE */ #if defined (CPAL_I2C_LISTEN_MODE) && defined (CPAL_I2C_SLAVE_MODE) /** * @brief Allows slave device to start a communication without knowing in advance * the nature of the operation (read or write). Slave waits until it receive * its own address.CPAL_I2C_SLAVE_READ_UserCallback is called for a read request * and CPAL_I2C_SLAVE_WRITE_UserCallback for a write request in I2C_SLAVE_ADDR_Handle. * User must implement inorder to configure DMA, interrupts and transfer parameters. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_Listen(CPAL_InitTypeDef* pDevInitStruct) { /* Check I2C State: - If busy --> exit operation - If disabled --> exit operation - If error --> exit operation - If ready --> - Enable Event Interrupt */ CPAL_LOG("\n\r\n\rLOG : I2C Device in listen mode"); /* If Device is Busy (a transaction is still on going) Exit function */ if (((pDevInitStruct->CPAL_State & CPAL_STATE_BUSY) != 0) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_TX) || (pDevInitStruct->CPAL_State == CPAL_STATE_READY_RX)) { CPAL_LOG("\n\rERROR : I2C Device Busy"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_DISABLED (device is not initialized) Exit function */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_DISABLED) { CPAL_LOG("\n\rERROR : I2C Device Not Initialized"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_ERROR (Error occurred ) */ else if (pDevInitStruct->CPAL_State == CPAL_STATE_ERROR) { CPAL_LOG("\n\rERROR : I2C Device Error"); return CPAL_FAIL; } /* If CPAL_State is CPAL_STATE_READY */ else { /* If NACK Slave Own Address option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0) { /* Enable Acknowledgement of Own address */ __CPAL_I2C_HAL_ENABLE_DEV(pDevInitStruct->CPAL_Dev); } /* Set device to slave mode */ pDevInitStruct->CPAL_Mode = CPAL_MODE_SLAVE; /* Update CPAL_State to CPAL_STATE_BUSY */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY; CPAL_LOG("\n\rLOG : I2C Device EVT IT Enabled"); /* Enable Slave Interrupts*/ __CPAL_I2C_HAL_ENABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); } return CPAL_PASS; } #endif /* CPAL_I2C_LISTEN_MODE && CPAL_I2C_SLAVE_MODE */ /** * @brief Wait until target device is ready for communication (This function is * used with Memory devices). * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_IsDeviceReady(CPAL_InitTypeDef* pDevInitStruct) { CR2_tmp = 0; CPAL_LOG("\n\r\n\rLOG : Wait until I2C Device is Ready"); /* Set CPAL_State to CPAL_STATE_BUSY */ pDevInitStruct->CPAL_State = CPAL_STATE_BUSY; /* Disable I2Cx device */ __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev); /* Enable I2Cx device */ __CPAL_I2C_HAL_ENABLE_DEV(pDevInitStruct->CPAL_Dev); /* Disable interrupts */ __CPAL_I2C_HAL_DISABLE_ALLIT(pDevInitStruct->CPAL_Dev); /* Configure slave address */ CR2_tmp |= (uint32_t)((pDevInitStruct->pCPAL_TransferTx->wAddr1) & 0x000003FF) | I2C_CR2_AUTOEND; /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); /* Generate Start */ __CPAL_I2C_HAL_START(pDevInitStruct->CPAL_Dev); /* Set 35ms timeout */ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_MIN + 35; /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is set or a NACK flag is set*/ while((__CPAL_I2C_HAL_GET_STOP(pDevInitStruct->CPAL_Dev) == RESET) && (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev) == RESET)); /* Reinitialize Timeout Value to default */ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT; /* Check if the NACKF flag has not been set */ if (__CPAL_I2C_HAL_GET_NACK(pDevInitStruct->CPAL_Dev) != RESET) { /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* Clear Stop flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Enable error interrupt */ __CPAL_I2C_HAL_ENABLE_ERRIT(pDevInitStruct->CPAL_Dev); /* Set CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; return CPAL_FAIL; } else { /* Clear Stop flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); /* Enable error interrupt */ __CPAL_I2C_HAL_ENABLE_ERRIT(pDevInitStruct->CPAL_Dev); /* Set CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; CPAL_LOG("\n\rLOG : I2C Target device Ready"); return CPAL_PASS; } } /*================== CPAL_I2C_Interrupt_Handler ==================*/ /** * @brief This function handles I2C interrupt request for preparing communication * and for transfer phase in case of using Interrupt Programming Model. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS. */ uint32_t CPAL_I2C_EV_IRQHandler( CPAL_InitTypeDef* pDevInitStruct) { __IO uint32_t I2CFlagStatus = 0x00000000; /* Read I2C status registers (ISR) */ I2CFlagStatus = __CPAL_I2C_HAL_GET_EVENT(pDevInitStruct->CPAL_Dev); #ifdef CPAL_I2C_MASTER_MODE /*----------------------------------------------------------------------------------------------*/ /*---------------------------------- If Master Mode selected ----------------------------------*/ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_MASTER) { #ifdef CPAL_I2C_IT_PROGMODEL /*----------------------------------------*/ /*------------- If TXIS event ------------*/ if (((I2CFlagStatus & CPAL_I2C_EVT_TXIS) != 0) && (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX)) { I2C_MASTER_TXIS_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If RXNE event ------------*/ if (((I2CFlagStatus & CPAL_I2C_EVT_RXNE) != 0) && (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_RX)) { I2C_MASTER_RXNE_Handle(pDevInitStruct); } #endif /* CPAL_I2C_IT_PROGMODEL */ /*----------------------------------------*/ /*-------------- If TCR event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_TCR) != 0) { I2C_MASTER_TCR_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If TC event --------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_TC ) != 0) { I2C_MASTER_TC_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If STOP event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_STOP) != 0) { I2C_MASTER_STOP_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If NACK event ------------*/ if((I2CFlagStatus & CPAL_I2C_EVT_NACK ) != 0) { I2C_MASTER_NACK_Handle(pDevInitStruct); } } #endif /* CPAL_I2C_MASTER_MODE */ #ifdef CPAL_I2C_SLAVE_MODE /*----------------------------------------------------------------------------------------------*/ /*---------------------------------- If Slave Mode selected ------------------------------------*/ if (pDevInitStruct->CPAL_Mode == CPAL_MODE_SLAVE) { /*----------------------------------------*/ /*------------- If ADDR event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_ADDR ) != 0) { I2C_SLAVE_ADDR_Handle(pDevInitStruct); } #ifdef CPAL_I2C_IT_PROGMODEL /*----------------------------------------*/ /*------------- If TXIS event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_TXIS) != 0) { I2C_SLAVE_TXIS_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If RXNE event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_RXNE) != 0) { I2C_SLAVE_RXNE_Handle(pDevInitStruct); } #endif /* CPAL_I2C_IT_PROGMODEL */ /*----------------------------------------*/ /*------------- If NACK event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_NACK) != 0) { I2C_SLAVE_NACK_Handle(pDevInitStruct); } /*----------------------------------------*/ /*------------- If STOP event ------------*/ if ((I2CFlagStatus & CPAL_I2C_EVT_STOP) != 0) { I2C_SLAVE_STOP_Handle(pDevInitStruct); } } #endif /* CPAL_I2C_SLAVE_MODE */ return CPAL_PASS; } /** * @brief Allows to handle errors occurred during initialization or communication * in order to recover the correct communication status or call specific * user functions. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS. */ uint32_t CPAL_I2C_ER_IRQHandler(CPAL_InitTypeDef* pDevInitStruct) { /* Read error register and affect to wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = __CPAL_I2C_HAL_GET_ERROR(pDevInitStruct->CPAL_Dev); /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; CPAL_LOG("\n\r\n\rERROR : I2C Device Error"); /* If Bus error occurred ---------------------------------------------------*/ if ((pDevInitStruct->wCPAL_DevError & CPAL_I2C_ERR_BERR) != 0) { CPAL_LOG("\n\rERROR : I2C Device BERR"); /* Clear error flag */ __CPAL_I2C_HAL_CLEAR_BERR(pDevInitStruct->CPAL_Dev); #ifdef USE_MULTIPLE_ERROR_CALLBACK /* Call Bus Error UserCallback */ CPAL_I2C_BERR_UserCallback(pDevInitStruct->CPAL_Dev); #endif /* USE_MULTIPLE_ERROR_CALLBACK */ } /* If Arbitration Loss error occurred --------------------------------------*/ if ((pDevInitStruct->wCPAL_DevError & CPAL_I2C_ERR_ARLO) != 0) { CPAL_LOG("\n\rERROR : I2C Device ARLO"); /* Clear error flag */ __CPAL_I2C_HAL_CLEAR_ARLO(pDevInitStruct->CPAL_Dev); #ifdef USE_MULTIPLE_ERROR_CALLBACK /* Call Arbitration Lost UserCallback */ CPAL_I2C_ARLO_UserCallback(pDevInitStruct->CPAL_Dev); #endif /* USE_MULTIPLE_ERROR_CALLBACK */ } /* If Overrun error occurred -----------------------------------------------*/ if ((pDevInitStruct->wCPAL_DevError & CPAL_I2C_ERR_OVR) != 0) { CPAL_LOG("\n\rERROR : I2C Device OVR"); /* No I2C software reset is performed here in order to allow user to get back the last data received correctly */ /* Clear error flag */ __CPAL_I2C_HAL_CLEAR_OVR(pDevInitStruct->CPAL_Dev); #ifdef USE_MULTIPLE_ERROR_CALLBACK /* Call Overrun error UserCallback */ CPAL_I2C_OVR_UserCallback(pDevInitStruct->CPAL_Dev); #endif /* USE_MULTIPLE_ERROR_CALLBACK */ } /* USE_SINGLE_ERROR_CALLBACK is defined in stm32f0xx_i2c_cpal_conf.h file */ #ifdef USE_SINGLE_ERROR_CALLBACK /* Call Error UserCallback */ CPAL_I2C_ERR_UserCallback(pDevInitStruct->CPAL_Dev, pDevInitStruct->wCPAL_DevError); #endif /* USE_SINGLE_ERROR_CALLBACK */ return CPAL_PASS; } #ifdef CPAL_I2C_DMA_PROGMODEL /** * @brief Handle I2C DMA TX interrupt request when DMA programming Model is * used for data transmission. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS. */ uint32_t CPAL_I2C_DMA_TX_IRQHandler(CPAL_InitTypeDef* pDevInitStruct) { /* Reinitialize timeout value to default (no timeout initiated) */ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT; CPAL_LOG("\n\r\n\rLOG : I2C Device TX DMA "); /*------------- If TC interrupt ------------*/ if((__CPAL_I2C_HAL_GET_DMATX_TCIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rLOG : I2C Device TX Complete"); /* If DMA normal mode */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_DMATX_CIRCULAR) == 0) { /* Update remaining number of data */ pDevInitStruct->pCPAL_TransferTx->wNumData = 0; /* Call DMA TX TC UserCallback */ CPAL_I2C_DMATXTC_UserCallback(pDevInitStruct); /* Disable DMA request and channel */ __CPAL_I2C_HAL_DISABLE_TXDMAREQ(pDevInitStruct->CPAL_Dev); __CPAL_I2C_HAL_DISABLE_DMATX(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device TX DMA Disabled"); } /* If DMA circular mode */ else { /* Call DMA TX TC UserCallback */ CPAL_I2C_DMATXTC_UserCallback(pDevInitStruct); } } /*------------- If HT interrupt ------------*/ else if ((__CPAL_I2C_HAL_GET_DMATX_HTIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rLOG : I2C Device TX DMA Half Transfer "); /* Call DMA TX HT UserCallback */ CPAL_I2C_DMATXHT_UserCallback(pDevInitStruct); } /*------------- If TE interrupt ------------*/ else if ((__CPAL_I2C_HAL_GET_DMATX_TEIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rERROR : I2C Device TX DMA Transfer Error "); /* Update CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* Update remaining number of data */ pDevInitStruct->pCPAL_TransferTx->wNumData = __CPAL_I2C_HAL_DMATX_GET_CNDT(pDevInitStruct->CPAL_Dev); /* Call TX transfer complete UserCallback */ CPAL_I2C_RXTC_UserCallback(pDevInitStruct); } /* Clear DMA interrupt Flag */ __CPAL_I2C_HAL_CLEAR_DMATX_IT(pDevInitStruct->CPAL_Dev); return CPAL_PASS; } /** * @brief Handle I2C DMA RX interrupt request when DMA programming Model is * used for data reception. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS. */ uint32_t CPAL_I2C_DMA_RX_IRQHandler(CPAL_InitTypeDef* pDevInitStruct) { /* Reinitialize Timeout Value to default (no timeout initiated) */ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT; CPAL_LOG("\n\r\n\rLOG : I2C Device RX DMA "); /*------------- If TC interrupt ------------*/ if ((__CPAL_I2C_HAL_GET_DMARX_TCIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rLOG : I2C Device RX Complete"); /* If DMA normal mode */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_DMARX_CIRCULAR) == 0) { /* Update remaining number of data */ pDevInitStruct->pCPAL_TransferRx->wNumData = 0; /* Disable DMA Request and Channel */ __CPAL_I2C_HAL_DISABLE_RXDMAREQ(pDevInitStruct->CPAL_Dev); __CPAL_I2C_HAL_DISABLE_DMARX(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device RX DMA Disabled"); /* Call DMA RX TC UserCallback */ CPAL_I2C_DMARXTC_UserCallback(pDevInitStruct); /* If No Stop Condition Generation option bit selected */ if (((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP) != 0) && (pDevInitStruct->CPAL_Mode == CPAL_MODE_SLAVE)) { /* Disable slave interrupt */ __CPAL_I2C_HAL_DISABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call TX transfer complete UserCallback */ CPAL_I2C_TXTC_UserCallback(pDevInitStruct); } } /* If DMA circular mode */ else { /* Call DMA RX TC UserCallback */ CPAL_I2C_DMARXTC_UserCallback(pDevInitStruct); } } /*------------- If HT interrupt ------------*/ else if ((__CPAL_I2C_HAL_GET_DMARX_HTIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rLOG : I2C Device RX DMA Half Transfer"); /* Call DMA RX HT UserCallback */ CPAL_I2C_DMARXHT_UserCallback(pDevInitStruct); } /*------------- If TE interrupt ------------*/ else if ((__CPAL_I2C_HAL_GET_DMARX_TEIT(pDevInitStruct->CPAL_Dev)) != 0) { CPAL_LOG("\n\rERROR : I2C Device RX DMA Transfer Error "); /* Update CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* Update remaining number of data */ pDevInitStruct->pCPAL_TransferRx->wNumData = __CPAL_I2C_HAL_DMARX_GET_CNDT(pDevInitStruct->CPAL_Dev); /* Call DMA RX TE UserCallback */ CPAL_I2C_DMARXTE_UserCallback(pDevInitStruct); } /* Clear DMA interrupt Flag */ __CPAL_I2C_HAL_CLEAR_DMARX_IT(pDevInitStruct->CPAL_Dev); return CPAL_PASS; } #endif /* CPAL_I2C_DMA_PROGMODEL */ /*================== CPAL_I2C_Timeout_Function ==================*/ /** * @brief This function Manages I2C Timeouts when waiting for specific events. * @param None * @retval CPAL_PASS or CPAL_FAIL. */ void CPAL_I2C_TIMEOUT_Manager(void) { uint32_t index = 0; /* Manage I2C timeouts conditions */ for (index = 0; index < CPAL_I2C_DEV_NUM; index ++) { if (I2C_DevStructures[index] != pNULL) { /* If Timeout occurred */ if (I2C_DevStructures[index]->wCPAL_Timeout == CPAL_I2C_TIMEOUT_DETECTED) { /* Reinitialize timeout value */ I2C_DevStructures[index]->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT; /* Update CPAL_State to CPAL_STATE_ERROR */ I2C_DevStructures[index]->CPAL_State = CPAL_STATE_ERROR; /* In case of Device Error Timeout_Callback should not be called */ if (I2C_DevStructures[index]->wCPAL_DevError == CPAL_I2C_ERR_NONE) { /* Update wCPAL_DevError to CPAL_I2C_ERR_TIMEOUT */ I2C_DevStructures[index]->wCPAL_DevError = CPAL_I2C_ERR_TIMEOUT; CPAL_LOG("\n\r\n\rLOG : I2C Device Timeout Error"); /* Call CPAL_TIMEOUT_UserCallback */ CPAL_TIMEOUT_UserCallback(I2C_DevStructures[index]); } } /* If Timeout is triggered (wCPAL_Timeout != CPAL_I2C_TIMEOUT_DEFAULT)*/ else if (I2C_DevStructures[index]->wCPAL_Timeout != CPAL_I2C_TIMEOUT_DEFAULT) { /* Decrement the timeout value */ I2C_DevStructures[index]->wCPAL_Timeout--; } } } } /** * @brief This function Manages I2C Timeouts when Timeout occurred. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ uint32_t CPAL_I2C_Timeout (CPAL_InitTypeDef* pDevInitStruct) { /* Reinitialize timeout value */ pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT; /* update CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* update wCPAL_DevError to CPAL_I2C_ERR_TIMEOUT */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_TIMEOUT; /* Call Timeout Callback and quit current function */ return (CPAL_TIMEOUT_UserCallback(pDevInitStruct)); } /*================== CPAL_I2C_Event_Handler ==================*/ #ifdef CPAL_I2C_MASTER_MODE /** * @brief Handles Master TCR interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_TCR_Handle(CPAL_InitTypeDef* pDevInitStruct) { CR2_tmp = 0; /* If DMA programming model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_DMA) { /* If master transmitter */ if (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) { /* Update wNumData */ pDevInitStruct->pCPAL_TransferTx->wNumData = pDevInitStruct->pCPAL_TransferTx->wNumData - 0xff; } /* If master receiver */ else { /* Update wNumData */ pDevInitStruct->pCPAL_TransferRx->wNumData = pDevInitStruct->pCPAL_TransferRx->wNumData - 0xff; } } /* If master transmitter */ if (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) { /* If remaining number of data is equal or lower than 255 */ if (pDevInitStruct->pCPAL_TransferTx->wNumData <= 0xff) { /* Update Num_Data */ Num_Data = pDevInitStruct->pCPAL_TransferTx->wNumData; /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(Num_Data) << 16); /* Disable reload */ CR2_tmp &= ~I2C_CR2_RELOAD; } /* If remaining number of data is greater than 255 */ else { /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(255) << 16); /* Enaable reload */ CR2_tmp |= I2C_CR2_RELOAD; } } /* If master receiver */ else { /* If remaining number of data is equal or lower than 255 */ if (pDevInitStruct->pCPAL_TransferRx->wNumData <= 0xff) { /* Update num data */ Num_Data = pDevInitStruct->pCPAL_TransferRx->wNumData; /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(Num_Data) << 16); /* Disable reload */ CR2_tmp &= ~I2C_CR2_RELOAD; } /* If remaining number of data is greater than 255 */ else { /* Set Nbytes to wNumData */ CR2_tmp |= (uint32_t)((uint32_t)(255) << 16); /* Enaable reload */ CR2_tmp |= I2C_CR2_RELOAD; } } /* Update CR2 Register */ __CPAL_I2C_HAL_CR2_UPDATE(pDevInitStruct->CPAL_Dev, CR2_tmp); return CPAL_PASS; } /** * @brief Handles Master TC interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_TC_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* No Stop Condition Generation option bit is not selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP) == 0) { /* Generate stop condition */ __CPAL_I2C_HAL_STOP(pDevInitStruct->CPAL_Dev); } /* No Stop Condition Generation option bit is selected */ else { /* Disable master interrupts */ __CPAL_I2C_HAL_DISABLE_MASTER_IT(pDevInitStruct->CPAL_Dev); /* If master transmitter */ if (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable TX interrupt */ __CPAL_I2C_HAL_DISABLE_TXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call TX Transfer complete Callback */ CPAL_I2C_TXTC_UserCallback(pDevInitStruct); } /* If master receiver */ else { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable RX interrupt */ __CPAL_I2C_HAL_DISABLE_RXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call RX Transfer complete Callback */ CPAL_I2C_RXTC_UserCallback(pDevInitStruct); } } return CPAL_PASS; } /** * @brief Handles Master STOP interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_STOP_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* If NACK received by master */ if (pDevInitStruct->wCPAL_DevError == CPAL_I2C_ERR_AF) { /* Set CPAL_State to CPAL_STATE_ERROR */ pDevInitStruct->CPAL_State = CPAL_STATE_ERROR; /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); } else { /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\r\n\rLOG : I2C Device Master IT"); CPAL_LOG("\n\rLOG : I2C Device Stop Generated"); /* Disable master interrupt */ __CPAL_I2C_HAL_DISABLE_MASTER_IT(pDevInitStruct->CPAL_Dev); /* Wait until BUSY flag is reset */ __CPAL_I2C_TIMEOUT(!(__CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_BUSY); /* If master transmitter */ if (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable TX interrupt */ __CPAL_I2C_HAL_DISABLE_TXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call TX Transfer complete Callback */ CPAL_I2C_TXTC_UserCallback(pDevInitStruct); } /* If master receiver */ else { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable RX interrupt */ __CPAL_I2C_HAL_DISABLE_RXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call RX Transfer complete Callback */ CPAL_I2C_RXTC_UserCallback(pDevInitStruct); } } return CPAL_PASS; } /** * @brief Handles Master NACK interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_NACK_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* Update wCPAL_DevError */ pDevInitStruct->wCPAL_DevError = CPAL_I2C_ERR_AF; /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* USE_SINGLE_ERROR_CALLBACK is defined in stm32f0xx_i2c_cpal_conf.h file */ #ifdef USE_SINGLE_ERROR_CALLBACK /* Call Error UserCallback */ CPAL_I2C_ERR_UserCallback(pDevInitStruct->CPAL_Dev, pDevInitStruct->wCPAL_DevError); #elif defined(USE_MULTIPLE_ERROR_CALLBACK) /* Call AF UserCallback */ CPAL_I2C_AF_UserCallback(pDevInitStruct->CPAL_Dev); #endif /* USE_SINGLE_ERROR_CALLBACK */ return CPAL_PASS; } #ifdef CPAL_I2C_IT_PROGMODEL /** * @brief Handles Master transmission TXIS interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_TXIS_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* Call TX UserCallback */ CPAL_I2C_TX_UserCallback(pDevInitStruct); /* Write Byte */ __CPAL_I2C_HAL_SEND((pDevInitStruct->CPAL_Dev), (*(pDevInitStruct->pCPAL_TransferTx->pbBuffer))); /* Decrement remaining number of data */ pDevInitStruct->pCPAL_TransferTx->wNumData--; if (pDevInitStruct->pCPAL_TransferTx->wNumData != 0) { /* Point to next data */ pDevInitStruct->pCPAL_TransferTx->pbBuffer++; } return CPAL_PASS; } /** * @brief Handles Master reception RXNE interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_MASTER_RXNE_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* Read Byte */ *(pDevInitStruct->pCPAL_TransferRx->pbBuffer) = __CPAL_I2C_HAL_RECEIVE(pDevInitStruct->CPAL_Dev); /* Call RX UserCallback */ CPAL_I2C_RX_UserCallback(pDevInitStruct); /* Decrement remaining number of data */ pDevInitStruct->pCPAL_TransferRx->wNumData--; /* If data remaining for reception */ if (pDevInitStruct->pCPAL_TransferRx->wNumData != 0) { /* Point to next data */ pDevInitStruct->pCPAL_TransferRx->pbBuffer++; } return CPAL_PASS; } #endif /* CPAL_I2C_IT_PROGMODEL */ #endif /* CPAL_I2C_MASTER_MODE */ #ifdef CPAL_I2C_SLAVE_MODE /** * @brief Handles Slave ADDR interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_SLAVE_ADDR_Handle(CPAL_InitTypeDef* pDevInitStruct) { #ifdef CPAL_I2C_LISTEN_MODE /* If slave receive request for write */ if (__CPAL_I2C_HAL_GET_DIR(pDevInitStruct->CPAL_Dev) == 0) { pDevInitStruct->CPAL_State = CPAL_STATE_BUSY_RX; /* Call Slave receive UserCallback */ CPAL_I2C_SLAVE_READ_UserCallback(pDevInitStruct); } /* If slave receive request for read */ else { pDevInitStruct->CPAL_State = CPAL_STATE_BUSY_TX; /* Call Slave Transmit UserCallback */ CPAL_I2C_SLAVE_WRITE_UserCallback(pDevInitStruct); } #else uint32_t slaveaddr = 0; /* If 7 Bit Addressing Mode */ if (pDevInitStruct->pCPAL_I2C_Struct->I2C_AcknowledgedAddress == I2C_AcknowledgedAddress_7bit) { /* Get slave matched address */ slaveaddr = __CPAL_I2C_HAL_GET_ADDCODE(pDevInitStruct->CPAL_Dev); /* if matched address is not equal to OA1 */ if (slaveaddr !=__CPAL_I2C_HAL_GET_OA1(pDevInitStruct->CPAL_Dev)) { /* If General Call addressing mode selected */ if ( slaveaddr == 0x00000000) { CPAL_LOG("\n\rLOG : I2C Device GENCALL Mode"); /* Call GENCALL UserCallback */ CPAL_I2C_GENCALL_UserCallback(pDevInitStruct); } /* If DUAL addressing mode selected */ else { CPAL_LOG("\n\rLOG : I2C Device DUAL ADDR Mode Selected"); /* Call DUALF UserCallback */ CPAL_I2C_DUALF_UserCallback(pDevInitStruct); } } } #endif /* CPAL_I2C_LISTEN_MODE */ /* Clear ADDR flag */ __CPAL_I2C_HAL_CLEAR_ADDR(pDevInitStruct->CPAL_Dev); return CPAL_PASS; } /** * @brief Handles Slave STOP interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_SLAVE_STOP_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* Clear STOP flag */ __CPAL_I2C_HAL_CLEAR_STOP(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\r\n\rLOG : I2C Device Slave IT"); CPAL_LOG("\n\rLOG : I2C Device Stop Detected"); /* Disable slave interrupt */ __CPAL_I2C_HAL_DISABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); /* Wait until BUSY flag is reset */ __CPAL_I2C_TIMEOUT(!(__CPAL_I2C_HAL_GET_BUSY(pDevInitStruct->CPAL_Dev)), CPAL_I2C_TIMEOUT_BUSY); /* If NACK Slave Own Address option bit selected */ if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0) { /* Disable Acknowledgement of own Address */ __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev); } /* If slave transmitter */ if (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable TX interrupt */ __CPAL_I2C_HAL_DISABLE_TXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call TX Transfer complete Callback */ CPAL_I2C_TXTC_UserCallback(pDevInitStruct); } /* If slave receiver */ else { #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable RX interrupt */ __CPAL_I2C_HAL_DISABLE_RXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call RX Transfer complete Callback */ CPAL_I2C_RXTC_UserCallback(pDevInitStruct); } return CPAL_PASS; } /** * @brief Handles Slave NACK interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_SLAVE_NACK_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* Clear NACK flag */ __CPAL_I2C_HAL_CLEAR_NACK(pDevInitStruct->CPAL_Dev); /* No Stop Condition Generation option bit selected and slave transmitter */ if (((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP) != 0) && (pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX)) { /* Disable slave interrupt */ __CPAL_I2C_HAL_DISABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); #ifdef CPAL_I2C_IT_PROGMODEL /* If Interrupt Programming Model */ if (pDevInitStruct->CPAL_ProgModel == CPAL_PROGMODEL_INTERRUPT) { /* Disable TX interrupt */ __CPAL_I2C_HAL_DISABLE_TXIE_IT(pDevInitStruct->CPAL_Dev); } #endif /* CPAL_I2C_IT_PROGMODEL */ /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call TX Transfer complete Callback */ CPAL_I2C_TXTC_UserCallback(pDevInitStruct); } return CPAL_PASS; } #ifdef CPAL_I2C_IT_PROGMODEL /** * @brief Handles Slave transmission TXIS interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_SLAVE_TXIS_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* If data remaining for transmission */ if (pDevInitStruct->pCPAL_TransferTx->wNumData != 0) { /* Call TX UserCallback */ CPAL_I2C_TX_UserCallback(pDevInitStruct); /* Write Byte */ __CPAL_I2C_HAL_SEND((pDevInitStruct->CPAL_Dev), (*(pDevInitStruct->pCPAL_TransferTx->pbBuffer))); /* Decrement remaining number of data */ pDevInitStruct->pCPAL_TransferTx->wNumData--; if (pDevInitStruct->pCPAL_TransferTx->wNumData != 0) { /* Point to next data */ pDevInitStruct->pCPAL_TransferTx->pbBuffer++; } } return CPAL_PASS; } /** * @brief Handles Slave reception RXNE interrupt event. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_SLAVE_RXNE_Handle(CPAL_InitTypeDef* pDevInitStruct) { /* If data remaining for reception */ if (pDevInitStruct->pCPAL_TransferRx->wNumData != 0) { /* Read Byte */ *(pDevInitStruct->pCPAL_TransferRx->pbBuffer) = __CPAL_I2C_HAL_RECEIVE(pDevInitStruct->CPAL_Dev); /* Call RX UserCallback */ CPAL_I2C_RX_UserCallback(pDevInitStruct); /* Decrement remaining number of data */ pDevInitStruct->pCPAL_TransferRx->wNumData--; /* If data remaining for reception */ if (pDevInitStruct->pCPAL_TransferRx->wNumData != 0) { /* Point to next data */ pDevInitStruct->pCPAL_TransferRx->pbBuffer++; } /* If all data received and No Stop Condition Generation option bit selected */ else if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NOSTOP) != 0) { /* Disable slave interrupt */ __CPAL_I2C_HAL_DISABLE_SLAVE_IT(pDevInitStruct->CPAL_Dev); /* Disable RX interrupt */ __CPAL_I2C_HAL_DISABLE_RXIE_IT(pDevInitStruct->CPAL_Dev); /* Update CPAL_State to CPAL_STATE_READY */ pDevInitStruct->CPAL_State = CPAL_STATE_READY; /* Call RX Transfer complete Callback */ CPAL_I2C_RXTC_UserCallback(pDevInitStruct); } } return CPAL_PASS; } #endif /* CPAL_I2C_IT_PROGMODEL */ #endif /* CPAL_I2C_SLAVE_MODE */ /*================== Local DMA and IT Manager ==================*/ #ifdef CPAL_I2C_DMA_PROGMODEL /** * @brief This function Configures and enables I2C DMA before starting transfer phase. * @param pDevInitStruct: Pointer to the peripheral configuration structure. * @param Direction : Transfer direction. * @retval CPAL_PASS or CPAL_FAIL. */ static uint32_t I2C_Enable_DMA (CPAL_InitTypeDef* pDevInitStruct, CPAL_DirectionTypeDef Direction) { /* If data transmission will be performed */ if ((pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_TX) || (Direction == CPAL_DIRECTION_TX)) { /* Configure TX DMA channels */ CPAL_I2C_HAL_DMATXConfig(pDevInitStruct->CPAL_Dev, pDevInitStruct->pCPAL_TransferTx, pDevInitStruct->wCPAL_Options); /* Enable TX DMA channels */ __CPAL_I2C_HAL_ENABLE_DMATX(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device DMA TX Configured and Enabled"); } /* If data reception will be performed */ else if ((pDevInitStruct->CPAL_State == CPAL_STATE_BUSY_RX) || (Direction == CPAL_DIRECTION_RX)) { /* Configure RX DMA channels */ CPAL_I2C_HAL_DMARXConfig(pDevInitStruct->CPAL_Dev, pDevInitStruct->pCPAL_TransferRx, pDevInitStruct->wCPAL_Options); /* Enable RX DMA channels */ __CPAL_I2C_HAL_ENABLE_DMARX(pDevInitStruct->CPAL_Dev); CPAL_LOG("\n\rLOG : I2C Device DMA RX Configured and Enabled"); } return CPAL_PASS; } #endif /* CPAL_I2C_DMA_PROGMODEL */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/