mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 18:13:49 +01:00
Merge pull request #18279 from gschorcht/cpu/esp32/periph_hal_esp32_i2c
cpu/esp32: use ESP-IDF i2c HAL for ESP32 periph/i2c
This commit is contained in:
commit
365fbed906
@ -100,24 +100,48 @@ static const gpio_t dac_channels[] = DAC_GPIOS;
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(I2C0_SCL) && !defined(I2C0_SCL_PULLUP)
|
||||
/** Define SCL pullup enabled by default */
|
||||
#define I2C0_SCL_PULLUP true
|
||||
#endif
|
||||
#if defined(I2C0_SDA) && !defined(I2C0_SDA_PULLUP)
|
||||
/** Define SDA pullup enabled by default */
|
||||
#define I2C0_SDA_PULLUP true
|
||||
#endif
|
||||
|
||||
#if defined(I2C1_SCL) && !defined(I2C1_SCL_PULLUP)
|
||||
/** Define SCL pullup enabled by default */
|
||||
#define I2C1_SCL_PULLUP true
|
||||
#endif
|
||||
#if defined(I2C1_SDA) && !defined(I2C1_SDA_PULLUP)
|
||||
/** Define SDA pullup enabled by default */
|
||||
#define I2C1_SDA_PULLUP true
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Static array with configuration for declared I2C devices
|
||||
*/
|
||||
static const i2c_conf_t i2c_config[] = {
|
||||
#if defined(I2C0_SCL) && defined(I2C0_SDA) && defined(I2C0_SPEED)
|
||||
#if defined(I2C0_SCL) && defined(I2C0_SDA) && defined(I2C0_SPEED)
|
||||
{
|
||||
.module = PERIPH_I2C0_MODULE,
|
||||
.speed = I2C0_SPEED,
|
||||
.scl = I2C0_SCL,
|
||||
.sda = I2C0_SDA,
|
||||
.scl_pullup = I2C0_SCL_PULLUP,
|
||||
.sda_pullup = I2C0_SCL_PULLUP,
|
||||
},
|
||||
#endif
|
||||
#if defined(I2C1_SCL) && defined(I2C1_SDA) && defined(I2C1_SPEED)
|
||||
#endif
|
||||
#if defined(I2C1_SCL) && defined(I2C1_SDA) && defined(I2C1_SPEED)
|
||||
{
|
||||
.module = PERIPH_I2C1_MODULE,
|
||||
.speed = I2C1_SPEED,
|
||||
.scl = I2C1_SCL,
|
||||
.sda = I2C1_SDA,
|
||||
.scl_pullup = I2C1_SCL_PULLUP,
|
||||
.sda_pullup = I2C1_SCL_PULLUP,
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@ -287,18 +311,18 @@ static const uart_conf_t uart_config[] = {
|
||||
.txd = UART0_TXD,
|
||||
.rxd = UART0_RXD,
|
||||
},
|
||||
#if defined(UART1_TXD) && defined(UART1_RXD)
|
||||
#if defined(UART1_TXD) && defined(UART1_RXD)
|
||||
{
|
||||
.txd = UART1_TXD,
|
||||
.rxd = UART1_RXD,
|
||||
},
|
||||
#endif
|
||||
#if defined(UART2_TXD) && defined(UART2_RXD)
|
||||
#endif
|
||||
#if defined(UART2_TXD) && defined(UART2_RXD)
|
||||
{
|
||||
.txd = UART2_TXD,
|
||||
.rxd = UART2_RXD,
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#ifndef PERIPH_CPU_H
|
||||
#define PERIPH_CPU_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/ledc_types.h"
|
||||
@ -331,15 +332,18 @@ typedef enum {
|
||||
* @brief I2C configuration structure type
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t module; /**< I2C module identifier */
|
||||
i2c_speed_t speed; /**< I2C bus speed */
|
||||
gpio_t scl; /**< GPIO used as SCL pin */
|
||||
gpio_t sda; /**< GPIO used as SDA pin */
|
||||
bool scl_pullup; /**< Pullup enabled for SCL pin */
|
||||
bool sda_pullup; /**< Pullup enabled for SDA pin */
|
||||
} i2c_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Maximum number of I2C interfaces that can be used by board definitions
|
||||
*/
|
||||
#define I2C_NUMOF_MAX (2)
|
||||
#define I2C_NUMOF_MAX (SOC_I2C_NUM)
|
||||
|
||||
#define PERIPH_I2C_NEED_READ_REG /**< i2c_read_reg required */
|
||||
#define PERIPH_I2C_NEED_READ_REGS /**< i2c_read_regs required */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level I2C driver software implementation using for ESP SoCs
|
||||
* @brief Low-level I2C driver software implementation for ESP SoCs
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
@ -35,6 +35,7 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "log.h"
|
||||
#include "macros/units.h"
|
||||
#include "mutex.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/gpio.h"
|
||||
@ -42,11 +43,15 @@
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_common.h"
|
||||
#if !defined(MCU_ESP8266)
|
||||
#include "esp_private/esp_clk.h"
|
||||
#endif
|
||||
#include "gpio_arch.h"
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#ifndef MCU_ESP8266
|
||||
|
||||
#include "hal/cpu_hal.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
|
||||
@ -104,38 +109,21 @@ static _i2c_bus_t _i2c_bus[I2C_NUMOF] = {};
|
||||
/* to ensure that I2C is always optimized with -O2 to use the defined delays */
|
||||
#pragma GCC optimize ("O2")
|
||||
|
||||
#ifdef MCU_ESP32
|
||||
static const uint32_t _i2c_delays[][5] =
|
||||
{
|
||||
/* values specify one half-period and are only valid for -O2 option */
|
||||
/* value = [period - 0.25 us (240 MHz) / 0.5us(160MHz) / 1.0us(80MHz)] */
|
||||
/* * cycles per second / 2 */
|
||||
/* 1 us = 16 cycles (80 MHz) / 32 cycles (160 MHz) / 48 cycles (240) */
|
||||
/* max clock speeds 2 MHz CPU clock: 19 kHz */
|
||||
/* 40 MHz CPU clock: 308 kHz */
|
||||
/* 80 MHz CPU clock: 516 kHz */
|
||||
/* 160 MHz CPU clock: 727 kHz */
|
||||
/* 240 MHz CPU clock: 784 kHz */
|
||||
/* values for 80, 160, 240, 2, 40 MHz */
|
||||
[I2C_SPEED_LOW] = {790, 1590, 2390, 10, 390 }, /* 10 kbps (period 100 us) */
|
||||
[I2C_SPEED_NORMAL] = { 70, 150, 230, 0, 30 }, /* 100 kbps (period 10 us) */
|
||||
[I2C_SPEED_FAST] = { 11, 31, 51, 0, 0 }, /* 400 kbps (period 2.5 us) */
|
||||
[I2C_SPEED_FAST_PLUS] = { 0, 0, 0, 0, 0 }, /* 1 Mbps (period 1 us) */
|
||||
[I2C_SPEED_HIGH] = { 0, 0, 0, 0, 0 } /* 3.4 Mbps (period 0.3 us) not working */
|
||||
#if defined(MCU_ESP32)
|
||||
#define I2C_CLK_CAL 62 /* clock calibration offset */
|
||||
#elif defined(MCU_ESP8266)
|
||||
#define I2C_CLK_CAL 47 /* clock calibration offset */
|
||||
#else
|
||||
#error "Platform implementation is missing"
|
||||
#endif
|
||||
|
||||
static const uint32_t _i2c_clocks[] = {
|
||||
10 * KHZ(1), /* I2C_SPEED_LOW */
|
||||
100 * KHZ(1), /* I2C_SPEED_NORMAL */
|
||||
400 * KHZ(1), /* I2C_SPEED_FAST */
|
||||
1000 * KHZ(1), /* I2C_SPEED_FAST_PLUS */
|
||||
3400 * KHZ(1), /* I2C_SPEED_HIGH */
|
||||
};
|
||||
#else /* MCU_ESP32 */
|
||||
static const uint32_t _i2c_delays[][2] =
|
||||
{
|
||||
/* values specify one half-period and are only valid for -O2 option */
|
||||
/* value = [period - 0.5us(160MHz) or 1.0us(80MHz)] * cycles per second / 2 */
|
||||
/* 1 us = 20 cycles (80 MHz) / 40 cycles (160 MHz) */
|
||||
[I2C_SPEED_LOW] = {989, 1990}, /* 10 kbps (period 100 us) */
|
||||
[I2C_SPEED_NORMAL] = { 89, 190}, /* 100 kbps (period 10 us) */
|
||||
[I2C_SPEED_FAST] = { 15, 40}, /* 400 kbps (period 2.5 us) */
|
||||
[I2C_SPEED_FAST_PLUS] = { 0, 13}, /* 1 Mbps (period 1 us) */
|
||||
[I2C_SPEED_HIGH] = { 0, 0} /* 3.4 Mbps (period 0.3 us) is not working */
|
||||
};
|
||||
#endif /* MCU_ESP32 */
|
||||
|
||||
/* forward declaration of internal functions */
|
||||
|
||||
@ -156,6 +144,13 @@ static int _i2c_arbitration_lost(_i2c_bus_t* bus, const char* func);
|
||||
static void _i2c_abort(_i2c_bus_t* bus, const char* func);
|
||||
static void _i2c_clear(_i2c_bus_t* bus);
|
||||
|
||||
#if defined(MCU_ESP8266)
|
||||
static inline int esp_clk_cpu_freq(void)
|
||||
{
|
||||
return ets_get_cpu_frequency() * MHZ(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* implementation of i2c interface */
|
||||
|
||||
void i2c_init(i2c_t dev)
|
||||
@ -177,19 +172,10 @@ void i2c_init(i2c_t dev)
|
||||
_i2c_bus[dev].sda_bit = BIT(_i2c_bus[dev].sda); /* store bit mask for faster access */
|
||||
_i2c_bus[dev].started = false; /* for handling of repeated start condition */
|
||||
|
||||
switch (ets_get_cpu_frequency()) {
|
||||
case 80: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][0]; break;
|
||||
case 160: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][1]; break;
|
||||
#ifdef MCU_ESP32
|
||||
case 240: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][2]; break;
|
||||
case 2: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][3]; break;
|
||||
case 40: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][4]; break;
|
||||
#endif
|
||||
default : LOG_TAG_INFO("i2c", "I2C software implementation is not "
|
||||
"supported for this CPU frequency: %d MHz\n",
|
||||
ets_get_cpu_frequency());
|
||||
return;
|
||||
}
|
||||
uint32_t delay;
|
||||
delay = esp_clk_cpu_freq() / _i2c_clocks[_i2c_bus[dev].speed] / 2;
|
||||
delay = (delay > I2C_CLK_CAL) ? delay - I2C_CLK_CAL : 0;
|
||||
_i2c_bus[dev].delay = delay;
|
||||
|
||||
DEBUG("%s: scl=%d sda=%d speed=%d\n", __func__,
|
||||
_i2c_bus[dev].scl, _i2c_bus[dev].sda, _i2c_bus[dev].speed);
|
||||
@ -418,8 +404,18 @@ static inline void _i2c_delay(_i2c_bus_t* bus)
|
||||
/* produces a delay */
|
||||
uint32_t cycles = bus->delay;
|
||||
if (cycles) {
|
||||
__asm__ volatile ("1: _addi.n %0, %0, -1 \n"
|
||||
" bnez %0, 1b \n" : "=r" (cycles) : "0" (cycles));
|
||||
#ifdef MCU_ESP8266
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
uint32_t wait_until = ccount + cycles;
|
||||
while (ccount < wait_until) {
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
}
|
||||
#else
|
||||
uint32_t start = cpu_hal_get_cycle_count();
|
||||
uint32_t wait_until = start + cycles;
|
||||
while (cpu_hal_get_cycle_count() < wait_until) { }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -837,8 +833,13 @@ static IRAM_ATTR int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack)
|
||||
|
||||
void i2c_print_config(void)
|
||||
{
|
||||
for (unsigned dev = 0; dev < I2C_NUMOF; dev++) {
|
||||
printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n",
|
||||
dev, i2c_config[dev].scl, i2c_config[dev].sda);
|
||||
if (I2C_NUMOF) {
|
||||
for (unsigned dev = 0; dev < I2C_NUMOF; dev++) {
|
||||
printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n",
|
||||
dev, i2c_config[dev].scl, i2c_config[dev].sda);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_TAG_INFO("i2c", "no I2C devices\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From 25509b8b61b329d3c4ae5b3874704dae55d62ccd Mon Sep 17 00:00:00 2001
|
||||
From: Gunar Schorcht <gunar@schorcht.net>
|
||||
Date: Tue, 8 Mar 2022 11:34:13 +0100
|
||||
Subject: [PATCH 15/17] driver/i2c: remove the include gpio.h in i2c.h header
|
||||
|
||||
Including driver/i2c.h by RIOT code leads to type conflicts with RIOT gpio_t type.
|
||||
---
|
||||
components/driver/i2c.c | 1 +
|
||||
components/driver/include/driver/i2c.h | 1 -
|
||||
2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/driver/i2c.c b/components/driver/i2c.c
|
||||
index 438d1efc12d..be26fdeffc3 100644
|
||||
--- a/components/driver/i2c.c
|
||||
+++ b/components/driver/i2c.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "hal/i2c_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
+#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h
|
||||
index 22dcc8ab241..e668bba2acd 100644
|
||||
--- a/components/driver/include/driver/i2c.h
|
||||
+++ b/components/driver/include/driver/i2c.h
|
||||
@@ -19,7 +19,6 @@ extern "C" {
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
-#include "driver/gpio.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/i2c_types.h"
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From cd8688a55e62094cb6605ee8594985f862d57a95 Mon Sep 17 00:00:00 2001
|
||||
From: Gunar Schorcht <gunar@schorcht.net>
|
||||
Date: Tue, 8 Mar 2022 11:35:11 +0100
|
||||
Subject: [PATCH 16/17] driver/i2c.h: expose i2c_hw_fsm_reset to RIOT code
|
||||
|
||||
---
|
||||
components/driver/i2c.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/driver/i2c.c b/components/driver/i2c.c
|
||||
index be26fdeffc3..cff410b9d1b 100644
|
||||
--- a/components/driver/i2c.c
|
||||
+++ b/components/driver/i2c.c
|
||||
@@ -209,7 +209,7 @@ static i2c_clk_alloc_t i2c_clk_alloc[I2C_SCLK_MAX] = {
|
||||
static i2c_obj_t *p_i2c_obj[I2C_NUM_MAX] = {0};
|
||||
static void i2c_isr_handler_default(void *arg);
|
||||
static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num);
|
||||
-static esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
|
||||
+esp_err_t IRAM_ATTR i2c_hw_fsm_reset(i2c_port_t i2c_num);
|
||||
|
||||
static void i2c_hw_disable(i2c_port_t i2c_num)
|
||||
{
|
||||
@@ -595,7 +595,7 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
* If we remove the power supply for the slave during I2C is reading, or directly connect SDA or SCL to ground,
|
||||
* this would cause the I2C FSM get stuck in wrong state, all we can do is to reset the I2C hardware in this case.
|
||||
**/
|
||||
-static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
+esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
{
|
||||
#if !SOC_I2C_SUPPORT_HW_FSM_RST
|
||||
int scl_low_period, scl_high_period;
|
||||
--
|
||||
2.17.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user