You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ut...@apache.org on 2018/04/18 21:56:33 UTC
[mynewt-core] 10/13: Add i2c driver for F3/F7
This is an automated email from the ASF dual-hosted git repository.
utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 20e796df31323b54b9f125690286114a773d0b8b
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Thu Mar 22 14:55:17 2018 -0300
Add i2c driver for F3/F7
This breaks the stm32cube based driver into two different drivers, one
which is compiled in if the BSP is based on F1/L1/F4 and another for
F3/F7.
FIXME: the driver for F3 is using a delay when no stop was sent by
previous message, might be due to not enough time between messages, need
to check timing register...
---
..._driver_mod_i2c.c => stm32_driver_mod_i2c_v1.c} | 10 +-
.../stm/stm32_common/src/stm32_driver_mod_i2c_v2.c | 647 +++++++++++++++++++++
hw/mcu/stm/stm32f1xx/src/hal_i2c.c | 34 +-
3 files changed, 678 insertions(+), 13 deletions(-)
diff --git a/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c.c b/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v1.c
similarity index 95%
rename from hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c.c
rename to hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v1.c
index 367e09f..c6e02a8 100644
--- a/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c.c
+++ b/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v1.c
@@ -29,6 +29,8 @@
#include <mcu/stm32_hal.h>
#include <syscfg/syscfg.h>
+#if !defined(STM32F3) && !defined(STM32F7)
+
#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */
#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */
@@ -125,8 +127,6 @@ static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeD
return HAL_OK;
}
-
-
/**
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for I2C module
@@ -345,8 +345,6 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c,
return HAL_OK;
}
-
-
/**
* @brief Transmits in master mode an amount of data in blocking mode.
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
@@ -356,6 +354,7 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c,
* @param pData Pointer to data buffer
* @param Size Amount of data to be sent
* @param Timeout Timeout duration
+ * @param LastOp If set sends STOP, otherwise no STOP
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2C_Master_Transmit_Custom(I2C_HandleTypeDef *hi2c,
@@ -606,6 +605,7 @@ static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t
* @param pData Pointer to data buffer
* @param Size Amount of data to be sent
* @param Timeout Timeout duration
+ * @param LastOp If set sends STOP, otherwise no STOP
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2C_Master_Receive_Custom(I2C_HandleTypeDef *hi2c,
@@ -852,4 +852,6 @@ HAL_StatusTypeDef HAL_I2C_Master_Receive_Custom(I2C_HandleTypeDef *hi2c,
}
}
+#endif /* !defined(STM32F3) && !defined(STM32F7) */
+
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v2.c b/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v2.c
new file mode 100644
index 0000000..b24ee86
--- /dev/null
+++ b/hw/mcu/stm/stm32_common/src/stm32_driver_mod_i2c_v2.c
@@ -0,0 +1,647 @@
+/**
+ * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+#include <os/os_time.h>
+#include <mcu/stm32_hal.h>
+#include <syscfg/syscfg.h>
+
+#if defined(STM32F3) || defined(STM32F7)
+
+#define I2C_TIMEOUT_BUSY (25U) /*!< 25 ms */
+
+#define MAX_NBYTE_SIZE 255U
+
+static const uint8_t HAL_I2C_MODE_MASTER_SEL = 0x11;
+
+/**
+ * @brief This function handles I2C Communication Timeout.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for I2C module
+ * @param Flag specifies the I2C flag to check.
+ * @param Status The new Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+/*
+ * FIXME: this function is similar enough that it could be shared between
+ * both i2c drivers.
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c,
+ uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hi2c I2C handle.
+ * @param DevAddress Specifies the slave address to be programmed.
+ * @param Size Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param Mode New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE Enable Reload mode .
+ * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
+ * @param Request New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
+{
+ uint32_t tmpreg = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_TRANSFER_MODE(Mode));
+ assert_param(IS_TRANSFER_REQUEST(Request));
+
+ /* Get the CR2 register value */
+ tmpreg = hi2c->Instance->CR2;
+
+ /* clear tmpreg specific bits */
+ tmpreg &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
+
+ /* update tmpreg */
+ tmpreg |= (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << 16) & I2C_CR2_NBYTES) | \
+ (uint32_t)Mode | (uint32_t)Request);
+
+ /* update CR2 register */
+ hi2c->Instance->CR2 = tmpreg;
+}
+
+/**
+ * @brief I2C Tx data register flush process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c)
+{
+ /* If a pending TXIS flag is set */
+ /* Write a dummy data in TXDR to clear it */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ hi2c->Instance->TXDR = 0x00U;
+ }
+
+ /* Flush TX register if not empty */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+}
+
+/**
+ * @brief This function handles Acknowledge failed detection during an I2C Communication.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ /* Wait until STOP Flag is reset */
+ /* AutoEnd should be initiate after AF */
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Clear NACKF Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_AF;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of STOP flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @param LastOp If set sends STOP, otherwise no STOP
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_Custom(I2C_HandleTypeDef *hi2c,
+ uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout,
+ uint8_t LastOp)
+{
+ uint32_t tickstart = 0U;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (hi2c->Mode != HAL_I2C_MODE_MASTER_SEL)
+ {
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ else
+ {
+ /* FIXME: with not stop must wait here! why? timing config? */
+ os_time_delay(1);
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+ }
+ else if (!LastOp)
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else if (!LastOp)
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ if (LastOp)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+ else
+ {
+ /* No autoend/reload was requested, make sure transmission of last byte
+ * has finished... */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, SET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ if (LastOp)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_MASTER_SEL;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ /* Check if a NACK is detected */
+ if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check if a STOPF is detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_TIMEOUT;
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Receives in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @param LastOp If set sends STOP, otherwise no STOP
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_Custom(I2C_HandleTypeDef *hi2c,
+ uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout,
+ uint8_t LastOp)
+{
+ uint32_t tickstart = 0U;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (hi2c->Mode != HAL_I2C_MODE_MASTER_SEL)
+ {
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ else
+ {
+ /* FIXME: with not stop must wait here! why? timing config? */
+ os_time_delay(1);
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
+ }
+ else if (!LastOp)
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Read data from RXDR */
+ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else if (!LastOp)
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ if (LastOp)
+ {
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+ else
+ {
+ /* No autoend/reload was requested, make sure transmission of last byte
+ * has finished... */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, SET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ if (LastOp)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_MASTER_SEL;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+#endif /* defined(STM32F3) || defined(STM32F7) */
diff --git a/hw/mcu/stm/stm32f1xx/src/hal_i2c.c b/hw/mcu/stm/stm32f1xx/src/hal_i2c.c
index 59dfc14..0d8d8f8 100644
--- a/hw/mcu/stm/stm32f1xx/src/hal_i2c.c
+++ b/hw/mcu/stm/stm32f1xx/src/hal_i2c.c
@@ -76,6 +76,7 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
struct stm32f1_hal_i2c_cfg *cfg = (struct stm32f1_hal_i2c_cfg *)usercfg;
struct stm32f1_hal_i2c *dev;
I2C_InitTypeDef *init;
+ GPIO_InitTypeDef gpio;
int rc;
if (i2c_num >= HAL_I2C_MAX_DEVS || !(dev = hal_i2c_devs[i2c_num])) {
@@ -93,20 +94,35 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
init->OwnAddress1 = I2C_ADDRESS;
init->OwnAddress2 = 0xFE;
+ init->DutyCycle = I2C_DUTYCYCLE_2;
+ init->DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ init->GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ init->NoStretchMode = I2C_NOSTRETCH_DISABLE;
+
/*
* Configure GPIO pins for I2C.
* Enable clock routing for I2C.
*/
- rc = hal_gpio_init_af(cfg->hic_pin_sda, cfg->hic_pin_af, HAL_GPIO_PULL_UP,
- 1);
- if (rc) {
- goto err;
- }
- rc = hal_gpio_init_af(cfg->hic_pin_scl, cfg->hic_pin_af, HAL_GPIO_PULL_UP,
- 1);
- if (rc) {
- goto err;
+ gpio.Speed = GPIO_SPEED_FREQ_HIGH;
+ gpio.Pull = GPIO_NOPULL;
+ gpio.Mode = GPIO_MODE_AF_OD;
+ hal_gpio_init_stm(cfg->hic_pin_scl, &gpio);
+ hal_gpio_init_stm(cfg->hic_pin_sda, &gpio);
+
+#if 0
+ hal_gpio_write(cfg->hic_pin_scl, 0);
+ //for (int i = 0; i < 1000; i++) asm("nop");
+ hal_gpio_write(cfg->hic_pin_scl, 1);
+
+ hal_gpio_write(cfg->hic_pin_sda, 0);
+ //for (int i = 0; i < 1000; i++) asm("nop");
+ hal_gpio_write(cfg->hic_pin_sda, 1);
+#endif
+
+ if (cfg->hic_pin_remap_fn) {
+ cfg->hic_pin_remap_fn();
}
+
*cfg->hic_rcc_reg |= cfg->hic_rcc_dev;
rc = HAL_I2C_Init(&dev->hid_handle);
if (rc) {
--
To stop receiving notification emails like this one, please contact
utzig@apache.org.