summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianShuang Ke <QinYUN575@Gmail.com>2024-06-27 22:36:18 +0800
committerAngus Gratton <angus@redyak.com.au>2025-07-30 10:51:29 +1000
commitca9916968c06437fa39549b0995ceb811209f994 (patch)
tree8e1b5ef2e9ce7ae79e2137708cba0a28c791a7a9
parent88cb6bc818546e7fe8b862c784e1e4a6b8a12b8a (diff)
esp32: Add support for ESP32-C2 (aka ESP8684).
Includes: esp32/esp32c2: Adapt to target chip ESP32C2. esp32/esp32c2: Fix heap size is too small to enable Bluetooth. Signed-off-by: TianShuangKe <qinyun575@gmail.com> Signed-off-by: Angus Gratton <angus@redyak.com.au>
-rw-r--r--docs/esp32/quickref.rst3
-rw-r--r--ports/esp32/README.md4
-rw-r--r--ports/esp32/boards/ESP32_GENERIC_C2/board.json22
-rw-r--r--ports/esp32/boards/ESP32_GENERIC_C2/board.md3
-rw-r--r--ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.cmake7
-rw-r--r--ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.h7
-rw-r--r--ports/esp32/boards/sdkconfig.base6
-rw-r--r--ports/esp32/boards/sdkconfig.c211
-rw-r--r--ports/esp32/esp32_rmt.c6
-rw-r--r--ports/esp32/machine_adc.c6
-rw-r--r--ports/esp32/machine_bitstream.c11
-rw-r--r--ports/esp32/machine_i2c.c6
-rw-r--r--ports/esp32/machine_pin.c2
-rw-r--r--ports/esp32/machine_pin.h17
-rw-r--r--ports/esp32/modesp32.c2
-rw-r--r--ports/esp32/modmachine.c6
-rw-r--r--ports/esp32/mpconfigport.h4
-rw-r--r--tests/extmod/machine_spi_rate.py2
-rw-r--r--tests/ports/esp32/esp32_idf_heap_info.py17
-rw-r--r--tests/ports/esp32/esp32_idf_heap_info.py.exp4
20 files changed, 128 insertions, 18 deletions
diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst
index c394414a7..49f546a17 100644
--- a/docs/esp32/quickref.rst
+++ b/docs/esp32/quickref.rst
@@ -802,6 +802,9 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
# The channel resolution is 100ns (1/(source_freq/clock_div)).
r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
+The ESP32-C2 family does not include any RMT peripheral, so this class is
+unavailable on those SoCs.
+
OneWire driver
--------------
diff --git a/ports/esp32/README.md b/ports/esp32/README.md
index 4adff6632..dd4584772 100644
--- a/ports/esp32/README.md
+++ b/ports/esp32/README.md
@@ -5,8 +5,8 @@ This is a port of MicroPython to the Espressif ESP32 series of
microcontrollers. It uses the ESP-IDF framework and MicroPython runs as
a task under FreeRTOS.
-Currently supports ESP32, ESP32-C3, ESP32-C6, ESP32-S2 and ESP32-S3
-(ESP8266 is supported by a separate MicroPython port).
+Currently supports ESP32, ESP32-C2 (aka ESP8684), ESP32-C3, ESP32-C6, ESP32-S2
+and ESP32-S3 (ESP8266 is supported by a separate MicroPython port).
Supported features include:
- REPL (Python prompt) over UART0.
diff --git a/ports/esp32/boards/ESP32_GENERIC_C2/board.json b/ports/esp32/boards/ESP32_GENERIC_C2/board.json
new file mode 100644
index 000000000..da0931a0e
--- /dev/null
+++ b/ports/esp32/boards/ESP32_GENERIC_C2/board.json
@@ -0,0 +1,22 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "deploy_options": {
+ "flash_offset": "0"
+ },
+ "docs": "",
+ "features": [
+ "BLE",
+ "External Flash",
+ "WiFi"
+ ],
+ "images": [
+ "esp32c2_devkitmini.jpg"
+ ],
+ "mcu": "esp32c2",
+ "product": "ESP32-C2",
+ "thumbnail": "",
+ "url": "https://www.espressif.com/en/products/modules",
+ "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/ESP32_GENERIC_C2/board.md b/ports/esp32/boards/ESP32_GENERIC_C2/board.md
new file mode 100644
index 000000000..b8ed10069
--- /dev/null
+++ b/ports/esp32/boards/ESP32_GENERIC_C2/board.md
@@ -0,0 +1,3 @@
+The following files are firmware images that should work on most ESP32-C2-based
+boards with at least 4MiB of flash and 26MHz crystal frequency. This includes
+ESP8684-WROOM and ESP8684-MINI modules.
diff --git a/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.cmake b/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.cmake
new file mode 100644
index 000000000..e9d498995
--- /dev/null
+++ b/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.cmake
@@ -0,0 +1,7 @@
+set(IDF_TARGET esp32c2)
+
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.ble
+ boards/sdkconfig.c2
+)
diff --git a/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.h b/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.h
new file mode 100644
index 000000000..ee918aaba
--- /dev/null
+++ b/ports/esp32/boards/ESP32_GENERIC_C2/mpconfigboard.h
@@ -0,0 +1,7 @@
+// This configuration is for a generic ESP32C2 board with 4MiB (or more) of flash.
+
+#define MICROPY_HW_BOARD_NAME "ESP32C2 module"
+#define MICROPY_HW_MCU_NAME "ESP32C2"
+
+#define MICROPY_HW_ENABLE_SDCARD (0)
+#define MICROPY_PY_MACHINE_I2S (0)
diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base
index 30740af43..69abc63bd 100644
--- a/ports/esp32/boards/sdkconfig.base
+++ b/ports/esp32/boards/sdkconfig.base
@@ -125,9 +125,9 @@ CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL=y
CONFIG_ETH_SPI_ETHERNET_DM9051=y
# Using newlib "nano" formatting saves size on SoCs where "nano" formatting
-# functions are in ROM. Note some newer chips (c2,c6) have "full" newlib
-# formatting in ROM instead and should override this, check
-# ESP_ROM_HAS_NEWLIB_NANO_FORMAT.
+# functions are in ROM. ESP32-C6 (and possibly other new chips) have "full"
+# newlib formatting in ROM instead and should override this, check
+# ESP_ROM_HAS_NEWLIB_NANO_FORMAT in ESP-IDF.
CONFIG_NEWLIB_NANO_FORMAT=y
# IRAM/DRAM split protection is a memory protection feature on some parts
diff --git a/ports/esp32/boards/sdkconfig.c2 b/ports/esp32/boards/sdkconfig.c2
new file mode 100644
index 000000000..e85bcdba3
--- /dev/null
+++ b/ports/esp32/boards/sdkconfig.c2
@@ -0,0 +1,11 @@
+#
+# Main XTAL Config
+#
+CONFIG_XTAL_FREQ_26=y
+# CONFIG_XTAL_FREQ_40 is not set
+CONFIG_XTAL_FREQ=26
+# Increase NimBLE stack size for functional BT
+CONFIG_BT_NIMBLE_TASK_STACK_SIZE=5120
+
+# Decrease mDNS stack size to save RAM
+CONFIG_MDNS_TASK_STACK_SIZE=3072
diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c
index 6890e16bf..f3bfbecdd 100644
--- a/ports/esp32/esp32_rmt.c
+++ b/ports/esp32/esp32_rmt.c
@@ -30,6 +30,8 @@
#include "modesp32.h"
#include "esp_task.h"
+
+#if SOC_RMT_SUPPORTED
#include "driver/rmt.h"
// This exposes the ESP32's RMT module to MicroPython. RMT is provided by the Espressif ESP-IDF:
@@ -105,7 +107,7 @@ esp_err_t rmt_driver_install_core1(uint8_t channel_id) {
return rmt_driver_install(channel_id, 0, 0);
}
-#endif
+#endif // MP_TASK_COREID==0
static mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
static const mp_arg_t allowed_args[] = {
@@ -387,3 +389,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
print, esp32_rmt_print,
locals_dict, &esp32_rmt_locals_dict
);
+
+#endif // SOC_RMT_SUPPORTED
diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c
index 02acaa22d..c5575d45e 100644
--- a/ports/esp32/machine_adc.c
+++ b/ports/esp32/machine_adc.c
@@ -87,6 +87,12 @@ static const machine_adc_obj_t madc_obj[] = {
{{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_7, GPIO_NUM_27},
{{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_8, GPIO_NUM_25},
{{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_9, GPIO_NUM_26},
+ #elif CONFIG_IDF_TARGET_ESP32C2
+ {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_0},
+ {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_1},
+ {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_2, GPIO_NUM_2},
+ {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_3, GPIO_NUM_3},
+ {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_4, GPIO_NUM_4},
#elif CONFIG_IDF_TARGET_ESP32C3
{{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_0},
{{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_1},
diff --git a/ports/esp32/machine_bitstream.c b/ports/esp32/machine_bitstream.c
index 6296ff067..ed7fcc407 100644
--- a/ports/esp32/machine_bitstream.c
+++ b/ports/esp32/machine_bitstream.c
@@ -90,6 +90,7 @@ static void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, u
mp_hal_quiet_timing_exit(irq_state);
}
+#if SOC_RMT_SUPPORTED
/******************************************************************************/
// RMT implementation
@@ -172,16 +173,18 @@ static void machine_bitstream_high_low_rmt(mp_hal_pin_obj_t pin, uint32_t *timin
// Cancel RMT output to GPIO pin.
esp_rom_gpio_connect_out_signal(pin, SIG_GPIO_OUT_IDX, false, false);
}
-
+#endif
/******************************************************************************/
// Interface to machine.bitstream
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) {
- if (esp32_rmt_bitstream_channel_id < 0) {
- machine_bitstream_high_low_bitbang(pin, timing_ns, buf, len);
- } else {
+ #if SOC_RMT_SUPPORTED
+ if (esp32_rmt_bitstream_channel_id >= 0) {
machine_bitstream_high_low_rmt(pin, timing_ns, buf, len, esp32_rmt_bitstream_channel_id);
+ return;
}
+ #endif
+ machine_bitstream_high_low_bitbang(pin, timing_ns, buf, len);
}
#endif // MICROPY_PY_MACHINE_BITSTREAM
diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c
index 259101ee7..4a5fd7176 100644
--- a/ports/esp32/machine_i2c.c
+++ b/ports/esp32/machine_i2c.c
@@ -55,7 +55,11 @@
#endif
#if SOC_I2C_SUPPORT_XTAL
-#define I2C_SCLK_FREQ XTAL_CLK_FREQ
+#if CONFIG_XTAL_FREQ > 0
+#define I2C_SCLK_FREQ (CONFIG_XTAL_FREQ * 1000000)
+#else
+#error "I2C uses XTAL but no configured freq"
+#endif // CONFIG_XTAL_FREQ
#elif SOC_I2C_SUPPORT_APB
#define I2C_SCLK_FREQ APB_CLK_FREQ
#else
diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c
index 4ab79f0a2..9999223b5 100644
--- a/ports/esp32/machine_pin.c
+++ b/ports/esp32/machine_pin.c
@@ -152,7 +152,7 @@ static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
// reset the pin to digital if this is a mode-setting init (grab it back from ADC)
if (args[ARG_mode].u_obj != mp_const_none) {
if (rtc_gpio_is_valid_gpio(index)) {
- #if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
+ #if !(CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
rtc_gpio_deinit(index);
#endif
}
diff --git a/ports/esp32/machine_pin.h b/ports/esp32/machine_pin.h
index 47f1ddebe..6fe9ef0e7 100644
--- a/ports/esp32/machine_pin.h
+++ b/ports/esp32/machine_pin.h
@@ -71,6 +71,23 @@
#define MICROPY_HW_ENABLE_GPIO38 (1)
#define MICROPY_HW_ENABLE_GPIO39 (1)
+#elif CONFIG_IDF_TARGET_ESP32C2
+
+#define MICROPY_HW_ENABLE_GPIO0 (1)
+#define MICROPY_HW_ENABLE_GPIO1 (1)
+#define MICROPY_HW_ENABLE_GPIO2 (1)
+#define MICROPY_HW_ENABLE_GPIO3 (1)
+#define MICROPY_HW_ENABLE_GPIO4 (1)
+#define MICROPY_HW_ENABLE_GPIO5 (1)
+#define MICROPY_HW_ENABLE_GPIO6 (1)
+#define MICROPY_HW_ENABLE_GPIO7 (1)
+#define MICROPY_HW_ENABLE_GPIO8 (1)
+#define MICROPY_HW_ENABLE_GPIO9 (1)
+#define MICROPY_HW_ENABLE_GPIO10 (1)
+#define MICROPY_HW_ENABLE_GPIO18 (1)
+#define MICROPY_HW_ENABLE_GPIO19 (1) // UART0_RXD
+#define MICROPY_HW_ENABLE_GPIO20 (1) // UART0_TXD
+
#elif CONFIG_IDF_TARGET_ESP32C3
#define MICROPY_HW_ENABLE_GPIO0 (1)
diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c
index fcd6ed9fa..bf7aec394 100644
--- a/ports/esp32/modesp32.c
+++ b/ports/esp32/modesp32.c
@@ -299,7 +299,9 @@ static const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },
+ #if SOC_RMT_SUPPORTED
{ MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) },
+ #endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) },
#endif
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index 0d7ea44c6..06360e8e8 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -99,6 +99,11 @@ static mp_obj_t mp_machine_get_freq(void) {
static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
+ #if CONFIG_IDF_TARGET_ESP32C2
+ if (freq != 80 && freq != 120) {
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 80MHz or 120MHz"));
+ }
+ #else
if (freq != 20 && freq != 40 && freq != 80 && freq != 160
#if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
&& freq != 240
@@ -110,6 +115,7 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
#endif
}
+ #endif
esp_pm_config_t pm = {
.max_freq_mhz = freq,
.min_freq_mhz = freq,
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 721f22de1..142c1b1be 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -32,7 +32,7 @@
#ifndef MICROPY_GC_INITIAL_HEAP_SIZE
#if CONFIG_IDF_TARGET_ESP32
#define MICROPY_GC_INITIAL_HEAP_SIZE (56 * 1024)
-#elif CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_SPIRAM
+#elif CONFIG_IDF_TARGET_ESP32C2 || (CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_SPIRAM)
#define MICROPY_GC_INITIAL_HEAP_SIZE (36 * 1024)
#else
#define MICROPY_GC_INITIAL_HEAP_SIZE (64 * 1024)
@@ -165,6 +165,8 @@
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s2"
#elif CONFIG_IDF_TARGET_ESP32S3
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s3"
+#elif CONFIG_IDF_TARGET_ESP32C2
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c2"
#elif CONFIG_IDF_TARGET_ESP32C3
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c3"
#elif CONFIG_IDF_TARGET_ESP32C6
diff --git a/tests/extmod/machine_spi_rate.py b/tests/extmod/machine_spi_rate.py
index c65095f22..fe15b66fe 100644
--- a/tests/extmod/machine_spi_rate.py
+++ b/tests/extmod/machine_spi_rate.py
@@ -25,7 +25,7 @@ elif "rp2" in sys.platform:
spi_instances = ((0, Pin(18), Pin(19), Pin(16)),)
elif "esp32" in sys.platform:
impl = str(sys.implementation)
- if "ESP32C3" in impl or "ESP32C6" in impl:
+ if any(soc in impl for soc in ("ESP32C2", "ESP32C3", "ESP32C6")):
spi_instances = ((1, Pin(4), Pin(5), Pin(6)),)
else:
spi_instances = ((1, Pin(18), Pin(19), Pin(21)), (2, Pin(18), Pin(19), Pin(21)))
diff --git a/tests/ports/esp32/esp32_idf_heap_info.py b/tests/ports/esp32/esp32_idf_heap_info.py
index fdd89161f..2f4529593 100644
--- a/tests/ports/esp32/esp32_idf_heap_info.py
+++ b/tests/ports/esp32/esp32_idf_heap_info.py
@@ -5,6 +5,19 @@ except ImportError:
print("SKIP")
raise SystemExit
+import sys
+
+# idf_heap_info() is expected to return at least this many
+# regions for HEAP_DATA and HEAP_EXEC, respectively.
+MIN_DATA = 3
+MIN_EXEC = 3
+
+impl = str(sys.implementation)
+if "ESP32C2" in impl:
+ # ESP32-C2 is less fragmented (yay!) and only has two memory regions
+ MIN_DATA = 2
+ MIN_EXEC = 2
+
# region tuple is: (size, free, largest free, min free)
# we check that each region's size is > 0 and that the free amounts are smaller than the size
@@ -22,12 +35,12 @@ def chk_heap(kind, regions):
# try getting heap regions
regions = esp32.idf_heap_info(esp32.HEAP_DATA)
-print("HEAP_DATA >2:", len(regions) > 2)
+print("HEAP_DATA >=MIN:", len(regions) >= MIN_DATA)
chk_heap("HEAP_DATA", regions)
# try getting code regions
regions = esp32.idf_heap_info(esp32.HEAP_EXEC)
-print("HEAP_EXEC >2:", len(regions) > 2)
+print("HEAP_EXEC >=MIN:", len(regions) >= MIN_EXEC)
chk_heap("HEAP_EXEC", regions)
# try invalid param
diff --git a/tests/ports/esp32/esp32_idf_heap_info.py.exp b/tests/ports/esp32/esp32_idf_heap_info.py.exp
index 2b63bf325..7fc50fc16 100644
--- a/tests/ports/esp32/esp32_idf_heap_info.py.exp
+++ b/tests/ports/esp32/esp32_idf_heap_info.py.exp
@@ -1,5 +1,5 @@
-HEAP_DATA >2: True
+HEAP_DATA >=MIN: True
HEAP_DATA [True, True, True, True]
-HEAP_EXEC >2: True
+HEAP_EXEC >=MIN: True
HEAP_EXEC [True, True, True, True]
[]