mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 03:20:00 +03:00
* Move RCC from drivers to platform * Extra line removed * Suggestion from code rabbit * Remove else and require explicit
137 lines
4 KiB
C
137 lines
4 KiB
C
/*
|
|
* This file is part of Betaflight.
|
|
*
|
|
* Betaflight is free software. You can redistribute this software
|
|
* and/or modify this software under the terms of the GNU General
|
|
* Public License as published by the Free Software Foundation,
|
|
* either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* Betaflight 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this software.
|
|
*
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "platform.h"
|
|
|
|
#if defined(USE_I2C) && !defined(SOFT_I2C)
|
|
|
|
#include "drivers/io.h"
|
|
#include "drivers/nvic.h"
|
|
#include "drivers/time.h"
|
|
#include "platform/rcc.h"
|
|
|
|
#include "drivers/bus_i2c.h"
|
|
#include "drivers/bus_i2c_impl.h"
|
|
#include "drivers/bus_i2c_timing.h"
|
|
#include "drivers/bus_i2c_utils.h"
|
|
|
|
#define IOCFG_I2C_PU IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
|
#define IOCFG_I2C IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
|
|
|
|
const i2cHardware_t i2cHardware[I2CDEV_COUNT] = {
|
|
#ifdef USE_I2C_DEVICE_1
|
|
{
|
|
.device = I2CDEV_1,
|
|
.reg = I2C1,
|
|
.sclPins = { I2CPINDEF(PB6, GPIO_AF4_I2C1), I2CPINDEF(PB8, GPIO_AF4_I2C1) },
|
|
.sdaPins = { I2CPINDEF(PB7, GPIO_AF4_I2C1), I2CPINDEF(PB9, GPIO_AF4_I2C1) },
|
|
.rcc = RCC_APB1(I2C1),
|
|
.ev_irq = I2C1_EV_IRQn,
|
|
.er_irq = I2C1_ER_IRQn,
|
|
},
|
|
#endif
|
|
#ifdef USE_I2C_DEVICE_2
|
|
{
|
|
.device = I2CDEV_2,
|
|
.reg = I2C2,
|
|
.sclPins = { I2CPINDEF(PB10, GPIO_AF4_I2C2), I2CPINDEF(PF1, GPIO_AF4_I2C2) },
|
|
.sdaPins = { I2CPINDEF(PB11, GPIO_AF4_I2C2), I2CPINDEF(PF0, GPIO_AF4_I2C2) },
|
|
.rcc = RCC_APB1(I2C2),
|
|
.ev_irq = I2C2_EV_IRQn,
|
|
.er_irq = I2C2_ER_IRQn,
|
|
},
|
|
#endif
|
|
#ifdef USE_I2C_DEVICE_3
|
|
{
|
|
.device = I2CDEV_3,
|
|
.reg = I2C3,
|
|
.sclPins = { I2CPINDEF(PA8, GPIO_AF4_I2C3) },
|
|
.sdaPins = { I2CPINDEF(PC9, GPIO_AF4_I2C3) },
|
|
.rcc = RCC_APB1(I2C3),
|
|
.ev_irq = I2C3_EV_IRQn,
|
|
.er_irq = I2C3_ER_IRQn,
|
|
},
|
|
#endif
|
|
};
|
|
|
|
i2cDevice_t i2cDevice[I2CDEV_COUNT];
|
|
|
|
void i2cInit(I2CDevice device)
|
|
{
|
|
if (device == I2CINVALID) {
|
|
return;
|
|
}
|
|
|
|
i2cDevice_t *pDev = &i2cDevice[device];
|
|
|
|
const i2cHardware_t *hardware = pDev->hardware;
|
|
const IO_t scl = pDev->scl;
|
|
const IO_t sda = pDev->sda;
|
|
|
|
if (!hardware || IOGetOwner(scl) || IOGetOwner(sda)) {
|
|
return;
|
|
}
|
|
|
|
IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device));
|
|
IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device));
|
|
|
|
// Enable RCC
|
|
RCC_ClockCmd(hardware->rcc, ENABLE);
|
|
|
|
i2cUnstick(scl, sda);
|
|
|
|
// Init pins
|
|
IOConfigGPIOAF(scl, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, pDev->sclAF);
|
|
IOConfigGPIOAF(sda, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, pDev->sdaAF);
|
|
|
|
// Init I2C peripheral
|
|
|
|
I2C_HandleTypeDef *pHandle = &pDev->handle;
|
|
|
|
memset(pHandle, 0, sizeof(*pHandle));
|
|
|
|
pHandle->Instance = pDev->hardware->reg;
|
|
|
|
// Compute TIMINGR value based on peripheral clock for this device instance
|
|
|
|
pHandle->Init.ClockSpeed = pDev->clockSpeed * 1000;
|
|
|
|
pHandle->Init.OwnAddress1 = 0x0;
|
|
pHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
|
pHandle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
|
pHandle->Init.OwnAddress2 = 0x0;
|
|
pHandle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
|
pHandle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
|
|
|
DAL_I2C_Init(pHandle);
|
|
|
|
// Setup interrupt handlers
|
|
DAL_NVIC_SetPriority(hardware->er_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_ER));
|
|
DAL_NVIC_EnableIRQ(hardware->er_irq);
|
|
DAL_NVIC_SetPriority(hardware->ev_irq, NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_EV), NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_EV));
|
|
DAL_NVIC_EnableIRQ(hardware->ev_irq);
|
|
}
|
|
|
|
#endif
|