From 8bfbb723f37c4416e15a935815fe367b09c7204b Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 19:25:31 +0200 Subject: [PATCH 1/7] Integrated STM32F4 I2C HAL functions. Changed old "I2C_SPEED" to "I2C_CLK_RATE" in order not to conflict with HAL. Use TOUCH_INT again to gate touch sampling. --- radio/src/targets/horus/CMakeLists.txt | 2 +- radio/src/targets/horus/hal.h | 2 +- radio/src/targets/horus/i2c_driver.cpp | 1020 ++++++++++++++++++++++ radio/src/targets/horus/i2c_driver.h | 397 +++++++++ radio/src/targets/horus/tp_gt911.cpp | 308 ++----- radio/src/targets/horus/tp_gt911.h | 31 +- radio/src/targets/taranis/hal.h | 2 +- radio/src/targets/taranis/i2c_driver.cpp | 2 +- 8 files changed, 1498 insertions(+), 266 deletions(-) create mode 100644 radio/src/targets/horus/i2c_driver.cpp create mode 100644 radio/src/targets/horus/i2c_driver.h diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index c01057e9c..be80a40ce 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -238,7 +238,7 @@ set(TARGET_SRC ) if(HARDWARE_TOUCH) - set(TOUCH_DRIVER tp_gt911.cpp) + set(TOUCH_DRIVER tp_gt911.cpp i2c_driver.cpp) add_definitions(-DHARDWARE_TOUCH) endif() diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 8d7be0da5..fd1605892 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -728,7 +728,7 @@ #define I2C_SCL_GPIO_PinSource GPIO_PinSource8 #define I2C_SDA_GPIO_PinSource GPIO_PinSource9 #endif -#define I2C_SPEED 400000 +#define I2C_CLK_RATE 400000 // Haptic #define HAPTIC_PWM diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp new file mode 100644 index 000000000..d47af3221 --- /dev/null +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -0,0 +1,1020 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * OpenTX - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * The content of this file partially stems from STM32F4 HAL by STMicroelectronics. + */ + +#include "opentx.h" +#include "i2c_driver.h" + +uint32_t GetTickCountMS(void) +{ + static uint32_t tickcount = 0; + tickcount++; + return (tickcount >> 10); + //return (ticksNow()/CYCLES_IN_MS); +} + +/* I2C MSP Initialization + * This function configures the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (I2C_GPIO == GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOH) + __HAL_RCC_GPIOH_CLK_ENABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); + + GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF); + GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF); + + GPIO_InitStruct.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(I2C_GPIO, &GPIO_InitStruct); + + /* Peripheral clock enable */ + if (I2C == I2C1) + __HAL_RCC_I2C1_CLK_ENABLE(); + else + if (I2C == I2C2) + __HAL_RCC_I2C2_CLK_ENABLE(); + else + if (I2C == I2C3) + __HAL_RCC_I2C3_CLK_ENABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); +} + +/* Initializes the I2C according to the specified parameters + * in the HAL_I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + uint32_t freqrange; + uint32_t pclk1; + + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); + assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if (hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_I2C_MspInit(hi2c); + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /*Reset I2C*/ + hi2c->Instance->CR1 |= I2C_CR1_SWRST; + hi2c->Instance->CR1 &= ~I2C_CR1_SWRST; + + /* Get PCLK1 frequency */ + RCC_ClocksTypeDef rccClocks; + RCC_GetClocksFreq(&rccClocks); + pclk1 = rccClocks.PCLK1_Frequency; + + /* Check the minimum allowed PCLK1 frequency */ + if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U) + { + return HAL_ERROR; + } + + /* Calculate frequency range */ + freqrange = I2C_FREQRANGE(pclk1); + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Frequency range */ + MODIFY_REG(hi2c->Instance->CR2, I2C_CR2_FREQ, freqrange); + + /*---------------------------- I2Cx TRISE Configuration --------------------*/ + /* Configure I2Cx: Rise Time */ + MODIFY_REG(hi2c->Instance->TRISE, I2C_TRISE_TRISE, I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed)); + + /*---------------------------- I2Cx CCR Configuration ----------------------*/ + /* Configure I2Cx: Speed */ + MODIFY_REG(hi2c->Instance->CCR, (I2C_CCR_FS | I2C_CCR_DUTY | I2C_CCR_CCR), I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle)); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + MODIFY_REG(hi2c->Instance->CR1, (I2C_CR1_ENGC | I2C_CR1_NOSTRETCH), (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode)); + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Configure I2Cx: Own Address1 and addressing mode */ + MODIFY_REG(hi2c->Instance->OAR1, (I2C_OAR1_ADDMODE | I2C_OAR1_ADD8_9 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD0), (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1)); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Configure I2Cx: Dual mode and Own Address2 */ + MODIFY_REG(hi2c->Instance->OAR2, (I2C_OAR2_ENDUAL | I2C_OAR2_ADD2), (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2)); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/* Configures I2C Analog noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter new state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF); + + /* Disable the analog filter */ + hi2c->Instance->FLTR |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/* Configures I2C Digital noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->FLTR; + + /* Reset I2Cx DNF bit [3:0] */ + tmpreg &= ~(I2C_FLTR_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter; + + /* Store the new register value */ + hi2c->Instance->FLTR = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +FlagStatus __HAL_I2C_GET_FLAG(I2C_HandleTypeDef *hi2c, uint32_t Flag) +{ + return I2C_GetFlagStatus(hi2c->Instance, Flag); +} + +/* 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 + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until flag is set */ + while (I2C_GetFlagStatus(hi2c->Instance, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for Master addressing phase. + * @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 Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/* 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. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) +{ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for specific usage of TXE 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_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original: HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for specific usage of BTF 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_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* 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 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = GetTickCountMS(); // Original: HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + 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->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while (hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + } + + /* Wait until BTF flag is set */ + if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/* Master sends target device address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/* 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 STOPF is detected */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + return HAL_OK; +} + +/* 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 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = GetTickCountMS(); // Original HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + 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->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while (hi2c->XferSize > 0U) + { + if (hi2c->XferSize <= 3U) + { + /* One byte */ + if (hi2c->XferSize == 1U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if (hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h new file mode 100644 index 000000000..c31b44f0c --- /dev/null +++ b/radio/src/targets/horus/i2c_driver.h @@ -0,0 +1,397 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * OpenTX - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * The content of this file partially stems from STM32F4 HAL by STMicroelectronics. + */ + + +#pragma once + +#include + +#define __IO volatile /*!< Defines 'read / write' permissions */ + +#define HAL_MAX_DELAY 0xFFFFFFFFU + +/* AHB1 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + */ +#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_GPIOB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_GPIOH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ + UNUSED(tmpreg); \ + } while(0U) + +#define __HAL_RCC_GPIOA_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOAEN)) +#define __HAL_RCC_GPIOB_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOBEN)) +#define __HAL_RCC_GPIOC_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOCEN)) +#define __HAL_RCC_GPIOH_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOHEN)) + +/* APB1 Peripheral Clock Enable Disable + * @brief Enable or disable the Low Speed APB (APB1) peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + */ +#define __HAL_RCC_I2C1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_I2C2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_I2C3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\ + UNUSED(tmpreg); \ + } while(0U) +#define __HAL_RCC_I2C1_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C1EN)) +#define __HAL_RCC_I2C2_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C2EN)) +#define __HAL_RCC_I2C3_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C3EN)) + +#define __HAL_LOCK(__HANDLE__) \ + do{ \ + if((__HANDLE__)->Lock == HAL_LOCKED) \ + { \ + return HAL_BUSY; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = HAL_LOCKED; \ + } \ + }while (0U) + +#define __HAL_UNLOCK(__HANDLE__) \ + do{ \ + (__HANDLE__)->Lock = HAL_UNLOCKED; \ + }while (0U) + + +/* Enable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE) + +/* Disable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE) + +// I2C Private Constants +#define I2C_FLAG_MASK 0x0000FFFFU +#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */ +#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */ + +#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ +#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ +#define I2C_TIMEOUT_STOP_FLAG 5U /*!< Timeout 5 ms */ +#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ + +// I2C Private Macros +#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST)) +#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__) - 1U)/((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR) +#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U) +#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U)) +#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U)? 4U:I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U)) +#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9)) +#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS)) +#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0))) +#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) + +#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) +#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0))) +#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1)))) + +#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8))) +#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) + +// I2C duty cycle in fast mode +#define I2C_DUTYCYCLE_2 0x00000000U +#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY + +// I2C addressing mode +#define I2C_ADDRESSINGMODE_7BIT 0x00004000U +#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) + +// I2C dual addressing mode +#define I2C_DUALADDRESS_DISABLE 0x00000000U +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL + +// I2C general call addressing mode +#define I2C_GENERALCALL_DISABLE 0x00000000U +#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC + +// I2C nostretch mode +#define I2C_NOSTRETCH_DISABLE 0x00000000U +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH + +// I2C Error Code definition +#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */ +#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */ +#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */ +#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */ +#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */ +#define HAL_I2C_ERROR_SIZE 0x00000040U /*!< Size Management error */ +#define HAL_I2C_ERROR_DMA_PARAM 0x00000080U /*!< DMA Parameter Error */ +#define HAL_I2C_WRONG_START 0x00000200U /*!< Wrong start Error */ + +// I2C XferOptions definition +#define I2C_FIRST_FRAME 0x00000001U +#define I2C_FIRST_AND_NEXT_FRAME 0x00000002U +#define I2C_NEXT_FRAME 0x00000004U +#define I2C_FIRST_AND_LAST_FRAME 0x00000008U +#define I2C_LAST_FRAME_NO_STOP 0x00000010U +#define I2C_LAST_FRAME 0x00000020U + +// I2C states +#define I2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | (uint32_t)HAL_I2C_STATE_BUSY_RX) & (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits */ +#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ +#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ + +// I2C Analog Filter +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF + +/* Clears the I2C ADDR pending flag. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + tmpreg = (__HANDLE__)->Instance->SR2; \ + UNUSED(tmpreg); \ + } while(0) + +/* Checks whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag + * @arg I2C_FLAG_BERR: Bus error flag + * @arg I2C_FLAG_TXE: Data register empty flag + * @arg I2C_FLAG_RXNE: Data register not empty flag + * @arg I2C_FLAG_STOPF: Stop detection flag + * @arg I2C_FLAG_ADD10: 10-bit header sent flag + * @arg I2C_FLAG_BTF: Byte transfer finished flag + * @arg I2C_FLAG_ADDR: Address sent flag + * Address matched flag + * @arg I2C_FLAG_SB: Start bit flag + * @arg I2C_FLAG_DUALF: Dual flag + * @arg I2C_FLAG_GENCALL: General call header flag + * @arg I2C_FLAG_TRA: Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY: Bus busy flag + * @arg I2C_FLAG_MSL: Master/Slave flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ + +/* Clears the I2C pending flags which are cleared by writing 0 in a specific bit. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BERR: Bus error flag + * @retval None + */ +#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = (uint16_t)(~((__FLAG__) & I2C_FLAG_MASK))) + +// HAL Status structures definition +typedef enum +{ + HAL_OK = 0x00U, + HAL_ERROR = 0x01U, + HAL_BUSY = 0x02U, + HAL_TIMEOUT = 0x03U +} HAL_StatusTypeDef; + +// HAL lock structures definition +typedef enum +{ + HAL_UNLOCKED = 0x00U, + HAL_LOCKED = 0x01U +} HAL_LockTypeDef; + +/* HAL State structure definition + * HAL I2C State value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : Abort (Abort user request on going) + * 10 : Timeout + * 11 : Error + * b5 Peripheral initialization status + * 0 : Reset (Peripheral not initialized) + * 1 : Init done (Peripheral initialized and ready to use. HAL I2C Init function called) + * b4 (not used) + * x : Should be set to 0 + * b3 + * 0 : Ready or Busy (No Listen mode ongoing) + * 1 : Listen (Peripheral in Address Listen Mode) + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (Peripheral busy with some configuration or internal operations) + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + */ +typedef enum +{ + HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ + +} HAL_I2C_StateTypeDef; + +/* HAL Mode structure definition + * HAL I2C Mode value coding follow below described bitmap : + * b7 (not used) + * x : Should be set to 0 + * b6 + * 0 : None + * 1 : Memory (HAL I2C communication is in Memory Mode) + * b5 + * 0 : None + * 1 : Slave (HAL I2C communication is in Slave Mode) + * b4 + * 0 : None + * 1 : Master (HAL I2C communication is in Master Mode) + * b3-b2-b1-b0 (not used) + * xxxx : Should be set to 0000 + */ +typedef enum +{ + HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ + HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ + HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ + HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ + +} HAL_I2C_ModeTypeDef; + +// I2C configuration structure definition +typedef struct +{ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref I2C_addressing_mode */ + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref I2C_dual_addressing_mode */ + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref I2C_general_call_addressing_mode */ + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref I2C_nostretch_mode */ +} HAL_I2C_InitTypeDef; // WARNING: renamed from I2C_InitTypeDef due to conflict + +// I2C handle structure definition +typedef struct +{ + I2C_TypeDef *Instance; /*!< I2C registers base address */ + HAL_I2C_InitTypeDef Init; /*!< I2C communication parameters (MOD!) */ + uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ + uint16_t XferSize; /*!< I2C transfer size */ + __IO uint16_t XferCount; /*!< I2C transfer counter */ + __IO uint32_t XferOptions; /*!< I2C transfer options */ + __IO uint32_t PreviousState; /*!< I2C communication Previous state and mode + context for internal usage */ + //DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ + //DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ + HAL_LockTypeDef Lock; /*!< I2C locking object */ + __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ + __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ + __IO uint32_t ErrorCode; /*!< I2C Error code */ + __IO uint32_t Devaddress; /*!< I2C Target device address */ + __IO uint32_t Memaddress; /*!< I2C Target memory address */ + __IO uint32_t MemaddSize; /*!< I2C Target memory address size */ + __IO uint32_t EventCount; /*!< I2C Event counter */ +} I2C_HandleTypeDef; + +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 8dd01b49b..82200288b 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "i2c_driver.h" #include "tp_gt911.h" #include "touch.h" @@ -409,6 +410,8 @@ struct TouchData touchData; uint16_t touchGT911fwver = 0; uint32_t touchGT911hiccups = 0; +I2C_HandleTypeDef hi2c1; + static void TOUCH_AF_ExtiStop(void) { SYSCFG_EXTILineConfig(TOUCH_INT_EXTI_PortSource, TOUCH_INT_EXTI_PinSource1); @@ -484,267 +487,78 @@ void TOUCH_AF_INT_Change(void) GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure); } -void I2C_Init() +void I2C_Init_Radio() { TRACE("I2C Init"); - I2C_DeInit(I2C); - - GPIO_InitTypeDef GPIO_InitStructure; - I2C_InitTypeDef I2C_InitStructure; - I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED; - I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; - I2C_InitStructure.I2C_OwnAddress1 = 0x00; - I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; - I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; - I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; - I2C_Init(I2C, &I2C_InitStructure); - I2C_Cmd(I2C, ENABLE); - - GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF); - GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF); - - GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(I2C_GPIO, &GPIO_InitStructure); + hi2c1.Instance = I2C; + hi2c1.Init.ClockSpeed = I2C_CLK_RATE; + hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_16_9; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + TRACE("I2C ERROR: HAL_I2C_Init() failed"); + } + // Configure Analogue filter + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + TRACE("I2C ERROR: HAL_I2CEx_ConfigAnalogFilter() failed"); + } + // Configure Digital filter + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) + { + TRACE("I2C ERROR: HAL_I2CEx_ConfigDigitalFilter() failed"); + } } -bool I2C_WaitFlag(uint32_t flag) +bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) { - uint32_t timeout = I2C_TIMEOUT_MAX; - while (!I2C_GetFlagStatus(I2C, flag)) { - if ((timeout--) == 0) return false; - } - return true; -} + uint8_t uAddrAndBuf[258]; + uAddrAndBuf[0] = (uint8_t)((reg & 0xFF00) >> 8); + uAddrAndBuf[1] = (uint8_t)(reg & 0x00FF); -bool I2C_WaitEvent(uint32_t event) -{ - uint32_t timeout = I2C_TIMEOUT_MAX; - while (!I2C_CheckEvent(I2C, event)) { - if ((timeout--) == 0) return false; - } - return true; -} - -bool I2C_WaitEventCleared(uint32_t event) -{ - uint32_t timeout = I2C_TIMEOUT_MAX; - while (I2C_CheckEvent(I2C, event)) { - if ((timeout--) == 0) return false; - } - return true; -} - -uint8_t I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) -{ - if (!I2C_WaitEventCleared(I2C_FLAG_BUSY)) - { - TRACE("I2C WRITE ERROR: busy timeout"); - return false; - } - - I2C_GenerateSTART(I2C, ENABLE); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT)) - { - TRACE("I2C WRITE ERROR: could not issue start"); - return false; - } - - I2C_Send7bitAddress(I2C, GT_CMD_WR, I2C_Direction_Transmitter); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) - { - TRACE("I2C WRITE ERROR: could not send device address"); - return false; - } - - I2C_SendData(I2C, (uint8_t)((reg & 0xFF00) >> 8)); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)) - { - TRACE("I2C WRITE ERROR: could not send register high address"); - return false; - } - - I2C_SendData(I2C, (uint8_t)(reg & 0x00FF)); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)) - { - TRACE("I2C WRITE ERROR: could not send register low address"); - return false; - } - - /* While there is data to be written */ - while (len--) { - I2C_SendData(I2C, *buf); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)) + if (len > 0) { - TRACE("I2C WRITE ERROR: could not send data with %u bytes remaining", len+1 ); - return false; + for (int i = 0;i < len;i++) + { + uAddrAndBuf[i + 2] = buf[i]; + } } - buf++; - } - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) - { - TRACE("I2C WRITE ERROR: waiting for BTF failed."); - return false; - } - - I2C_GenerateSTOP(I2C, ENABLE); - return true; + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 10000) != HAL_OK) + { + TRACE("I2C ERROR: WriteRegister failed"); + asm("bkpt 255"); + return false; + } + return true; } -bool I2C_GT911_ReadRegister(u16 reg, uint8_t * buf, uint8_t len) +bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) { - if (!I2C_WaitEventCleared(I2C_FLAG_BUSY)) - { - TRACE("I2C READ ERROR: busy timeout"); - return false; - } + uint8_t uRegAddr[2]; + uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8); + uRegAddr[1] = (uint8_t)(reg & 0x00FF); - I2C_GenerateSTART(I2C, ENABLE); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT)) - { - TRACE("I2C READ ERROR: could not issue first step start"); - return false; - } - - I2C_Send7bitAddress(I2C, GT_CMD_WR, I2C_Direction_Transmitter); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) - { - TRACE("I2C READ ERROR: could not send first step device address"); - return false; - } - - I2C_SendData(I2C, (uint8_t)((reg & 0xFF00) >> 8)); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)) - { - TRACE("I2C READ ERROR: could not send register high address"); - return false; - } - - I2C_SendData(I2C, (uint8_t)(reg & 0x00FF)); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) - { - TRACE("I2C READ ERROR: could not send register low address"); - return false; - } - - // According to GP911 data sheet, repeated start is not listed, so we do full stop. - // See chapter 6.1.c, page 12, diagram for reading data - I2C_GenerateSTOP(I2C, ENABLE); - if (!I2C_WaitEventCleared(I2C_FLAG_BUSY)) - { - TRACE("I2C READ ERROR: timeout waiting for first stop"); - return false; - } - - // Enable Acknowledgement, clear POS flag - I2C_AcknowledgeConfig(I2C, ENABLE); - I2C_NACKPositionConfig(I2C, I2C_NACKPosition_Current); - - I2C_GenerateSTART(I2C, ENABLE); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT)) - { - TRACE("I2C READ ERROR: could not issue second step start"); - return false; - } - - I2C_Send7bitAddress(I2C, GT_CMD_RD, I2C_Direction_Receiver); - if (!I2C_WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) - { - TRACE("I2C READ ERROR: could not send second step device address"); - return false; - } - - if (len == 1) { - // Clear Ack bit - I2C_AcknowledgeConfig(I2C, DISABLE); - - // EV6_1 -- must be atomic -- Clear ADDR, generate STOP - __disable_irq(); - (void) I2C->SR2; - I2C_GenerateSTOP(I2C,ENABLE); - __enable_irq(); - - // Receive data EV7 - if(!I2C_WaitFlag(I2C_FLAG_RXNE)) { - TRACE("I2C READ ERROR: timeout waiting for RxNE"); - I2C_Init(); - return false; - } - - *buf++ = I2C_ReceiveData(I2C); - } - else if (len == 2) { - - // Set POS flag - I2C_NACKPositionConfig(I2C, I2C_NACKPosition_Next); - - // EV6_1 -- must be atomic and in this order - __disable_irq(); - (void) I2C->SR2; // Clear ADDR flag - I2C_AcknowledgeConfig(I2C, DISABLE); // Clear Ack bit - __enable_irq(); - - // EV7_3 -- Wait for BTF, program stop, read data twice - if (!I2C_WaitFlag(I2C_FLAG_BTF)) { - TRACE("I2C READ ERROR: timeout waiting for BTF"); - I2C_Init(); - return false; - } - - __disable_irq(); - I2C_GenerateSTOP(I2C,ENABLE); - *buf++ = I2C->DR; - __enable_irq(); - - *buf++ = I2C->DR; - } - else { - - (void) I2C->SR2; // Clear ADDR flag - while (len-- != 3) { - // EV7 -- cannot guarantee 1 transfer completion time, wait for BTF - // instead of RXNE - if (!I2C_WaitFlag(I2C_FLAG_BTF)) { - TRACE("I2C READ ERROR: timeout waiting for BTF"); - I2C_Init(); + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10000) != HAL_OK) + { + TRACE("I2C ERROR: ReadRedister write reg address failed"); + asm("bkpt 255"); return false; - } - - *buf++ = I2C_ReceiveData(I2C); } - // Data N-2 in DR, data N-1 in shift register, - // SCL stretched low until data N-2 is read - if (!I2C_WaitFlag(I2C_FLAG_BTF)) { - TRACE("I2C READ ERROR: timeout waiting for BTF"); - I2C_Init(); - return false; + if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 10000) != HAL_OK) + { + TRACE("I2C ERROR: ReadRedister read reg address failed"); + asm("bkpt 255"); + return false; } - - I2C_AcknowledgeConfig(I2C, DISABLE); // clear ack bit - *buf++ = I2C_ReceiveData(I2C); // receive byte N-2 - - // Wait for BTF, program stop, read data twice - if (!I2C_WaitFlag(I2C_FLAG_BTF)) { - TRACE("I2C READ ERROR: timeout waiting for BTF"); - I2C_Init(); - return false; - } - - __disable_irq(); - I2C_GenerateSTOP(I2C,ENABLE); - *buf++ = I2C->DR; - __enable_irq(); - - *buf++ = I2C->DR; - } - - return true; + return true; } bool I2C_GT911_SendConfig(void) @@ -791,7 +605,7 @@ bool touchPanelInit(void) TRACE("Touchpanel init start ..."); TOUCH_AF_GPIOConfig(); //SET RST=OUT INT=OUT INT=LOW - I2C_Init(); + I2C_Init_Radio(); TPRST_LOW(); TPINT_HIGH(); @@ -888,10 +702,10 @@ void touchPanelRead() { uint8_t state = 0; - // if (!touchEventOccured) - // return; + if (!touchEventOccured) + return; - // touchEventOccured = false; + touchEventOccured = false; uint32_t startReadStatus = RTOS_GET_MS(); do { diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h index 0651dc1b6..5f3f44f8f 100644 --- a/radio/src/targets/horus/tp_gt911.h +++ b/radio/src/targets/horus/tp_gt911.h @@ -30,28 +30,29 @@ extern bool touchPanelInit(); void touchPanelRead(); bool touchPanelEventOccured(); -#define GT911_TIMEOUT 3 // 3ms +#define GT911_TIMEOUT 3 // 3ms #define GT911_MAX_TP 5 #define GT911_CFG_NUMER 0x6C //I2C -#define GT_CMD_WR 0X28 -#define GT_CMD_RD 0X29 -#define I2C_TIMEOUT_MAX 1000 +#define GT911_I2C_ADDR 0x14 +//#define GT_CMD_WR 0x28 +//#define GT_CMD_RD 0x29 +//#define I2C_TIMEOUT_MAX 1000 -//GT9147 -#define GT_CTRL_REG 0X8040 -#define GT_CFGS_REG 0X8047 -#define GT_CHECK_REG 0X80FF -#define GT_PID_REG 0X8140 +//GT911 +#define GT_CTRL_REG 0x8040 +#define GT_CFGS_REG 0x8047 +#define GT_CHECK_REG 0x80FF +#define GT_PID_REG 0x8140 -#define GT_GSTID_REG 0X814E -#define GT_TP1_REG 0X8150 -#define GT_TP2_REG 0X8158 -#define GT_TP3_REG 0X8160 -#define GT_TP4_REG 0X8168 -#define GT_TP5_REG 0X8170 +#define GT_GSTID_REG 0x814E +#define GT_TP1_REG 0x8150 +#define GT_TP2_REG 0x8158 +#define GT_TP3_REG 0x8160 +#define GT_TP4_REG 0x8168 +#define GT_TP5_REG 0x8170 #define GT911_READ_XY_REG 0x814E #define GT911_CLEARBUF_REG 0x814E diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 27d68d9c0..e25ed35c5 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -1968,7 +1968,7 @@ #define I2C_SDA_GPIO_PinSource GPIO_PinSource7 #define I2C_ADDRESS_VOLUME 0x5C #endif -#define I2C_SPEED 400000 +#define I2C_CLK_RATE 400000 #define I2C_ADDRESS_EEPROM 0xA2 #define I2C_FLASH_PAGESIZE 64 diff --git a/radio/src/targets/taranis/i2c_driver.cpp b/radio/src/targets/taranis/i2c_driver.cpp index 2620312ba..24d15a2c0 100644 --- a/radio/src/targets/taranis/i2c_driver.cpp +++ b/radio/src/targets/taranis/i2c_driver.cpp @@ -37,7 +37,7 @@ void i2cInit() GPIO_ResetBits(I2C_WP_GPIO, I2C_WP_GPIO_PIN); I2C_InitTypeDef I2C_InitStructure; - I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED; + I2C_InitStructure.I2C_ClockSpeed = I2C_CLK_RATE; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; From 2ca5cc771cb21ead71c713328dcd868f06ed0aae Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 21:34:20 +0200 Subject: [PATCH 2/7] Added De-Init and Re-Init (in case this is ever required). --- radio/src/targets/horus/i2c_driver.cpp | 158 ++++++++++++++++++++++--- radio/src/targets/horus/i2c_driver.h | 38 +++--- radio/src/targets/horus/tp_gt911.cpp | 30 +++-- 3 files changed, 175 insertions(+), 51 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index d47af3221..0a1a99bf9 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -77,12 +77,102 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); } +/* De-initializes the GPIOx peripheral registers to their default reset values. + * @param GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or + * x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices. + * @param GPIO_Pin specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @retval None + */ +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) +{ + uint32_t position; + uint32_t ioposition = 0x00U; + uint32_t iocurrent = 0x00U; + uint32_t tmp = 0x00U; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + + /* Configure the port pins */ + for(position = 0U; position < GPIO_NUMBER; position++) + { + /* Get the IO position */ + ioposition = 0x01U << position; + /* Get the current IO position */ + iocurrent = (GPIO_Pin) & ioposition; + + if(iocurrent == ioposition) + { + /*------------------------- EXTI Mode Configuration --------------------*/ + tmp = SYSCFG->EXTICR[position >> 2U]; + tmp &= (0x0FU << (4U * (position & 0x03U))); + if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U)))) + { + /* Clear EXTI line configuration */ + EXTI->IMR &= ~((uint32_t)iocurrent); + EXTI->EMR &= ~((uint32_t)iocurrent); + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR &= ~((uint32_t)iocurrent); + EXTI->FTSR &= ~((uint32_t)iocurrent); + + /* Configure the External Interrupt or event for the current IO */ + tmp = 0x0FU << (4U * (position & 0x03U)); + SYSCFG->EXTICR[position >> 2U] &= ~tmp; + } + + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO Direction in Input Floating Mode */ + GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2U)); + + /* Configure the default Alternate Function in current IO */ + GPIOx->AFR[position >> 3U] &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ; + + /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U)); + + /* Configure the default value IO Output Type */ + GPIOx->OTYPER &= ~(GPIO_OTYPER_OT_0 << position) ; + + /* Configure the default value for IO Speed */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U)); + } + } +} + +/* I2C MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance==I2C1) + { + __HAL_RCC_I2C1_CLK_DISABLE(); + } else + { + if(hi2c->Instance==I2C2) + { + __HAL_RCC_I2C2_CLK_DISABLE(); + if(hi2c->Instance==I2C3) + { + __HAL_RCC_I2C3_CLK_DISABLE(); + } else + TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); + } + } + HAL_GPIO_DeInit(I2C_GPIO, I2C_SCL_GPIO_PinSource); + HAL_GPIO_DeInit(I2C_GPIO, I2C_SDA_GPIO_PinSource); +} + /* Initializes the I2C according to the specified parameters - * in the HAL_I2C_InitTypeDef and initialize the associated handle. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL status - */ + * in the HAL_I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) { uint32_t freqrange; @@ -172,6 +262,41 @@ HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) return HAL_OK; } +/* DeInitialize the I2C peripheral. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + /* Configures I2C Analog noise filter. * @param hi2c pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2Cx peripheral. @@ -254,11 +379,6 @@ HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_ } } -FlagStatus __HAL_I2C_GET_FLAG(I2C_HandleTypeDef *hi2c, uint32_t Flag) -{ - return I2C_GetFlagStatus(hi2c->Instance, Flag); -} - /* This function handles I2C Communication Timeout. * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for I2C module @@ -303,9 +423,9 @@ static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uin */ static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + while (I2C_GetFlagStatus(hi2c->Instance, Flag) == RESET) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + if (I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_AF) == SET) { /* Generate Stop */ SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); @@ -419,7 +539,7 @@ static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_ */ static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_AF) == SET) { /* Clear NACKF Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); @@ -446,7 +566,7 @@ static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) */ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_TXE) == RESET) { /* Check if a NACK is detected */ if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) @@ -483,7 +603,7 @@ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, */ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == RESET) { /* Check if a NACK is detected */ if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) @@ -589,7 +709,7 @@ HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevA hi2c->XferCount--; hi2c->XferSize--; - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + if (( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { /* Write data to DR */ hi2c->Instance->DR = *hi2c->pBuffPtr; @@ -738,10 +858,10 @@ static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_RXNE) == RESET) { /* Check if a STOPF is detected */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_STOPF) == SET) { /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); @@ -990,7 +1110,7 @@ HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAd hi2c->XferSize--; hi2c->XferCount--; - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == SET) { /* Read data from DR */ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index c31b44f0c..f2008084d 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -28,6 +28,19 @@ #define __IO volatile /*!< Defines 'read / write' permissions */ +#define GPIO_NUMBER 16U + +#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U :\ + ((__GPIOx__) == (GPIOI))? 8U :\ + ((__GPIOx__) == (GPIOJ))? 9U : 10U) + #define HAL_MAX_DELAY 0xFFFFFFFFU /* AHB1 Peripheral Clock Enable Disable @@ -226,30 +239,6 @@ UNUSED(tmpreg); \ } while(0) -/* Checks whether the specified I2C flag is set or not. - * @param __HANDLE__ specifies the I2C Handle. - * @param __FLAG__ specifies the flag to check. - * This parameter can be one of the following values: - * @arg I2C_FLAG_OVR: Overrun/Underrun flag - * @arg I2C_FLAG_AF: Acknowledge failure flag - * @arg I2C_FLAG_ARLO: Arbitration lost flag - * @arg I2C_FLAG_BERR: Bus error flag - * @arg I2C_FLAG_TXE: Data register empty flag - * @arg I2C_FLAG_RXNE: Data register not empty flag - * @arg I2C_FLAG_STOPF: Stop detection flag - * @arg I2C_FLAG_ADD10: 10-bit header sent flag - * @arg I2C_FLAG_BTF: Byte transfer finished flag - * @arg I2C_FLAG_ADDR: Address sent flag - * Address matched flag - * @arg I2C_FLAG_SB: Start bit flag - * @arg I2C_FLAG_DUALF: Dual flag - * @arg I2C_FLAG_GENCALL: General call header flag - * @arg I2C_FLAG_TRA: Transmitter/Receiver flag - * @arg I2C_FLAG_BUSY: Bus busy flag - * @arg I2C_FLAG_MSL: Master/Slave flag - * @retval The new state of __FLAG__ (TRUE or FALSE). - */ - /* Clears the I2C pending flags which are cleared by writing 0 in a specific bit. * @param __HANDLE__ specifies the I2C Handle. * @param __FLAG__ specifies the flag to clear. @@ -391,6 +380,7 @@ typedef struct } I2C_HandleTypeDef; HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c); HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 82200288b..6b0471629 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -487,7 +487,7 @@ void TOUCH_AF_INT_Change(void) GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure); } -void I2C_Init_Radio() +void I2C_Init_Radio(void) { TRACE("I2C Init"); @@ -533,7 +533,6 @@ bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 10000) != HAL_OK) { TRACE("I2C ERROR: WriteRegister failed"); - asm("bkpt 255"); return false; } return true; @@ -548,14 +547,12 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10000) != HAL_OK) { TRACE("I2C ERROR: ReadRedister write reg address failed"); - asm("bkpt 255"); return false; } if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 10000) != HAL_OK) { TRACE("I2C ERROR: ReadRedister read reg address failed"); - asm("bkpt 255"); return false; } return true; @@ -678,6 +675,23 @@ bool touchPanelInit(void) } } +bool I2C_ReInit(void) +{ + TRACE("I2C ReInit"); + touchPanelDeInit(); + if (HAL_I2C_DeInit(&hi2c1) != HAL_OK) + TRACE("I2C ReInit - I2C DeInit failed"); + + // If DeInit fails, try to re-init anyway + if (!touchPanelInit()) + { + TRACE("I2C ReInit - touchPanelInit failed"); + return false; + } + return true; +} + + #if defined(SIMU) || defined(SEMIHOSTING) || defined(DEBUG) static const char* event2str(uint8_t ev) { @@ -713,8 +727,8 @@ void touchPanelRead() //ledRed(); touchGT911hiccups++; TRACE("GT911 I2C read XY error"); - touchPanelDeInit(); - touchPanelInit(); + if (!I2C_ReInit()) + TRACE("I2C ReInit failed"); return; } @@ -735,8 +749,8 @@ void touchPanelRead() //ledRed(); touchGT911hiccups++; TRACE("GT911 I2C data read error"); - touchPanelDeInit(); - touchPanelInit(); + if (!I2C_ReInit()) + TRACE("I2C ReInit failed"); return; } if (touchState.event == TE_NONE || touchState.event == TE_UP || From b86745d8f43492f9cbcc325a3f8852ac76290fb9 Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 22:41:12 +0200 Subject: [PATCH 3/7] Clear ADDR bit in atomic way. Not in original STM32F4 HAL. Lower timeouts to more reasonable values. --- radio/src/targets/horus/i2c_driver.cpp | 17 ++++++++--------- radio/src/targets/horus/i2c_driver.h | 4 ++-- radio/src/targets/horus/tp_gt911.cpp | 6 +++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 0a1a99bf9..9998be448 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -28,8 +28,7 @@ uint32_t GetTickCountMS(void) { static uint32_t tickcount = 0; tickcount++; - return (tickcount >> 10); - //return (ticksNow()/CYCLES_IN_MS); + return (tickcount >> 11); // division with 2048, roughly to get milliseconds } /* I2C MSP Initialization @@ -396,7 +395,7 @@ static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uin /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -447,7 +446,7 @@ static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeD /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -577,7 +576,7 @@ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original: HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -614,7 +613,7 @@ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -644,7 +643,7 @@ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { /* Init tickstart for timeout management*/ - uint32_t tickstart = GetTickCountMS(); // Original: HAL_GetTick(); + uint32_t tickstart = GetTickCountMS(); if (hi2c->State == HAL_I2C_STATE_READY) { @@ -878,7 +877,7 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, } /* Check for the Timeout */ - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -907,7 +906,7 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { /* Init tickstart for timeout management*/ - uint32_t tickstart = GetTickCountMS(); // Original HAL_GetTick(); + uint32_t tickstart = GetTickCountMS(); if (hi2c->State == HAL_I2C_STATE_READY) { diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index f2008084d..f1c6069bf 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -234,8 +234,10 @@ #define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg = 0x00U; \ + __disable_irq(); \ tmpreg = (__HANDLE__)->Instance->SR1; \ tmpreg = (__HANDLE__)->Instance->SR2; \ + __enable_irq(); \ UNUSED(tmpreg); \ } while(0) @@ -307,7 +309,6 @@ typedef enum HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ - } HAL_I2C_StateTypeDef; /* HAL Mode structure definition @@ -332,7 +333,6 @@ typedef enum HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ - } HAL_I2C_ModeTypeDef; // I2C configuration structure definition diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 6b0471629..b49d34a7a 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -530,7 +530,7 @@ bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) } } - if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 10000) != HAL_OK) + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 100) != HAL_OK) { TRACE("I2C ERROR: WriteRegister failed"); return false; @@ -544,13 +544,13 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8); uRegAddr[1] = (uint8_t)(reg & 0x00FF); - if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10000) != HAL_OK) + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10) != HAL_OK) { TRACE("I2C ERROR: ReadRedister write reg address failed"); return false; } - if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 10000) != HAL_OK) + if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 100) != HAL_OK) { TRACE("I2C ERROR: ReadRedister read reg address failed"); return false; From a886c72a556f86d586c83c41dbb474e58657717d Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 23:09:33 +0200 Subject: [PATCH 4/7] Cosmetics --- radio/src/targets/horus/i2c_driver.cpp | 29 +++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 9998be448..251b40f68 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -41,17 +41,14 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) GPIO_InitTypeDef GPIO_InitStruct = {0}; if (I2C_GPIO == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (I2C_GPIO == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (I2C_GPIO == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else if (I2C_GPIO == GPIOH) + __HAL_RCC_GPIOH_CLK_ENABLE(); else - if (I2C_GPIO == GPIOB) - __HAL_RCC_GPIOB_CLK_ENABLE(); - else - if (I2C_GPIO == GPIOC) - __HAL_RCC_GPIOC_CLK_ENABLE(); - else - if (I2C_GPIO == GPIOH) - __HAL_RCC_GPIOH_CLK_ENABLE(); - else - TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF); GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF); @@ -66,14 +63,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) /* Peripheral clock enable */ if (I2C == I2C1) __HAL_RCC_I2C1_CLK_ENABLE(); + else if (I2C == I2C2) + __HAL_RCC_I2C2_CLK_ENABLE(); + else if (I2C == I2C3) + __HAL_RCC_I2C3_CLK_ENABLE(); else - if (I2C == I2C2) - __HAL_RCC_I2C2_CLK_ENABLE(); - else - if (I2C == I2C3) - __HAL_RCC_I2C3_CLK_ENABLE(); - else - TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); } /* De-initializes the GPIOx peripheral registers to their default reset values. From 5f0bac3dc94a9ee3f4307c4a1dea6dacbd5787b0 Mon Sep 17 00:00:00 2001 From: rotorman Date: Fri, 16 Jul 2021 18:40:52 +0200 Subject: [PATCH 5/7] Rewrore STM32F4 HAL_I2C_MspDeInit to not call HAL_GPIO_DeInit(), but only disable I2C GPIO with GPIO_Init(). --- radio/src/targets/horus/i2c_driver.cpp | 29 ++++++++++++++++++-------- radio/src/targets/horus/tp_gt911.cpp | 4 ++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 251b40f68..1bd9b403d 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -145,20 +145,31 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) if(hi2c->Instance==I2C1) { __HAL_RCC_I2C1_CLK_DISABLE(); - } else + } + else { if(hi2c->Instance==I2C2) { - __HAL_RCC_I2C2_CLK_DISABLE(); - if(hi2c->Instance==I2C3) - { - __HAL_RCC_I2C3_CLK_DISABLE(); - } else - TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); + __HAL_RCC_I2C2_CLK_DISABLE(); + if(hi2c->Instance==I2C3) + __HAL_RCC_I2C3_CLK_DISABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); } } - HAL_GPIO_DeInit(I2C_GPIO, I2C_SCL_GPIO_PinSource); - HAL_GPIO_DeInit(I2C_GPIO, I2C_SDA_GPIO_PinSource); + + GPIO_InitTypeDef GPIO_InitStructure; + + /* Configure the default Alternate Function in current IO */ + GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, 0); + GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, 0); + + GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; /* Configure a low value for IO Speed */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; /* Configure IO Direction in Input Floating Mode */ + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; /* Leave the configuration to Open Drain */ + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIO_Init(I2C_GPIO, &GPIO_InitStructure); } /* Initializes the I2C according to the specified parameters diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index b49d34a7a..b9065ad54 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -546,13 +546,13 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10) != HAL_OK) { - TRACE("I2C ERROR: ReadRedister write reg address failed"); + TRACE("I2C ERROR: ReadRegister write reg address failed"); return false; } if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 100) != HAL_OK) { - TRACE("I2C ERROR: ReadRedister read reg address failed"); + TRACE("I2C ERROR: ReadRegister read reg address failed"); return false; } return true; From 0423b8d28686bc5442e24b73dbc505665fc28556 Mon Sep 17 00:00:00 2001 From: Risto Date: Sat, 17 Jul 2021 14:40:28 +0200 Subject: [PATCH 6/7] Stop disabling interrupts while clearing ADDR bit --- radio/src/targets/horus/i2c_driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index f1c6069bf..30bb9ffda 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -234,10 +234,8 @@ #define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg = 0x00U; \ - __disable_irq(); \ tmpreg = (__HANDLE__)->Instance->SR1; \ tmpreg = (__HANDLE__)->Instance->SR2; \ - __enable_irq(); \ UNUSED(tmpreg); \ } while(0) From ef08fc019f1130b17546016a9436c1090ae4a426 Mon Sep 17 00:00:00 2001 From: rotorman Date: Sun, 18 Jul 2021 11:32:14 +0200 Subject: [PATCH 7/7] Incremented GT911 configuration with +1 and stopped writing it to GT911 on init/start if the same version has already been flashed to GT911 (as previously). --- radio/src/targets/horus/tp_gt911.cpp | 2 +- radio/src/targets/horus/tp_gt911.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index b9065ad54..667df4b50 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -638,7 +638,7 @@ bool touchPanelInit(void) } TRACE("Chip config Ver:%x", tmp[0]); - if (tmp[0] <= GT911_CFG_NUMER) //Config ver + if (tmp[0] < GT911_CFG_NUMER) //Config ver { TRACE("Sending new config %d", GT911_CFG_NUMER); if (!I2C_GT911_SendConfig()) diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h index 5f3f44f8f..d0fe6e903 100644 --- a/radio/src/targets/horus/tp_gt911.h +++ b/radio/src/targets/horus/tp_gt911.h @@ -33,7 +33,7 @@ bool touchPanelEventOccured(); #define GT911_TIMEOUT 3 // 3ms #define GT911_MAX_TP 5 -#define GT911_CFG_NUMER 0x6C +#define GT911_CFG_NUMER 0x6D //I2C #define GT911_I2C_ADDR 0x14