Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ jobs:
make esp32
make ESP32_CHIP=esp32c3 esp32
make ESP32_CHIP=esp32c6 esp32
make ESP32_CHIP=esp32h2 esp32
make ESP32_CHIP=esp32p4 esp32
make ESP32_CHIP=esp32s2 esp32
make ESP32_CHIP=esp32s3 esp32
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ esp32c3:
esp32c6:
$(MAKE) IDF_TARGET=esp32c6 ESP32_CHIP=esp32c6 esp32

.PHONY: esp32h2
esp32h2:
$(MAKE) IDF_TARGET=esp32h2 ESP32_CHIP=esp32h2 esp32

.PHONY: esp32p4
esp32p4:
$(MAKE) IDF_TARGET=esp32p4 ESP32_CHIP=esp32p4 esp32
Expand Down
8 changes: 6 additions & 2 deletions lib/esp32/esp32.toit
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the lib/LICENSE file.

import system.trace show send-trace-message
import system show architecture ARCHITECTURE-ESP32H2
import system.storage // For toitdoc.

/**
Expand Down Expand Up @@ -172,6 +173,7 @@ The following GPIO pins can be used:
- ESP32: 0, 2, 4, 12-15, 25-27, 32-39
- ESP32-S2: 0-21
- ESP32-S3: 0-21
- ESP32-H2: 7-14

Support for the ESP32-C3 is not yet implemented.

Expand Down Expand Up @@ -229,16 +231,18 @@ set-real-time-clock time/Time -> none:
set-real-time-clock_ seconds/int ns/int -> none:
#primitive.core.set-real-time-clock

/** The WiFi MAC address of the ESP32. */
/** The base MAC address of the ESP32. */
mac-address -> ByteArray:
#primitive.esp32.get-mac-address

/**
Size of the user accessible RTC memory.

The ESP32-H2 provides 3840 bytes; other ESP32 variants provide 4096 bytes.

Deprecated.
*/
RTC-MEMORY-SIZE ::= 4096
RTC-MEMORY-SIZE ::= architecture == ARCHITECTURE-ESP32H2 ? 3840 : 4096

/**
Constructs a $ByteArray backed by the RTC user data.
Expand Down
4 changes: 4 additions & 0 deletions lib/gpio/adc.toit
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ Pin 5 is an ADC pin of channel 2. However, the controller of ADC channel 2
ADC1: Pins 0-6
No ADC2.

## ESP32H2
ADC1: Pins 1-5
No ADC2.

## ESP32P4
ADC1: Pins 16-23, 49-54

Expand Down
10 changes: 10 additions & 0 deletions lib/gpio/gpio.toit
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ Pins 0-7 are RTC pins and can be used in deep-sleep.
For chip variants without an in-package flash, GPIO14 is not led out to any
chip pins.

# ESP32H2
The ESP32H2 has GPIO numbers 0-27.
Pins 6-7 and 15-21 are not exposed on variants with in-package flash.
Pins 15-21 are reserved for flash.
Pins 2, 3, 8, 9, and 25 are strapping pins.
Pins 26-27 are used by USB Serial/JTAG.
Pins 1-5 are ADC pins of channel 1.
Pins 7-14 are RTC pins and can be used in deep sleep.
Pins 13-14 may be connected to a board's 32 kHz crystal.

# ESP32P4
The ESP32P4 has 55 physical pins (0-54). Each pin can be used as
a general-purpose pin, or be connected to a peripheral.
Expand Down
2 changes: 1 addition & 1 deletion lib/i2s.toit
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The channels on the peripheral are not independent. It's not possible to have tw
simplex channels on the same peripheral.

# Other ESP32 variants
The ESP32C3, and ESP32C6 have one I2S peripheral. There are no restrictions on
The ESP32C3, ESP32C6, and ESP32H2 have one I2S peripheral. There are no restrictions on
which pins can be used for the master clock. The master clock can be used as
input or output.

Expand Down
1 change: 1 addition & 0 deletions lib/pulse_counter.toit
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Each unit has two channels that can be configured independently. They share the
The ESP32 has 8 units.
The ESP32C3 has no pulse counter.
The ESP32C6 has 4 units.
The ESP32H2 has 4 units.
The ESP32S2 has 4 units.
The ESP32S3 has 4 units.

Expand Down
10 changes: 5 additions & 5 deletions lib/rmt.toit
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ $Signals represent a collection of signals to be sent by the RMT controller.
# Hardware differences

The ESP32 has 8 RMT channels, each of which can be configured for input or output.
The ESP32C3 and ESP32C6 each have 2 TX and 2 RX channels.
The ESP32C3, ESP32C6, and ESP32H2 each have 2 TX and 2 RX channels.
The ESP32P4, ESP32S2 and ESP32S3 each have 4 TX and 4 RX channels.

The number of bytes per memory block is 256 on the ESP32 and ESP32S2. It is
192 on the ESP32C3, ESP32C6, ESP32P4, and ESP32S3.
192 on the ESP32C3, ESP32C6, ESP32H2, ESP32P4, and ESP32S3.

RMT DMA is available on the ESP32P4 and ESP32S3. DMA-capable channels consume
an internal DMA channel and internal RAM, so DMA is disabled by default.
Expand Down Expand Up @@ -700,7 +700,7 @@ class Channel:
The number of bytes per memory block.

On the ESP32 and ESP32S2 it is 256.
On the ESP32C3, ESP32C6, ESP32P4, and ESP32S3 it is 192.
On the ESP32C3, ESP32C6, ESP32H2, ESP32P4, and ESP32S3 it is 192.
*/
BYTES-PER-MEMORY-BLOCK/int ::= rmt-bytes-per-memory-block_

Expand Down Expand Up @@ -983,7 +983,7 @@ class Out extends Channel_:

The $loop-count parameter specifies how many times the signals are repeated. If it is
set to -1, the signals are repeated indefinitely. The ESP32 only supports -1 (infinite)
and 1. Other variants, like the ESP32C3, ESP32C6, ESP32P4, ESP32S2, and ESP32S3, support
and 1. Other variants, like the ESP32C3, ESP32C6, ESP32H2, ESP32P4, ESP32S2, and ESP32S3, support
other positive values.

The $done-level parameter specifies the level of the pin when the transmission is done.
Expand Down Expand Up @@ -1133,7 +1133,7 @@ class ChannelInOut:
/**
Synchronizes the output of multiple $Out channels.

Not all hardware supports this feature. The ESP32 does not, but the ESP32C3, ESP32C6,
Not all hardware supports this feature. The ESP32 does not, but the ESP32C3, ESP32C6, ESP32H2,
ESP32P4, ESP32S2, and ESP32S3 do.
*/
class SynchronizationManager:
Expand Down
3 changes: 3 additions & 0 deletions lib/system/system.toit
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ ARCHITECTURE-ESP32C3 ::= "esp32c3"
/** Return value from $architecture. */
ARCHITECTURE-ESP32C6 ::= "esp32c6"

/** Return value from $architecture. */
ARCHITECTURE-ESP32H2 ::= "esp32h2"

/** Return value from $architecture. */
ARCHITECTURE-ESP32P4 ::= "esp32p4"

Expand Down
6 changes: 6 additions & 0 deletions src/os_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#include <esp32c3/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32C6
#include <esp32c6/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32H2
#include <esp32h2/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32P4
#include <esp32p4/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32S2
Expand Down Expand Up @@ -452,6 +454,8 @@ void OS::set_up() {
const char* chip_name = "ESP32C3";
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
const char* chip_name = "ESP32C6";
#elif defined(CONFIG_IDF_TARGET_ESP32H2)
const char* chip_name = "ESP32H2";
#elif defined(CONFIG_IDF_TARGET_ESP32P4)
const char* chip_name = "ESP32P4";
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
Expand Down Expand Up @@ -588,6 +592,8 @@ const char* OS::get_architecture() {
return "esp32c3";
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
return "esp32c6";
#elif defined(CONFIG_IDF_TARGET_ESP32H2)
return "esp32h2";
#elif defined(CONFIG_IDF_TARGET_ESP32P4)
return "esp32p4";
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
Expand Down
12 changes: 10 additions & 2 deletions src/primitive_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#include <esp32c3/rom/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32C6
#include <esp32c6/rom/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32H2
#include <esp32h2/rom/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32P4
#include <esp32p4/rom/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32S2
Expand Down Expand Up @@ -353,7 +355,12 @@ PRIMITIVE(total_deep_sleep_time) {
PRIMITIVE(enable_external_wakeup) {
#if SOC_PM_SUPPORT_EXT1_WAKEUP
ARGS(int64, pin_mask, bool, on_any_high);
esp_err_t err = esp_sleep_enable_ext1_wakeup(pin_mask, on_any_high ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW);
#if CONFIG_IDF_TARGET_ESP32
auto low_mode = ESP_EXT1_WAKEUP_ALL_LOW;
#else
auto low_mode = ESP_EXT1_WAKEUP_ANY_LOW;
#endif
esp_err_t err = esp_sleep_enable_ext1_wakeup(pin_mask, on_any_high ? ESP_EXT1_WAKEUP_ANY_HIGH : low_mode);
if (err != ESP_OK) {
ESP_LOGE("Toit", "Failed: sleep_enable_ext1_wakeup");
FAIL(ERROR);
Expand Down Expand Up @@ -419,7 +426,8 @@ PRIMITIVE(get_mac_address) {
if (result == null) FAIL(ALLOCATION_FAILED);

ByteArray::Bytes bytes = ByteArray::Bytes(result);
esp_err_t err = esp_efuse_mac_get_default(bytes.address());
// The efuse-default API writes an eight-byte EUI-64 on IEEE 802.15.4 chips.
esp_err_t err = esp_read_mac(bytes.address(), ESP_MAC_BASE);
if (err != ESP_OK) memset(bytes.address(), 0, 6);

return result;
Expand Down
15 changes: 15 additions & 0 deletions src/resources/adc_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ static int get_adc1_channel(int pin) {
}
}

#elif CONFIG_IDF_TARGET_ESP32H2

#define ADC_CLK_SRC_DEFAULT ADC_DIGI_CLK_SRC_DEFAULT

static int get_adc1_channel(int pin) {
switch (pin) {
case 1: return ADC_CHANNEL_0;
case 2: return ADC_CHANNEL_1;
case 3: return ADC_CHANNEL_2;
case 4: return ADC_CHANNEL_3;
case 5: return ADC_CHANNEL_4;
default: return -1;
}
}

#elif CONFIG_IDF_TARGET_ESP32P4

#define ADC_CLK_SRC_DEFAULT ADC_RTC_CLK_SRC_DEFAULT
Expand Down
8 changes: 8 additions & 0 deletions src/resources/gpio_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GPIO summary:
- Esp32: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/gpio.html
- Esp32c3: https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/peripherals/gpio.html
- Esp32c6: https://docs.espressif.com/projects/esp-idf/en/stable/esp32c6/api-reference/peripherals/gpio.html
- Esp32h2: https://docs.espressif.com/projects/esp-idf/en/stable/esp32h2/api-reference/peripherals/gpio.html
- Esp32p4: https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/gpio.html
- Esp32s2: https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-reference/peripherals/gpio.html
- Esp32s3: https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html
Expand All @@ -61,6 +62,8 @@ static ResourcePool<int, -1> gpio_pins(
20, 21
#elif CONFIG_IDF_TARGET_ESP32C6
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
#elif CONFIG_IDF_TARGET_ESP32H2
20, 21, 22, 23, 24, 25, 26, 27
#elif CONFIG_IDF_TARGET_ESP32P4
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
Expand Down Expand Up @@ -94,6 +97,11 @@ static bool is_restricted_pin(int num) {
// Pins 24-30 are used for flash and PSRAM.
return 24 <= num && num <= 30;
}
#elif CONFIG_IDF_TARGET_ESP32H2
static bool is_restricted_pin(int num) {
// GPIOs 6-7 and 15-21 are not available outside the SiP package.
return (6 <= num && num <= 7) || (15 <= num && num <= 21);
}
#elif CONFIG_IDF_TARGET_ESP32P4
static bool is_restricted_pin(int num) {
// TODO(floitsch): are there restricted pins on the P4?
Expand Down
36 changes: 28 additions & 8 deletions src/resources/pwm_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,30 +76,35 @@ const ledc_clk_cfg_t kDefaultClk = LEDC_USE_RC_FAST_CLK;
class PwmResource : public Resource {
public:
TAG(PwmResource);
PwmResource(ResourceGroup* group, ledc_channel_t channel, gpio_num_t num, bool owns_pin)
PwmResource(ResourceGroup* group, ledc_channel_t channel, gpio_num_t num, bool owns_pin, bool full_duty)
: Resource(group)
, channel_(channel)
, num_(num)
, owns_pin_(owns_pin) {}
, owns_pin_(owns_pin)
, full_duty_(full_duty) {}

ledc_channel_t channel() const { return channel_; }
gpio_num_t num() const { return num_; }
// Whether this channel reserved its pin and must release it.
bool owns_pin() const { return owns_pin_; }
bool full_duty() const { return full_duty_; }
void set_full_duty(bool value) { full_duty_ = value; }

private:
ledc_channel_t channel_;
gpio_num_t num_;
bool owns_pin_;
bool full_duty_;
};

class PwmResourceGroup : public ResourceGroup {
public:
TAG(PwmResourceGroup);
PwmResourceGroup(Process* process, ledc_timer_t timer, uint32 max_value)
PwmResourceGroup(Process* process, ledc_timer_t timer, uint32 max_value, int max_frequency)
: ResourceGroup(process)
, timer_(timer)
, max_value_(max_value) {}
, max_value_(max_value)
, max_frequency_(max_frequency) {}

~PwmResourceGroup() {
ledc_timer_rst(SPEED_MODE, timer_);
Expand All @@ -108,6 +113,7 @@ class PwmResourceGroup : public ResourceGroup {

ledc_timer_t timer() { return timer_; }
uint32 max_value() { return max_value_; }
int max_frequency() { return max_frequency_; }

protected:
virtual void on_unregister_resource(Resource* r) {
Expand All @@ -132,6 +138,7 @@ class PwmResourceGroup : public ResourceGroup {
private:
ledc_timer_t timer_;
uint32 max_value_;
int max_frequency_;
};

MODULE_IMPLEMENTATION(pwm, MODULE_PWM)
Expand Down Expand Up @@ -183,7 +190,7 @@ PRIMITIVE(init) {
return Primitive::os_error(err, process);
}

PwmResourceGroup* gpio = _new PwmResourceGroup(process, timer, (1 << resolution_bits) - 1);
PwmResourceGroup* gpio = _new PwmResourceGroup(process, timer, (1 << resolution_bits) - 1, max_frequency);
if (!gpio) {
ledc_timer_rst(SPEED_MODE, timer);
ledc_timers.put(timer);
Expand Down Expand Up @@ -240,12 +247,18 @@ PRIMITIVE(start) {
},
};
esp_err_t err = ledc_channel_config(&config);
if (err == ESP_OK && factor >= 1.0) {
// The largest duty counter value still leaves a one-tick low pulse.
// Force the idle level instead; this also works at maximum resolution,
// where programming 2^resolution as the duty would overflow the counter.
err = ledc_stop(SPEED_MODE, channel, 1);
}
if (err != ESP_OK) {
ledc_channels.put(channel);
return Primitive::os_error(err, process);
}

PwmResource* pwm = _new PwmResource(resource_group, channel, static_cast<gpio_num_t>(pin_num), owns_pin);
PwmResource* pwm = _new PwmResource(resource_group, channel, static_cast<gpio_num_t>(pin_num), owns_pin, factor >= 1.0);
if (!pwm) {
ledc_stop(SPEED_MODE, channel, 0);
ledc_channels.put(channel);
Expand All @@ -266,6 +279,9 @@ PRIMITIVE(start) {
PRIMITIVE(factor) {
ARGS(PwmResourceGroup, resource_group, PwmResource, resource);

// A stopped idle-high channel does not advance its duty counter.
if (resource->full_duty()) return Primitive::allocate_double(1.0, process);

uint32 duty = ledc_get_duty(SPEED_MODE, resource->channel());
if (duty == LEDC_ERR_DUTY) {
return Primitive::os_error(LEDC_ERR_DUTY, process);
Expand All @@ -283,11 +299,15 @@ PRIMITIVE(set_factor) {
return Primitive::os_error(err, process);
}

err = ledc_update_duty(SPEED_MODE, resource->channel());
// Updating a duty below 100% re-enables a channel stopped at idle-high.
err = factor >= 1.0
? ledc_stop(SPEED_MODE, resource->channel(), 1)
: ledc_update_duty(SPEED_MODE, resource->channel());
if (err != ESP_OK) {
return Primitive::os_error(err, process);
}

resource->set_full_duty(factor >= 1.0);
return process->null_object();
}

Expand All @@ -303,7 +323,7 @@ PRIMITIVE(frequency) {
PRIMITIVE(set_frequency) {
ARGS(PwmResourceGroup, resource_group, int, frequency);

if (frequency <= 0 || frequency > resource_group->max_value()) FAIL(OUT_OF_BOUNDS);
if (frequency <= 0 || frequency > resource_group->max_frequency()) FAIL(OUT_OF_BOUNDS);

esp_err_t err = ledc_set_freq(SPEED_MODE, resource_group->timer(), static_cast<uint32>(frequency));
if (err != ESP_OK) {
Expand Down
3 changes: 3 additions & 0 deletions src/rtc_memory_esp32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#elif CONFIG_IDF_TARGET_ESP32C6
#include <esp32c6/rom/ets_sys.h>
#include <esp32c6/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32H2
#include <esp32h2/rom/ets_sys.h>
#include <esp32h2/rtc.h>
#elif CONFIG_IDF_TARGET_ESP32P4
#include <esp32p4/rom/ets_sys.h>
#include <esp32p4/rtc.h>
Expand Down
Loading
Loading