Browse Source

esp32: Add support for esp32c6.

This commit adds general support for ESP32-C6 SoCs.

Signed-off-by: Andrew Leech <andrew@alelec.net>
pull/11869/head
Andrew Leech 1 year ago
committed by Damien George
parent
commit
6d799378ba
  1. 2
      README.md
  2. 6
      docs/esp32/quickref.rst
  3. 14
      ports/esp32/boards/deploy_c6.md
  4. 2
      ports/esp32/esp32_common.cmake
  5. 7
      ports/esp32/gccollect.c
  6. 4
      ports/esp32/machine_adc.c
  7. 2
      ports/esp32/machine_adc_block.c
  8. 2
      ports/esp32/machine_bitstream.c
  9. 14
      ports/esp32/machine_hw_spi.c
  10. 2
      ports/esp32/machine_i2c.c
  11. 9
      ports/esp32/machine_pin.c
  12. 30
      ports/esp32/machine_pin.h
  13. 4
      ports/esp32/machine_pwm.c
  14. 1
      ports/esp32/main_esp32c3/CMakeLists.txt
  15. 14
      ports/esp32/main_esp32c6/CMakeLists.txt
  16. 5
      ports/esp32/main_esp32c6/idf_component.yml
  17. 1
      ports/esp32/main_esp32c6/linker.lf
  18. 1
      ports/esp32/modesp32.c
  19. 13
      ports/esp32/modmachine.c
  20. 16
      ports/esp32/mpconfigport.h
  21. 2
      ports/esp32/mphalport.h

2
README.md

@ -108,7 +108,7 @@ track of the code size of the core runtime and VM.
In addition, the following ports are provided in this repository:
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6).
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.

6
docs/esp32/quickref.rst

@ -18,7 +18,7 @@ working with this board it may be useful to get an overview of the microcontroll
general.rst
tutorial/index.rst
Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32S2, ESP32S3 --
Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32C6, ESP32S2, ESP32S3 --
supported by MicroPython, with some differences in functionality between them.
Installing MicroPython
@ -61,13 +61,13 @@ The :mod:`esp32` module::
import esp32
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3
esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3/C6
Note that the temperature sensor in the ESP32 will typically read higher than
ambient due to the IC getting warm while it runs. This effect can be minimised
by reading the temperature sensor immediately after waking up from sleep.
ESP32C3, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
ESP32C3, ESP32C6, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
It is implemented a bit differently to the ESP32 and returns the temperature in
Celsius::

14
ports/esp32/boards/deploy_c6.md

@ -0,0 +1,14 @@
Program your board using the esptool.py program, found [here](https://github.com/espressif/esptool).
If you are putting MicroPython on your board for the first time then you should
first erase the entire flash using:
```bash
esptool.py --chip esp32c6 --port /dev/ttyUSB0 erase_flash
```
From then on program the firmware starting at address 0x0:
```bash
esptool.py --chip esp32c6 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x0 ESP32_GENERIC_C6-20240602-v1.24.0.bin
```

2
ports/esp32/esp32_common.cmake

@ -198,7 +198,7 @@ idf_component_register(
set(MICROPY_TARGET ${COMPONENT_TARGET})
# Define mpy-cross flags, for use with frozen code.
if(NOT IDF_TARGET STREQUAL "esp32c3")
if(CONFIG_IDF_TARGET_ARCH STREQUAL "xtensa")
set(MICROPY_CROSS_FLAGS -march=xtensawin)
endif()

7
ports/esp32/gccollect.c

@ -35,7 +35,7 @@
#include "py/mpthread.h"
#include "gccollect.h"
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ARCH_XTENSA
#include "xtensa/hal.h"
@ -61,8 +61,7 @@ void gc_collect(void) {
gc_collect_end();
}
#elif CONFIG_IDF_TARGET_ESP32C3
#elif CONFIG_IDF_TARGET_ARCH_RISCV
#include "shared/runtime/gchelper.h"
void gc_collect(void) {
@ -74,6 +73,8 @@ void gc_collect(void) {
gc_collect_end();
}
#else
#error unknown CONFIG_IDF_TARGET_ARCH
#endif
#if MICROPY_GC_SPLIT_HEAP_AUTO

4
ports/esp32/machine_adc.c

@ -44,7 +44,7 @@
#define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_9_10_11
#endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3
#define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_12 \
{ MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(12) },
#else
@ -87,7 +87,7 @@ 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_ESP32C3
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
{{&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},

2
ports/esp32/machine_adc_block.c

@ -35,7 +35,7 @@ machine_adc_block_obj_t madcblock_obj[] = {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
{{&machine_adc_block_type}, ADC_UNIT_1, 12, -1, {0}},
{{&machine_adc_block_type}, ADC_UNIT_2, 12, -1, {0}},
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C6
{{&machine_adc_block_type}, ADC_UNIT_1, 13, -1, {0}},
{{&machine_adc_block_type}, ADC_UNIT_2, 13, -1, {0}},
#endif

2
ports/esp32/machine_bitstream.c

@ -42,7 +42,7 @@
// This is a translation of the cycle counter implementation in ports/stm32/machine_bitstream.c.
static void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) {
uint32_t pin_mask, gpio_reg_set, gpio_reg_clear;
#if !CONFIG_IDF_TARGET_ESP32C3
#if !CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
if (pin >= 32) {
pin_mask = 1 << (pin - 32);
gpio_reg_set = GPIO_OUT1_W1TS_REG;

14
ports/esp32/machine_hw_spi.c

@ -38,10 +38,10 @@
#include "soc/spi_pins.h"
// SPI mappings by device, naming used by IDF old/new
// upython | ESP32 | ESP32S2 | ESP32S3 | ESP32C3
// ----------+-----------+-----------+---------+---------
// SPI(id=1) | HSPI/SPI2 | FSPI/SPI2 | SPI2 | SPI2
// SPI(id=2) | VSPI/SPI3 | HSPI/SPI3 | SPI3 | err
// upython | ESP32 | ESP32S2 | ESP32S3 | ESP32C3 | ESP32C6
// ----------+-----------+-----------+---------+---------+---------
// SPI(id=1) | HSPI/SPI2 | FSPI/SPI2 | SPI2 | SPI2 | SPI2
// SPI(id=2) | VSPI/SPI3 | HSPI/SPI3 | SPI3 | err | err
// Number of available hardware SPI peripherals.
#if SOC_SPI_PERIPH_NUM > 2
@ -251,14 +251,14 @@ static void machine_hw_spi_init_internal(machine_hw_spi_obj_t *self, mp_arg_val_
// Select DMA channel based on the hardware SPI host
int dma_chan = 0;
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
dma_chan = SPI_DMA_CH_AUTO;
#else
#if CONFIG_IDF_TARGET_ESP32
if (self->host == SPI2_HOST) {
dma_chan = 1;
} else {
dma_chan = 2;
}
#else
dma_chan = SPI_DMA_CH_AUTO;
#endif
ret = spi_bus_initialize(self->host, &buscfg, dma_chan);

2
ports/esp32/machine_i2c.c

@ -49,7 +49,7 @@
#endif
#endif
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3
#define I2C_SCLK_FREQ XTAL_CLK_FREQ
#elif CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
#define I2C_SCLK_FREQ APB_CLK_FREQ

9
ports/esp32/machine_pin.c

@ -43,7 +43,7 @@
#include "modesp32.h"
#include "genhdr/pins.h"
#if CONFIG_IDF_TARGET_ESP32C3
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
#include "soc/usb_serial_jtag_reg.h"
#endif
@ -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
#if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
rtc_gpio_deinit(index);
#endif
}
@ -163,6 +163,11 @@ static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
}
#endif
#if CONFIG_IDF_TARGET_ESP32C6 && CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
if (index == 12 || index == 13) {
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
}
#endif
// configure the pin for gpio
esp_rom_gpio_pad_select_gpio(index);

30
ports/esp32/machine_pin.h

@ -94,6 +94,36 @@
#define MICROPY_HW_ENABLE_GPIO20 (1)
#define MICROPY_HW_ENABLE_GPIO21 (1)
#elif CONFIG_IDF_TARGET_ESP32C6
#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_GPIO11 (1)
#if !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
#define MICROPY_HW_ENABLE_GPIO12 (1)
#define MICROPY_HW_ENABLE_GPIO13 (1)
#endif
#define MICROPY_HW_ENABLE_GPIO14 (1)
#define MICROPY_HW_ENABLE_GPIO15 (1)
#define MICROPY_HW_ENABLE_GPIO16 (1)
#define MICROPY_HW_ENABLE_GPIO17 (1)
#define MICROPY_HW_ENABLE_GPIO18 (1)
#define MICROPY_HW_ENABLE_GPIO19 (1)
#define MICROPY_HW_ENABLE_GPIO20 (1)
#define MICROPY_HW_ENABLE_GPIO21 (1)
#define MICROPY_HW_ENABLE_GPIO22 (1)
#define MICROPY_HW_ENABLE_GPIO23 (1)
// GPIO 24-30 are used for spi/sip flash.
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define MICROPY_HW_ENABLE_GPIO0 (1)

4
ports/esp32/machine_pwm.c

@ -241,7 +241,11 @@ static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
// Configure the new resolution and frequency
timer->duty_resolution = res;
timer->freq_hz = freq;
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
timer->clk_cfg = LEDC_USE_XTAL_CLK;
#else
timer->clk_cfg = LEDC_USE_APB_CLK;
#endif
#if SOC_LEDC_SUPPORT_REF_TICK
if (freq < EMPIRIC_FREQ) {
timer->clk_cfg = LEDC_USE_REF_TICK;

1
ports/esp32/main_esp32c3/CMakeLists.txt

@ -9,5 +9,6 @@ if(NOT MICROPY_PORT_DIR)
endif()
list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
list(APPEND IDF_COMPONENTS riscv)
include(${MICROPY_PORT_DIR}/esp32_common.cmake)

14
ports/esp32/main_esp32c6/CMakeLists.txt

@ -0,0 +1,14 @@
# Set location of base MicroPython directory.
if(NOT MICROPY_DIR)
get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
endif()
# Set location of the ESP32 port directory.
if(NOT MICROPY_PORT_DIR)
get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
endif()
list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
list(APPEND IDF_COMPONENTS riscv)
include(${MICROPY_PORT_DIR}/esp32_common.cmake)

5
ports/esp32/main_esp32c6/idf_component.yml

@ -0,0 +1,5 @@
## IDF Component Manager Manifest File
dependencies:
espressif/mdns: "~1.1.0"
idf:
version: ">=5.1.0"

1
ports/esp32/main_esp32c6/linker.lf

@ -0,0 +1 @@
# Empty linker fragment (no workaround required for C6, see main_esp32/linker.lf).

1
ports/esp32/modesp32.c

@ -29,7 +29,6 @@
#include <time.h>
#include <sys/time.h>
#include "soc/rtc_cntl_reg.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_heap_caps.h"

13
ports/esp32/modmachine.c

@ -90,9 +90,8 @@ typedef enum {
static bool is_soft_reset = 0;
#if CONFIG_IDF_TARGET_ESP32C3
int esp_clk_cpu_freq(void);
#endif
// Note: this is from a private IDF header
extern int esp_clk_cpu_freq(void);
static mp_obj_t mp_machine_get_freq(void) {
return mp_obj_new_int(esp_rom_get_cpu_ticks_per_us() * 1000000);
@ -101,11 +100,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 (freq != 20 && freq != 40 && freq != 80 && freq != 160
#if !CONFIG_IDF_TARGET_ESP32C3
#if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
&& freq != 240
#endif
) {
#if CONFIG_IDF_TARGET_ESP32C3
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz or 160MHz"));
#else
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
@ -118,6 +117,8 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
esp_pm_config_esp32_t pm;
#elif CONFIG_IDF_TARGET_ESP32C3
esp_pm_config_esp32c3_t pm;
#elif CONFIG_IDF_TARGET_ESP32C6
esp_pm_config_esp32c6_t pm;
#elif CONFIG_IDF_TARGET_ESP32S2
esp_pm_config_esp32s2_t pm;
#elif CONFIG_IDF_TARGET_ESP32S3
@ -146,7 +147,7 @@ static void machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_
esp_sleep_enable_timer_wakeup(((uint64_t)expiry) * 1000);
}
#if !CONFIG_IDF_TARGET_ESP32C3
#if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
if (machine_rtc_config.ext0_pin != -1 && (machine_rtc_config.ext0_wake_types & wake_type)) {
esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0);

16
ports/esp32/mpconfigport.h

@ -18,7 +18,7 @@
// object representation and NLR handling
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
#if !CONFIG_IDF_TARGET_ESP32C3
#if CONFIG_IDF_TARGET_ARCH_XTENSA
#define MICROPY_NLR_SETJMP (1)
#endif
@ -41,10 +41,10 @@
// emitters
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#if !CONFIG_IDF_TARGET_ESP32C3
#define MICROPY_EMIT_XTENSAWIN (1)
#else
#if CONFIG_IDF_TARGET_ARCH_RISCV
#define MICROPY_EMIT_RV32 (1)
#else
#define MICROPY_EMIT_XTENSAWIN (1)
#endif
// optimisations
@ -161,6 +161,8 @@
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s3"
#elif CONFIG_IDF_TARGET_ESP32C3
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c3"
#elif CONFIG_IDF_TARGET_ESP32C6
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c6"
#endif
#endif
#define MICROPY_PY_NETWORK_INCLUDEFILE "ports/esp32/modnetwork.h"
@ -364,11 +366,7 @@ void boardctrl_startup(void);
#if MICROPY_PY_NETWORK_LAN && CONFIG_ETH_USE_SPI_ETHERNET
#ifndef MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (12)
#else
#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (36)
#endif
#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (20)
#endif
#endif

2
ports/esp32/mphalport.h

@ -73,7 +73,7 @@ void check_esp_err_(esp_err_t code, const char *func, const int line, const char
uint32_t mp_hal_ticks_us(void);
__attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
uint32_t ccount;
#if CONFIG_IDF_TARGET_ESP32C3
#if CONFIG_IDF_TARGET_ARCH_RISCV
__asm__ __volatile__ ("csrr %0, 0x7E2" : "=r" (ccount)); // Machine Performance Counter Value
#else
__asm__ __volatile__ ("rsr %0,ccount" : "=a" (ccount));

Loading…
Cancel
Save