This commit is contained in:
VojtechBartoska
2021-11-04 16:59:11 +01:00
1765 changed files with 112736 additions and 54960 deletions

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ boards.sloeber.txt
# Ignore docs build (Sphinx)
docs/build
docs/source/_build

View File

@ -7,6 +7,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-i2c-slave.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
@ -54,6 +55,7 @@ set(LIBRARY_SRCS
libraries/DNSServer/src/DNSServer.cpp
libraries/EEPROM/src/EEPROM.cpp
libraries/ESPmDNS/src/ESPmDNS.cpp
libraries/Ethernet/src/ETH.cpp
libraries/FFat/src/FFat.cpp
libraries/FS/src/FS.cpp
libraries/FS/src/vfs_api.cpp
@ -90,7 +92,6 @@ set(LIBRARY_SRCS
libraries/WebServer/src/detail/mimetable.cpp
libraries/WiFiClientSecure/src/ssl_client.cpp
libraries/WiFiClientSecure/src/WiFiClientSecure.cpp
libraries/WiFi/src/ETH.cpp
libraries/WiFi/src/WiFiAP.cpp
libraries/WiFi/src/WiFiClient.cpp
libraries/WiFi/src/WiFi.cpp
@ -174,7 +175,7 @@ set(includedirs
set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
set(priv_includes cores/esp32/libb64)
set(requires spi_flash mbedtls mdns esp_adc_cal wifi_provisioning nghttp)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt esp_ipc)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt esp_ipc esp_hid)
idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})

View File

@ -2064,6 +2064,122 @@ ttgo-t7-v14-mini32.menu.DebugLevel.verbose.build.code_debug=5
##############################################################
ttgo-t-oi-plus.name=TTGO T-OI PLUS RISC-V ESP32-C3
ttgo-t-oi-plus.upload.tool=esptool_py
ttgo-t-oi-plus.upload.maximum_size=1310720
ttgo-t-oi-plus.upload.maximum_data_size=327680
ttgo-t-oi-plus.upload.flags=
ttgo-t-oi-plus.upload.extra_flags=
ttgo-t-oi-plus.serial.disableDTR=false
ttgo-t-oi-plus.serial.disableRTS=false
ttgo-t-oi-plus.build.tarch=riscv32
ttgo-t-oi-plus.build.target=esp
ttgo-t-oi-plus.build.mcu=esp32c3
ttgo-t-oi-plus.build.core=esp32
ttgo-t-oi-plus.build.variant=ttgo-t-oi-plus
ttgo-t-oi-plus.build.board=TTGO-T-OI-PLUS_DEV
ttgo-t-oi-plus.build.bootloader_addr=0x0
ttgo-t-oi-plus.build.cdc_on_boot=0
ttgo-t-oi-plus.build.f_cpu=160000000L
ttgo-t-oi-plus.build.flash_size=4MB
ttgo-t-oi-plus.build.flash_freq=80m
ttgo-t-oi-plus.build.flash_mode=qio
ttgo-t-oi-plus.build.boot=qio
ttgo-t-oi-plus.build.partitions=default
ttgo-t-oi-plus.build.defines=
ttgo-t-oi-plus.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.default.build.partitions=default
ttgo-t-oi-plus.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
ttgo-t-oi-plus.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
ttgo-t-oi-plus.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.minimal.build.partitions=minimal
ttgo-t-oi-plus.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.no_ota.build.partitions=no_ota
ttgo-t-oi-plus.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
ttgo-t-oi-plus.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
ttgo-t-oi-plus.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
ttgo-t-oi-plus.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
ttgo-t-oi-plus.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
ttgo-t-oi-plus.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
ttgo-t-oi-plus.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
ttgo-t-oi-plus.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
ttgo-t-oi-plus.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
ttgo-t-oi-plus.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.huge_app.build.partitions=huge_app
ttgo-t-oi-plus.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
ttgo-t-oi-plus.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
ttgo-t-oi-plus.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
ttgo-t-oi-plus.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
ttgo-t-oi-plus.menu.CPUFreq.160=160MHz (WiFi)
ttgo-t-oi-plus.menu.CPUFreq.160.build.f_cpu=160000000L
ttgo-t-oi-plus.menu.CPUFreq.80=80MHz (WiFi)
ttgo-t-oi-plus.menu.CPUFreq.80.build.f_cpu=80000000L
ttgo-t-oi-plus.menu.CPUFreq.40=40MHz
ttgo-t-oi-plus.menu.CPUFreq.40.build.f_cpu=40000000L
ttgo-t-oi-plus.menu.CPUFreq.20=20MHz
ttgo-t-oi-plus.menu.CPUFreq.20.build.f_cpu=20000000L
ttgo-t-oi-plus.menu.CPUFreq.10=10MHz
ttgo-t-oi-plus.menu.CPUFreq.10.build.f_cpu=10000000L
ttgo-t-oi-plus.menu.FlashMode.qio=QIO
ttgo-t-oi-plus.menu.FlashMode.qio.build.flash_mode=dio
ttgo-t-oi-plus.menu.FlashMode.qio.build.boot=qio
ttgo-t-oi-plus.menu.FlashMode.dio=DIO
ttgo-t-oi-plus.menu.FlashMode.dio.build.flash_mode=dio
ttgo-t-oi-plus.menu.FlashMode.dio.build.boot=dio
ttgo-t-oi-plus.menu.FlashMode.qout=QOUT
ttgo-t-oi-plus.menu.FlashMode.qout.build.flash_mode=dout
ttgo-t-oi-plus.menu.FlashMode.qout.build.boot=qout
ttgo-t-oi-plus.menu.FlashMode.dout=DOUT
ttgo-t-oi-plus.menu.FlashMode.dout.build.flash_mode=dout
ttgo-t-oi-plus.menu.FlashMode.dout.build.boot=dout
ttgo-t-oi-plus.menu.FlashFreq.80=80MHz
ttgo-t-oi-plus.menu.FlashFreq.80.build.flash_freq=80m
ttgo-t-oi-plus.menu.FlashFreq.40=40MHz
ttgo-t-oi-plus.menu.FlashFreq.40.build.flash_freq=40m
ttgo-t-oi-plus.menu.FlashSize.4M=4MB (32Mb)
ttgo-t-oi-plus.menu.FlashSize.4M.build.flash_size=4MB
ttgo-t-oi-plus.menu.UploadSpeed.921600=921600
ttgo-t-oi-plus.menu.UploadSpeed.921600.upload.speed=921600
ttgo-t-oi-plus.menu.UploadSpeed.115200=115200
ttgo-t-oi-plus.menu.UploadSpeed.115200.upload.speed=115200
ttgo-t-oi-plus.menu.UploadSpeed.256000.windows=256000
ttgo-t-oi-plus.menu.UploadSpeed.256000.upload.speed=256000
ttgo-t-oi-plus.menu.UploadSpeed.230400.windows.upload.speed=256000
ttgo-t-oi-plus.menu.UploadSpeed.230400=230400
ttgo-t-oi-plus.menu.UploadSpeed.230400.upload.speed=230400
ttgo-t-oi-plus.menu.UploadSpeed.460800.linux=460800
ttgo-t-oi-plus.menu.UploadSpeed.460800.macosx=460800
ttgo-t-oi-plus.menu.UploadSpeed.460800.upload.speed=460800
ttgo-t-oi-plus.menu.UploadSpeed.512000.windows=512000
ttgo-t-oi-plus.menu.UploadSpeed.512000.upload.speed=512000
ttgo-t-oi-plus.menu.DebugLevel.none=None
ttgo-t-oi-plus.menu.DebugLevel.none.build.code_debug=0
ttgo-t-oi-plus.menu.DebugLevel.error=Error
ttgo-t-oi-plus.menu.DebugLevel.error.build.code_debug=1
ttgo-t-oi-plus.menu.DebugLevel.warn=Warn
ttgo-t-oi-plus.menu.DebugLevel.warn.build.code_debug=2
ttgo-t-oi-plus.menu.DebugLevel.info=Info
ttgo-t-oi-plus.menu.DebugLevel.info.build.code_debug=3
ttgo-t-oi-plus.menu.DebugLevel.debug=Debug
ttgo-t-oi-plus.menu.DebugLevel.debug.build.code_debug=4
ttgo-t-oi-plus.menu.DebugLevel.verbose=Verbose
ttgo-t-oi-plus.menu.DebugLevel.verbose.build.code_debug=5
##############################################################
cw02.name=XinaBox CW02
cw02.upload.tool=esptool_py
@ -3794,6 +3910,13 @@ adafruit_metro_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
adafruit_metro_esp32s2.menu.DFUOnBoot.dfu=Enabled
adafruit_metro_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
adafruit_metro_esp32s2.menu.UploadMode.cdc=Internal USB
adafruit_metro_esp32s2.menu.UploadMode.cdc.upload.use_1200bps_touch=true
adafruit_metro_esp32s2.menu.UploadMode.cdc.upload.wait_for_upload_port=true
adafruit_metro_esp32s2.menu.UploadMode.default=UART0
adafruit_metro_esp32s2.menu.UploadMode.default.upload.use_1200bps_touch=false
adafruit_metro_esp32s2.menu.UploadMode.default.upload.wait_for_upload_port=false
adafruit_metro_esp32s2.menu.PSRAM.enabled=Enabled
adafruit_metro_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
adafruit_metro_esp32s2.menu.PSRAM.disabled=Disabled
@ -3908,11 +4031,11 @@ adafruit_metro_esp32s2.menu.DebugLevel.verbose.build.code_debug=5
adafruit_magtag29_esp32s2.name=Adafruit MagTag 2.9"
adafruit_magtag29_esp32s2.vid.0=0x239A
adafruit_magtag29_esp32s2.pid.0=0x80DF
adafruit_magtag29_esp32s2.pid.0=0x80E5
adafruit_magtag29_esp32s2.vid.1=0x239A
adafruit_magtag29_esp32s2.pid.1=0x00DF
adafruit_magtag29_esp32s2.pid.1=0x00E5
adafruit_magtag29_esp32s2.vid.1=0x239A
adafruit_magtag29_esp32s2.pid.1=0x80E0
adafruit_magtag29_esp32s2.pid.1=0x80E6
adafruit_magtag29_esp32s2.upload.tool=esptool_py
adafruit_magtag29_esp32s2.upload.maximum_size=1310720
@ -3959,6 +4082,13 @@ adafruit_magtag29_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
adafruit_magtag29_esp32s2.menu.DFUOnBoot.dfu=Enabled
adafruit_magtag29_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
adafruit_magtag29_esp32s2.menu.UploadMode.cdc=Internal USB
adafruit_magtag29_esp32s2.menu.UploadMode.cdc.upload.use_1200bps_touch=true
adafruit_magtag29_esp32s2.menu.UploadMode.cdc.upload.wait_for_upload_port=true
adafruit_magtag29_esp32s2.menu.UploadMode.default=UART0
adafruit_magtag29_esp32s2.menu.UploadMode.default.upload.use_1200bps_touch=false
adafruit_magtag29_esp32s2.menu.UploadMode.default.upload.wait_for_upload_port=false
adafruit_magtag29_esp32s2.menu.PSRAM.enabled=Enabled
adafruit_magtag29_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
adafruit_magtag29_esp32s2.menu.PSRAM.disabled=Disabled
@ -4124,6 +4254,13 @@ adafruit_funhouse_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
adafruit_funhouse_esp32s2.menu.DFUOnBoot.dfu=Enabled
adafruit_funhouse_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
adafruit_funhouse_esp32s2.menu.UploadMode.cdc=Internal USB
adafruit_funhouse_esp32s2.menu.UploadMode.cdc.upload.use_1200bps_touch=true
adafruit_funhouse_esp32s2.menu.UploadMode.cdc.upload.wait_for_upload_port=true
adafruit_funhouse_esp32s2.menu.UploadMode.default=UART0
adafruit_funhouse_esp32s2.menu.UploadMode.default.upload.use_1200bps_touch=false
adafruit_funhouse_esp32s2.menu.UploadMode.default.upload.wait_for_upload_port=false
adafruit_funhouse_esp32s2.menu.PSRAM.enabled=Enabled
adafruit_funhouse_esp32s2.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
adafruit_funhouse_esp32s2.menu.PSRAM.disabled=Disabled
@ -4236,7 +4373,7 @@ adafruit_funhouse_esp32s2.menu.DebugLevel.verbose.build.code_debug=5
##############################################################
adafruit_feather_esp32s2_nopsram.name=Adafruit Feather ESP32-S2 (no PSRAM)
adafruit_feather_esp32s2_nopsram.name=Adafruit Feather ESP32-S2
adafruit_feather_esp32s2_nopsram.vid.0=0x239A
adafruit_feather_esp32s2_nopsram.pid.0=0x80EB
adafruit_feather_esp32s2_nopsram.vid.1=0x239A
@ -4261,7 +4398,7 @@ adafruit_feather_esp32s2_nopsram.build.target=esp32s2
adafruit_feather_esp32s2_nopsram.build.mcu=esp32s2
adafruit_feather_esp32s2_nopsram.build.core=esp32
adafruit_feather_esp32s2_nopsram.build.variant=adafruit_feather_esp32s2
adafruit_feather_esp32s2_nopsram.build.board=ADAFRUIT_FEATHER_ESP32S2_NOPSRAM
adafruit_feather_esp32s2_nopsram.build.board=ADAFRUIT_FEATHER_ESP32S2
adafruit_feather_esp32s2_nopsram.build.cdc_on_boot=0
adafruit_feather_esp32s2_nopsram.build.msc_on_boot=0
@ -4289,10 +4426,10 @@ adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.default.build.dfu_on_boot=0
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.dfu=Enabled
adafruit_feather_esp32s2_nopsram.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled=Disabled
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled.build.defines=
adafruit_feather_esp32s2_nopsram.menu.PSRAM.enabled=Enabled
adafruit_feather_esp32s2_nopsram.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled=Disabled
adafruit_feather_esp32s2_nopsram.menu.PSRAM.disabled.build.defines=
adafruit_feather_esp32s2_nopsram.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
adafruit_feather_esp32s2_nopsram.menu.PartitionScheme.default.build.partitions=default
@ -9379,19 +9516,32 @@ atmegazero_esp32s2.build.core=esp32
atmegazero_esp32s2.build.variant=atmegazero_esp32s2
atmegazero_esp32s2.build.board=atmegazero_esp32s2
atmegazero_esp32s2.build.cdc_on_boot=1
atmegazero_esp32s2.build.msc_on_boot=0
atmegazero_esp32s2.build.dfu_on_boot=0
atmegazero_esp32s2.build.serial=0
atmegazero_esp32s2.build.f_cpu=240000000L
atmegazero_esp32s2.build.flash_size=4MB
atmegazero_esp32s2.build.flash_freq=80m
atmegazero_esp32s2.build.flash_size=16MB
atmegazero_esp32s2.build.flash_freq=40m
atmegazero_esp32s2.build.flash_mode=qio
atmegazero_esp32s2.build.boot=qio
atmegazero_esp32s2.build.partitions=default
atmegazero_esp32s2.build.defines=
atmegazero_esp32s2.menu.SerialMode.cdc=USB CDC
atmegazero_esp32s2.menu.SerialMode.cdc.build.serial=1
atmegazero_esp32s2.menu.SerialMode.default=UART0
atmegazero_esp32s2.menu.SerialMode.default.build.serial=0
atmegazero_esp32s2.menu.CDCOnBoot.cdc=Enabled
atmegazero_esp32s2.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
atmegazero_esp32s2.menu.CDCOnBoot.default=Disabled
atmegazero_esp32s2.menu.CDCOnBoot.default.build.cdc_on_boot=0
atmegazero_esp32s2.menu.MSCOnBoot.default=Disabled
atmegazero_esp32s2.menu.MSCOnBoot.default.build.msc_on_boot=0
atmegazero_esp32s2.menu.MSCOnBoot.msc=Enabled
atmegazero_esp32s2.menu.MSCOnBoot.msc.build.msc_on_boot=1
atmegazero_esp32s2.menu.DFUOnBoot.default=Disabled
atmegazero_esp32s2.menu.DFUOnBoot.default.build.dfu_on_boot=0
atmegazero_esp32s2.menu.DFUOnBoot.dfu=Enabled
atmegazero_esp32s2.menu.DFUOnBoot.dfu.build.dfu_on_boot=1
atmegazero_esp32s2.menu.PSRAM.disabled=Disabled
atmegazero_esp32s2.menu.PSRAM.disabled.build.defines=
@ -9537,10 +9687,10 @@ deneyapmini.build.boot=qio
deneyapmini.build.partitions=default
deneyapmini.build.defines=
deneyapmini.menu.SerialMode.default=USB_CDC
deneyapmini.menu.SerialMode.default.build.serial=1
deneyapmini.menu.SerialMode.uart=UART0
deneyapmini.menu.SerialMode.uart.build.serial=0
deneyapmini.menu.CDCOnBoot.default=Disabled
deneyapmini.menu.CDCOnBoot.default.build.cdc_on_boot=0
deneyapmini.menu.CDCOnBoot.cdc=Enabled
deneyapmini.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
deneyapmini.menu.PSRAM.disabled=Disabled
deneyapmini.menu.PSRAM.disabled.build.defines=

View File

@ -38,6 +38,7 @@ extern "C" {
#define ESP_FLASH_IMAGE_BASE 0x1000 // Flash offset containing flash size and spi mode
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#include "soc/efuse_reg.h"
#define ESP_FLASH_IMAGE_BASE 0x1000
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/spi_flash.h"
@ -270,7 +271,17 @@ const char * EspClass::getChipModel(void)
return "Unknown";
}
#elif CONFIG_IDF_TARGET_ESP32S2
return "ESP32-S2";
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
switch (pkg_ver) {
case 0:
return "ESP32-S2";
case 1:
return "ESP32-S2FH16";
case 2:
return "ESP32-S2FH32";
default:
return "ESP32-S2 (Unknown)";
}
#elif CONFIG_IDF_TARGET_ESP32S3
return "ESP32-S3";
#elif CONFIG_IDF_TARGET_ESP32C3

View File

@ -113,6 +113,7 @@ static size_t msc_update_get_required_disk_sectors(){
log_d("USING FAT12");
mcs_is_fat16 = false;
}
log_d("FAT sector size: %u", DISK_SECTOR_SIZE);
log_d("FAT data sectors: %u", data_sectors);
log_d("FAT table sectors: %u", msc_table_sectors);
log_d("FAT total sectors: %u (%uKB)", total_sectors, (total_sectors * DISK_SECTOR_SIZE) / 1024);
@ -227,7 +228,7 @@ static esp_err_t msc_update_write(const esp_partition_t *partition, uint32_t off
//called when error was encountered while updating
static void msc_update_error(){
log_e("UPDATE_ERROR: %u", msc_update_bytes_written);
arduino_firmware_msc_event_data_t p = {0};
arduino_firmware_msc_event_data_t p;
p.error.size = msc_update_bytes_written;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_ERROR_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
msc_update_state = MSC_UPDATE_IDLE;
@ -251,7 +252,7 @@ static void msc_update_end(){
msc_update_error();
return;
}
arduino_firmware_msc_event_data_t p = {0};
arduino_firmware_msc_event_data_t p;
p.end.size = msc_update_entry->file_size;
arduino_usb_event_post(ARDUINO_FIRMWARE_MSC_EVENTS, ARDUINO_FIRMWARE_MSC_END_EVENT, &p, sizeof(arduino_firmware_msc_event_data_t), portMAX_DELAY);
}
@ -289,7 +290,7 @@ static int32_t msc_write(uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_
}
} else if(msc_ota_partition && lba >= msc_update_start_sector){
//handle writes to the region where the new firmware will be uploaded
arduino_firmware_msc_event_data_t p = {0};
arduino_firmware_msc_event_data_t p;
if(msc_update_state <= MSC_UPDATE_STARTING && buffer[0] == 0xE9){
msc_update_state = MSC_UPDATE_RUNNING;
msc_update_start_sector = lba;
@ -345,7 +346,7 @@ static int32_t msc_read(uint32_t lba, uint32_t offset, void* buffer, uint32_t bu
static bool msc_start_stop(uint8_t power_condition, bool start, bool load_eject){
//log_d("power: %u, start: %u, eject: %u", power_condition, start, load_eject);
arduino_firmware_msc_event_data_t p = {0};
arduino_firmware_msc_event_data_t p;
p.power.power_condition = power_condition;
p.power.start = start;
p.power.load_eject = load_eject;

View File

@ -169,7 +169,7 @@ void HWCDC::begin(unsigned long baud)
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
if(!intr_handle && esp_intr_alloc(ETS_USB_INTR_SOURCE/*ETS_USB_SERIAL_JTAG_INTR_SOURCE*/, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK){
if(!intr_handle && esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, hw_cdc_isr_handler, NULL, &intr_handle) != ESP_OK){
isr_log_e("HW USB CDC failed to init interrupts");
end();
return;

View File

@ -87,7 +87,6 @@ HardwareSerial Serial1(1);
#if SOC_UART_NUM > 2
HardwareSerial Serial2(2);
#endif
#endif
void serialEventRun(void)
{
@ -105,6 +104,7 @@ void serialEventRun(void)
if(Serial2.available()) serialEvent2();
#endif
}
#endif
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256) {}

View File

@ -256,7 +256,7 @@ float Stream::parseFloat(char skipChar)
} else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
if(isFraction) {
fraction *= 0.1;
fraction *= 0.1f;
}
}
read(); // consume the character we got with peek

View File

@ -15,6 +15,7 @@
#if CONFIG_TINYUSB_ENABLED
#include "pins_arduino.h"
#include "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "common/tusb_common.h"
@ -85,14 +86,14 @@ static bool tinyusb_device_suspended = false;
// Invoked when device is mounted (configured)
void tud_mount_cb(void){
tinyusb_device_mounted = true;
arduino_usb_event_data_t p = {0};
arduino_usb_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STARTED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
// Invoked when device is unmounted
void tud_umount_cb(void){
tinyusb_device_mounted = false;
arduino_usb_event_data_t p = {0};
arduino_usb_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
@ -100,7 +101,7 @@ void tud_umount_cb(void){
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en){
tinyusb_device_suspended = true;
arduino_usb_event_data_t p = {0};
arduino_usb_event_data_t p;
p.suspend.remote_wakeup_en = remote_wakeup_en;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_SUSPEND_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
@ -108,7 +109,7 @@ void tud_suspend_cb(bool remote_wakeup_en){
// Invoked when usb bus is resumed
void tud_resume_cb(void){
tinyusb_device_suspended = false;
arduino_usb_event_data_t p = {0};
arduino_usb_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}

View File

@ -156,7 +156,7 @@ void USBCDC::_onUnplugged(void){
connected = false;
dtr = false;
rts = false;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
}
@ -178,7 +178,7 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
lineState++;
if(connected){
connected = false;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
} else {
@ -208,14 +208,14 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){
if(lineState == CDC_LINE_IDLE){
if(dtr && rts && !connected){
connected = true;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
} else if(!dtr && connected){
connected = false;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
arduino_usb_cdc_event_data_t l = {0};
arduino_usb_cdc_event_data_t l;
l.line_state.dtr = dtr;
l.line_state.rts = rts;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_STATE_EVENT, &l, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
@ -233,7 +233,7 @@ void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _pari
data_bits = _data_bits;
stop_bits = _stop_bits;
parity = _parity;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
p.line_coding.bit_rate = bit_rate;
p.line_coding.data_bits = data_bits;
p.line_coding.stop_bits = stop_bits;
@ -251,13 +251,13 @@ void USBCDC::_onRX(){
return;
}
}
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
p.rx.len = count;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
void USBCDC::_onTX(){
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_cdc_event_data_t p;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_TX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}

View File

@ -37,7 +37,7 @@ static uint8_t __analogVRefPin = 0;
#include "soc/rtc_io_reg.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#else
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
@ -46,10 +46,23 @@ static uint8_t __analogVRefPin = 0;
#endif
static uint8_t __analogAttenuation = 3;//11db
static uint8_t __analogWidth = 3;//12 bits
static uint8_t __analogWidth = ADC_WIDTH_MAX - 1; //3 for ESP32/ESP32C3; 4 for ESP32S2
static uint8_t __analogReturnedWidth = SOC_ADC_MAX_BITWIDTH; //12 for ESP32/ESP32C3; 13 for ESP32S2
static uint8_t __analogClockDiv = 1;
static adc_attenuation_t __pin_attenuation[SOC_GPIO_PIN_COUNT];
static inline uint16_t mapResolution(uint16_t value)
{
uint8_t from = __analogWidth + 9;
if (from == __analogReturnedWidth) {
return value;
}
if (from > __analogReturnedWidth) {
return value >> (from - __analogReturnedWidth);
}
return value << (__analogReturnedWidth - from);
}
void __analogSetClockDiv(uint8_t clockDiv){
if(!clockDiv){
clockDiv = 1;
@ -146,6 +159,7 @@ void __analogReadResolution(uint8_t bits)
if(!bits || bits > 16){
return;
}
__analogReturnedWidth = bits;
#if CONFIG_IDF_TARGET_ESP32
__analogSetWidth(bits); // hadware from 9 to 12
#endif
@ -165,7 +179,7 @@ uint16_t __analogRead(uint8_t pin)
channel -= 10;
r = adc2_get_raw( channel, __analogWidth, &value);
if ( r == ESP_OK ) {
return value;
return mapResolution(value);
} else if ( r == ESP_ERR_INVALID_STATE ) {
log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r));
} else if ( r == ESP_ERR_TIMEOUT ) {
@ -174,9 +188,10 @@ uint16_t __analogRead(uint8_t pin)
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
}
} else {
return adc1_get_raw(channel);
value = adc1_get_raw(channel);
return mapResolution(value);
}
return value;
return mapResolution(value);
}
uint32_t __analogReadMilliVolts(uint8_t pin){

848
cores/esp32/esp32-hal-i2c-slave.c Executable file
View File

@ -0,0 +1,848 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "rom/gpio.h"
#include "soc/gpio_sig_map.h"
#include "hal/gpio_types.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "esp_intr_alloc.h"
#include "driver/periph_ctrl.h"
#include "soc/i2c_reg.h"
#include "soc/i2c_struct.h"
#include "hal/i2c_ll.h"
#include "esp32-hal-log.h"
#include "esp32-hal-i2c-slave.h"
#define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer
#if SOC_I2C_NUM > 1
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
#define I2C_SDA_IDX(p) ((p==0)?I2CEXT0_SDA_OUT_IDX:((p==1)?I2CEXT1_SDA_OUT_IDX:0))
#else
#define I2C_SCL_IDX(p) I2CEXT0_SCL_OUT_IDX
#define I2C_SDA_IDX(p) I2CEXT0_SDA_OUT_IDX
#endif
#if CONFIG_IDF_TARGET_ESP32
#define I2C_TXFIFO_WM_INT_ENA I2C_TXFIFO_EMPTY_INT_ENA
#define I2C_RXFIFO_WM_INT_ENA I2C_RXFIFO_FULL_INT_ENA
#endif
enum {
I2C_SLAVE_EVT_RX, I2C_SLAVE_EVT_TX
};
typedef struct i2c_slave_struct_t {
i2c_dev_t * dev;
uint8_t num;
int8_t sda;
int8_t scl;
i2c_slave_request_cb_t request_callback;
i2c_slave_receive_cb_t receive_callback;
void * arg;
intr_handle_t intr_handle;
TaskHandle_t task_handle;
xQueueHandle event_queue;
#if I2C_SLAVE_USE_RX_QUEUE
xQueueHandle rx_queue;
#else
RingbufHandle_t rx_ring_buf;
#endif
xQueueHandle tx_queue;
uint32_t rx_data_count;
#if !CONFIG_DISABLE_HAL_LOCKS
xSemaphoreHandle lock;
#endif
} i2c_slave_struct_t;
typedef union {
struct {
uint32_t event : 2;
uint32_t stop : 1;
uint32_t param : 29;
};
uint32_t val;
} i2c_slave_queue_event_t;
static i2c_slave_struct_t _i2c_bus_array[SOC_I2C_NUM] = {
{ &I2C0, 0, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
#if !CONFIG_DISABLE_HAL_LOCKS
, NULL
#endif
},
#if SOC_I2C_NUM > 1
{ &I2C1, 1, -1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
#if !CONFIG_DISABLE_HAL_LOCKS
, NULL
#endif
}
#endif
};
#if CONFIG_DISABLE_HAL_LOCKS
#define I2C_SLAVE_MUTEX_LOCK()
#define I2C_SLAVE_MUTEX_UNLOCK()
#else
#define I2C_SLAVE_MUTEX_LOCK() if(i2c->lock){xSemaphoreTake(i2c->lock, portMAX_DELAY);}
#define I2C_SLAVE_MUTEX_UNLOCK() if(i2c->lock){xSemaphoreGive(i2c->lock);}
#endif
//-------------------------------------- HAL_LL (Missing Functions) ------------------------------------------------
typedef enum {
I2C_STRETCH_CAUSE_MASTER_READ,
I2C_STRETCH_CAUSE_TX_FIFO_EMPTY,
I2C_STRETCH_CAUSE_RX_FIFO_FULL,
I2C_STRETCH_CAUSE_MAX
} i2c_stretch_cause_t;
static inline i2c_stretch_cause_t i2c_ll_stretch_cause(i2c_dev_t *hw)
{
#if CONFIG_IDF_TARGET_ESP32C3
return hw->sr.stretch_cause;
#elif CONFIG_IDF_TARGET_ESP32S2
return hw->status_reg.stretch_cause;
#else
return I2C_STRETCH_CAUSE_MAX;
#endif
}
static inline void i2c_ll_set_stretch(i2c_dev_t *hw, uint16_t time)
{
#ifndef CONFIG_IDF_TARGET_ESP32
typeof(hw->scl_stretch_conf) scl_stretch_conf;
scl_stretch_conf.val = 0;
scl_stretch_conf.slave_scl_stretch_en = (time > 0);
scl_stretch_conf.stretch_protect_num = time;
scl_stretch_conf.slave_scl_stretch_clr = 1;
hw->scl_stretch_conf.val = scl_stretch_conf.val;
if(time > 0){
//enable interrupt
hw->int_ena.val |= I2C_SLAVE_STRETCH_INT_ENA;
} else {
//disable interrupt
hw->int_ena.val &= (~I2C_SLAVE_STRETCH_INT_ENA);
}
#endif
}
static inline void i2c_ll_stretch_clr(i2c_dev_t *hw)
{
#ifndef CONFIG_IDF_TARGET_ESP32
hw->scl_stretch_conf.slave_scl_stretch_clr = 1;
#endif
}
static inline bool i2c_ll_slave_addressed(i2c_dev_t *hw)
{
#if CONFIG_IDF_TARGET_ESP32C3
return hw->sr.slave_addressed;
#else
return hw->status_reg.slave_addressed;
#endif
}
static inline bool i2c_ll_slave_rw(i2c_dev_t *hw)//not exposed by hal_ll
{
#if CONFIG_IDF_TARGET_ESP32C3
return hw->sr.slave_rw;
#else
return hw->status_reg.slave_rw;
#endif
}
//-------------------------------------- PRIVATE (Function Prototypes) ------------------------------------------------
static void i2c_slave_free_resources(i2c_slave_struct_t * i2c);
static void i2c_slave_delay_us(uint64_t us);
static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode);
static bool i2c_slave_check_line_state(int8_t sda, int8_t scl);
static bool i2c_slave_attach_gpio(i2c_slave_struct_t * i2c, int8_t sda, int8_t scl);
static bool i2c_slave_detach_gpio(i2c_slave_struct_t * i2c);
static bool i2c_slave_set_frequency(i2c_slave_struct_t * i2c, uint32_t clk_speed);
static bool i2c_slave_send_event(i2c_slave_struct_t * i2c, i2c_slave_queue_event_t* event);
static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t * i2c);
static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t * i2c, uint32_t len);
static size_t i2c_slave_read_rx(i2c_slave_struct_t * i2c, uint8_t * data, size_t len);
static void i2c_slave_isr_handler(void* arg);
static void i2c_slave_task(void *pv_args);
//=====================================================================================================================
//-------------------------------------- Public Functions -------------------------------------------------------------
//=====================================================================================================================
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg){
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
}
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
I2C_SLAVE_MUTEX_LOCK();
i2c->request_callback = request_callback;
i2c->receive_callback = receive_callback;
i2c->arg = arg;
I2C_SLAVE_MUTEX_UNLOCK();
return ESP_OK;
}
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len) {
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
}
if (sda < 0 || scl < 0) {
log_e("invalid pins sda=%d, scl=%d", sda, scl);
return ESP_ERR_INVALID_ARG;
}
if(!frequency){
frequency = 100000;
} else if(frequency > 1000000){
frequency = 1000000;
}
log_i("Initialising I2C Slave: sda=%d scl=%d freq=%d, addr=0x%x", sda, scl, frequency, slaveID);
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
esp_err_t ret = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
if(!i2c->lock){
i2c->lock = xSemaphoreCreateMutex();
if (i2c->lock == NULL) {
log_e("RX queue create failed");
return ESP_ERR_NO_MEM;
}
}
#endif
I2C_SLAVE_MUTEX_LOCK();
i2c_slave_free_resources(i2c);
#if I2C_SLAVE_USE_RX_QUEUE
i2c->rx_queue = xQueueCreate(rx_len, sizeof(uint8_t));
if (i2c->rx_queue == NULL) {
log_e("RX queue create failed");
ret = ESP_ERR_NO_MEM;
goto fail;
}
#else
i2c->rx_ring_buf = xRingbufferCreate(rx_len, RINGBUF_TYPE_BYTEBUF);
if (i2c->rx_ring_buf == NULL) {
log_e("RX RingBuf create failed");
ret = ESP_ERR_NO_MEM;
goto fail;
}
#endif
i2c->tx_queue = xQueueCreate(tx_len, sizeof(uint8_t));
if (i2c->tx_queue == NULL) {
log_e("TX queue create failed");
ret = ESP_ERR_NO_MEM;
goto fail;
}
i2c->event_queue = xQueueCreate(16, sizeof(i2c_slave_queue_event_t));
if (i2c->event_queue == NULL) {
log_e("Event queue create failed");
ret = ESP_ERR_NO_MEM;
goto fail;
}
xTaskCreate(i2c_slave_task, "i2c_slave_task", 4096, i2c, 20, &i2c->task_handle);
if(i2c->task_handle == NULL){
log_e("Event thread create failed");
ret = ESP_ERR_NO_MEM;
goto fail;
}
if (frequency == 0) {
frequency = 100000L;
}
frequency = (frequency * 5) / 4;
if (i2c->num == 0) {
periph_module_enable(PERIPH_I2C0_MODULE);
#if SOC_I2C_NUM > 1
} else {
periph_module_enable(PERIPH_I2C1_MODULE);
#endif
}
i2c_ll_slave_init(i2c->dev);
i2c_ll_set_fifo_mode(i2c->dev, true);
i2c_ll_set_slave_addr(i2c->dev, slaveID, false);
i2c_ll_set_tout(i2c->dev, 32000);
i2c_slave_set_frequency(i2c, frequency);
if (!i2c_slave_check_line_state(sda, scl)) {
log_e("bad pin state");
ret = ESP_FAIL;
goto fail;
}
i2c_slave_attach_gpio(i2c, sda, scl);
if (i2c_ll_is_bus_busy(i2c->dev)) {
log_w("Bus busy, reinit");
ret = ESP_FAIL;
goto fail;
}
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_clr_intsts_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_set_fifo_mode(i2c->dev, true);
if (!i2c->intr_handle) {
uint32_t flags = ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED;
if(i2c->num == 0) {
ret = esp_intr_alloc(ETS_I2C_EXT0_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#if SOC_I2C_NUM > 1
} else {
ret = esp_intr_alloc(ETS_I2C_EXT1_INTR_SOURCE, flags, &i2c_slave_isr_handler, i2c, &i2c->intr_handle);
#endif
}
if (ret != ESP_OK) {
log_e("install interrupt handler Failed=%d", ret);
goto fail;
}
}
i2c_ll_txfifo_rst(i2c->dev);
i2c_ll_rxfifo_rst(i2c->dev);
i2c_ll_slave_enable_rx_it(i2c->dev);
i2c_ll_set_stretch(i2c->dev, 0x3FF);
i2c_ll_update(i2c->dev);
I2C_SLAVE_MUTEX_UNLOCK();
return ret;
fail:
i2c_slave_free_resources(i2c);
I2C_SLAVE_MUTEX_UNLOCK();
return ret;
}
esp_err_t i2cSlaveDeinit(uint8_t num){
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return ESP_ERR_INVALID_ARG;
}
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
if(!i2c->lock){
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
return ESP_ERR_NO_MEM;
}
I2C_SLAVE_MUTEX_LOCK();
i2c_slave_free_resources(i2c);
I2C_SLAVE_MUTEX_UNLOCK();
return ESP_OK;
}
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms) {
if(num >= SOC_I2C_NUM){
log_e("Invalid port num: %u", num);
return 0;
}
size_t to_queue = 0, to_fifo = 0;
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
if(!i2c->lock){
log_e("Lock is not initialized! Did you call i2c_slave_init()?");
return ESP_ERR_NO_MEM;
}
if(!i2c->tx_queue){
return 0;
}
I2C_SLAVE_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
//make sure that tx is idle
uint64_t tout_at = esp_timer_get_time() + (timeout_ms * 1000);
while(i2c_ll_slave_addressed(i2c->dev) && i2c_ll_slave_rw(i2c->dev)) {
// ongoing MASTER READ
//wait up to timeout_ms for current transaction to finish
vTaskDelay(2);
if((uint64_t)esp_timer_get_time() >= tout_at){
log_e("TX IDLE WAIT TIMEOUT!");
I2C_SLAVE_MUTEX_UNLOCK();
return 0;
}
}
i2c_ll_slave_disable_tx_it(i2c->dev);
if (i2c_ll_get_txfifo_len(i2c->dev) < SOC_I2C_FIFO_LEN) {
i2c_ll_txfifo_rst(i2c->dev);
}
#endif
to_fifo = i2c_ll_get_txfifo_len(i2c->dev);
if(len < to_fifo){
to_fifo = len;
}
i2c_ll_write_txfifo(i2c->dev, (uint8_t*)buf, to_fifo);
buf += to_fifo;
len -= to_fifo;
//reset tx_queue
xQueueReset(i2c->tx_queue);
//write the rest of the bytes to the queue
if(len){
to_queue = uxQueueSpacesAvailable(i2c->tx_queue);
if(len < to_queue){
to_queue = len;
}
for (size_t i = 0; i < to_queue; i++) {
if (xQueueSend(i2c->tx_queue, &buf[i], timeout_ms / portTICK_RATE_MS) != pdTRUE) {
xQueueReset(i2c->tx_queue);
to_queue = 0;
break;
}
}
//no need to enable TX_EMPTY if tx_queue is empty
if(to_queue){
i2c_ll_slave_enable_tx_it(i2c->dev);
}
}
I2C_SLAVE_MUTEX_UNLOCK();
return to_queue + to_fifo;
}
//=====================================================================================================================
//-------------------------------------- Private Functions ------------------------------------------------------------
//=====================================================================================================================
static void i2c_slave_free_resources(i2c_slave_struct_t * i2c){
i2c_slave_detach_gpio(i2c);
i2c_ll_set_slave_addr(i2c->dev, 0, false);
i2c_ll_disable_intr_mask(i2c->dev, I2C_LL_INTR_MASK);
i2c_ll_clr_intsts_mask(i2c->dev, I2C_LL_INTR_MASK);
if (i2c->intr_handle) {
esp_intr_free(i2c->intr_handle);
i2c->intr_handle = NULL;
}
if(i2c->task_handle){
vTaskDelete(i2c->task_handle);
i2c->task_handle = NULL;
}
#if I2C_SLAVE_USE_RX_QUEUE
if (i2c->rx_queue) {
vQueueDelete(i2c->rx_queue);
i2c->rx_queue = NULL;
}
#else
if (i2c->rx_ring_buf) {
vRingbufferDelete(i2c->rx_ring_buf);
i2c->rx_ring_buf = NULL;
}
#endif
if (i2c->tx_queue) {
vQueueDelete(i2c->tx_queue);
i2c->tx_queue = NULL;
}
if (i2c->event_queue) {
vQueueDelete(i2c->event_queue);
i2c->event_queue = NULL;
}
i2c->rx_data_count = 0;
}
static bool i2c_slave_set_frequency(i2c_slave_struct_t * i2c, uint32_t clk_speed)
{
if (i2c == NULL) {
log_e("no control buffer");
return false;
}
if(clk_speed > 1100000UL){
clk_speed = 1100000UL;
}
// Adjust Fifo thresholds based on frequency
uint32_t a = (clk_speed / 50000L) + 2;
log_d("Fifo thresholds: rx_fifo_full = %d, tx_fifo_empty = %d", SOC_I2C_FIFO_LEN - a, a);
i2c_clk_cal_t clk_cal;
#if SOC_I2C_SUPPORT_APB
i2c_ll_cal_bus_clk(APB_CLK_FREQ, clk_speed, &clk_cal);
i2c_ll_set_source_clk(i2c->dev, I2C_SCLK_APB); /*!< I2C source clock from APB, 80M*/
#elif SOC_I2C_SUPPORT_XTAL
i2c_ll_cal_bus_clk(XTAL_CLK_FREQ, clk_speed, &clk_cal);
i2c_ll_set_source_clk(i2c->dev, I2C_SCLK_XTAL); /*!< I2C source clock from XTAL, 40M */
#endif
i2c_ll_set_txfifo_empty_thr(i2c->dev, a);
i2c_ll_set_rxfifo_full_thr(i2c->dev, SOC_I2C_FIFO_LEN - a);
i2c_ll_set_bus_timing(i2c->dev, &clk_cal);
i2c_ll_set_filter(i2c->dev, 3);
return true;
}
static void i2c_slave_delay_us(uint64_t us)
{
uint64_t m = esp_timer_get_time();
if (us) {
uint64_t e = (m + us);
if (m > e) { //overflow
while ((uint64_t)esp_timer_get_time() > e);
}
while ((uint64_t)esp_timer_get_time() < e);
}
}
static void i2c_slave_gpio_mode(int8_t pin, gpio_mode_t mode)
{
gpio_config_t conf = {
.pin_bit_mask = 1LL << pin,
.mode = mode,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&conf);
}
static bool i2c_slave_check_line_state(int8_t sda, int8_t scl)
{
if (sda < 0 || scl < 0) {
return false;//return false since there is nothing to do
}
// if the bus is not 'clear' try the cycling SCL until SDA goes High or 9 cycles
gpio_set_level(sda, 1);
gpio_set_level(scl, 1);
i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD);
i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT | GPIO_MODE_DEF_OD);
gpio_set_level(scl, 1);
if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state
log_w("invalid state sda(%d)=%d, scl(%d)=%d", sda, gpio_get_level(sda), scl, gpio_get_level(scl));
for (uint8_t a=0; a<9; a++) {
i2c_slave_delay_us(5);
if (gpio_get_level(sda) && gpio_get_level(scl)) { // bus recovered
log_w("Recovered after %d Cycles",a);
gpio_set_level(sda,0); // start
i2c_slave_delay_us(5);
for (uint8_t a=0;a<9; a++) {
gpio_set_level(scl,1);
i2c_slave_delay_us(5);
gpio_set_level(scl,0);
i2c_slave_delay_us(5);
}
gpio_set_level(scl,1);
i2c_slave_delay_us(5);
gpio_set_level(sda,1); // stop
break;
}
gpio_set_level(scl, 0);
i2c_slave_delay_us(5);
gpio_set_level(scl, 1);
}
}
if (!gpio_get_level(sda) || !gpio_get_level(scl)) { // bus in busy state
log_e("Bus Invalid State, Can't init sda=%d, scl=%d",gpio_get_level(sda),gpio_get_level(scl));
return false; // bus is busy
}
return true;
}
static bool i2c_slave_attach_gpio(i2c_slave_struct_t * i2c, int8_t sda, int8_t scl)
{
if (i2c == NULL) {
log_e("no control block");
return false;
}
if ((sda < 0)||( scl < 0)) {
log_e("bad pins sda=%d, scl=%d",sda,scl);
return false;
}
i2c->scl = scl;
gpio_set_level(scl, 1);
i2c_slave_gpio_mode(scl, GPIO_MODE_INPUT_OUTPUT_OD);
gpio_matrix_out(scl, I2C_SCL_IDX(i2c->num), false, false);
gpio_matrix_in(scl, I2C_SCL_IDX(i2c->num), false);
i2c->sda = sda;
gpio_set_level(sda, 1);
i2c_slave_gpio_mode(sda, GPIO_MODE_INPUT_OUTPUT_OD);
gpio_matrix_out(sda, I2C_SDA_IDX(i2c->num), false, false);
gpio_matrix_in(sda, I2C_SDA_IDX(i2c->num), false);
return true;
}
static bool i2c_slave_detach_gpio(i2c_slave_struct_t * i2c)
{
if (i2c == NULL) {
log_e("no control Block");
return false;
}
if (i2c->scl >= 0) {
gpio_matrix_out(i2c->scl, 0x100, false, false);
gpio_matrix_in(0x30, I2C_SCL_IDX(i2c->num), false);
i2c_slave_gpio_mode(i2c->scl, GPIO_MODE_INPUT);
i2c->scl = -1; // un attached
}
if (i2c->sda >= 0) {
gpio_matrix_out(i2c->sda, 0x100, false, false);
gpio_matrix_in(0x30, I2C_SDA_IDX(i2c->num), false);
i2c_slave_gpio_mode(i2c->sda, GPIO_MODE_INPUT);
i2c->sda = -1; // un attached
}
return true;
}
static bool i2c_slave_send_event(i2c_slave_struct_t * i2c, i2c_slave_queue_event_t* event)
{
bool pxHigherPriorityTaskWoken = false;
if(i2c->event_queue) {
if(xQueueSendFromISR(i2c->event_queue, event, (BaseType_t * const)&pxHigherPriorityTaskWoken) != pdTRUE){
//log_e("event_queue_full");
}
}
return pxHigherPriorityTaskWoken;
}
static bool i2c_slave_handle_tx_fifo_empty(i2c_slave_struct_t * i2c)
{
bool pxHigherPriorityTaskWoken = false;
uint32_t d = 0, moveCnt = i2c_ll_get_txfifo_len(i2c->dev);
while (moveCnt > 0) { // read tx queue until Fifo is full or queue is empty
if(xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t * const)&pxHigherPriorityTaskWoken) == pdTRUE){
i2c_ll_write_txfifo(i2c->dev, (uint8_t*)&d, 1);
moveCnt--;
} else {
i2c_ll_slave_disable_tx_it(i2c->dev);
break;
}
}
return pxHigherPriorityTaskWoken;
}
static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t * i2c, uint32_t len)
{
#if I2C_SLAVE_USE_RX_QUEUE
uint32_t d = 0;
#else
uint8_t data[SOC_I2C_FIFO_LEN];
#endif
bool pxHigherPriorityTaskWoken = false;
#if I2C_SLAVE_USE_RX_QUEUE
while (len > 0) {
i2c_ll_read_rxfifo(i2c->dev, (uint8_t*)&d, 1);
if(xQueueSendFromISR(i2c->rx_queue, &d, (BaseType_t * const)&pxHigherPriorityTaskWoken) != pdTRUE){
log_e("rx_queue_full");
} else {
i2c->rx_data_count++;
}
if (--len == 0) {
len = i2c_ll_get_rxfifo_cnt(i2c->dev);
}
#else
if(len){
i2c_ll_read_rxfifo(i2c->dev, data, len);
if(xRingbufferSendFromISR(i2c->rx_ring_buf, (void*) data, len, (BaseType_t * const)&pxHigherPriorityTaskWoken) != pdTRUE){
log_e("rx_ring_buf_full");
} else {
i2c->rx_data_count += len;
}
#endif
}
return pxHigherPriorityTaskWoken;
}
static void i2c_slave_isr_handler(void* arg)
{
bool pxHigherPriorityTaskWoken = false;
i2c_slave_struct_t * i2c = (i2c_slave_struct_t *) arg; // recover data
uint32_t activeInt = i2c_ll_get_intsts_mask(i2c->dev);
i2c_ll_clr_intsts_mask(i2c->dev, activeInt);
uint8_t rx_fifo_len = i2c_ll_get_rxfifo_cnt(i2c->dev);
uint8_t tx_fifo_len = SOC_I2C_FIFO_LEN - i2c_ll_get_txfifo_len(i2c->dev);
bool slave_rw = i2c_ll_slave_rw(i2c->dev);
if(activeInt & I2C_RXFIFO_WM_INT_ENA){ // RX FiFo Full
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
i2c_ll_slave_enable_rx_it(i2c->dev);//is this necessary?
}
if(activeInt & I2C_TRANS_COMPLETE_INT_ENA){ // STOP
if(rx_fifo_len){ //READ RX FIFO
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
}
if(i2c->rx_data_count){ //WRITE or RepeatedStart
//SEND RX Event
i2c_slave_queue_event_t event;
event.event = I2C_SLAVE_EVT_RX;
event.stop = !slave_rw;
event.param = i2c->rx_data_count;
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
//Zero RX count
i2c->rx_data_count = 0;
}
if(slave_rw){ // READ
#if CONFIG_IDF_TARGET_ESP32
//SEND TX Event
i2c_slave_queue_event_t event;
event.event = I2C_SLAVE_EVT_TX;
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
#else
//reset TX data
i2c_ll_txfifo_rst(i2c->dev);
uint8_t d;
while (xQueueReceiveFromISR(i2c->tx_queue, &d, (BaseType_t * const)&pxHigherPriorityTaskWoken) == pdTRUE) ;//flush partial write
#endif
}
}
#ifndef CONFIG_IDF_TARGET_ESP32
if(activeInt & I2C_SLAVE_STRETCH_INT_ENA){ // STRETCH
i2c_stretch_cause_t cause = i2c_ll_stretch_cause(i2c->dev);
if(cause == I2C_STRETCH_CAUSE_MASTER_READ){
//on C3 RX data dissapears with repeated start, so we need to get it here
if(rx_fifo_len){
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
}
//SEND TX Event
i2c_slave_queue_event_t event;
event.event = I2C_SLAVE_EVT_TX;
pxHigherPriorityTaskWoken |= i2c_slave_send_event(i2c, &event);
//will clear after execution
} else if(cause == I2C_STRETCH_CAUSE_TX_FIFO_EMPTY){
pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c);
i2c_ll_stretch_clr(i2c->dev);
} else if(cause == I2C_STRETCH_CAUSE_RX_FIFO_FULL){
pxHigherPriorityTaskWoken |= i2c_slave_handle_rx_fifo_full(i2c, rx_fifo_len);
i2c_ll_stretch_clr(i2c->dev);
}
}
#endif
if(activeInt & I2C_TXFIFO_WM_INT_ENA){ // TX FiFo Empty
pxHigherPriorityTaskWoken |= i2c_slave_handle_tx_fifo_empty(i2c);
}
if(pxHigherPriorityTaskWoken){
portYIELD_FROM_ISR();
}
}
static size_t i2c_slave_read_rx(i2c_slave_struct_t * i2c, uint8_t * data, size_t len){
if(!len){
return 0;
}
#if I2C_SLAVE_USE_RX_QUEUE
uint8_t d = 0;
BaseType_t res = pdTRUE;
for(size_t i=0; i<len; i++) {
if(data){
res = xQueueReceive(i2c->rx_queue, &data[i], 0);
} else {
res = xQueueReceive(i2c->rx_queue, &d, 0);
}
if (res != pdTRUE) {
log_e("Read Queue(%u) Failed", i);
len = i;
break;
}
}
return (data)?len:0;
#else
size_t dlen = 0,
to_read = len,
so_far = 0,
available = 0;
uint8_t * rx_data = NULL;
vRingbufferGetInfo(i2c->rx_ring_buf, NULL, NULL, NULL, NULL, &available);
if(available < to_read){
log_e("Less available than requested. %u < %u", available, len);
to_read = available;
}
while(to_read){
dlen = 0;
rx_data = (uint8_t *)xRingbufferReceiveUpTo(i2c->rx_ring_buf, &dlen, 0, to_read);
if(!rx_data){
log_e("Receive %u Failed", to_read);
return so_far;
}
if(data){
memcpy(data+so_far, rx_data, dlen);
}
vRingbufferReturnItem(i2c->rx_ring_buf, rx_data);
so_far+=dlen;
to_read-=dlen;
}
return (data)?so_far:0;
#endif
}
static void i2c_slave_task(void *pv_args)
{
i2c_slave_struct_t * i2c = (i2c_slave_struct_t *)pv_args;
i2c_slave_queue_event_t event;
size_t len = 0;
bool stop = false;
uint8_t * data = NULL;
for(;;){
if(xQueueReceive(i2c->event_queue, &event, portMAX_DELAY) == pdTRUE){
// Write
if(event.event == I2C_SLAVE_EVT_RX){
len = event.param;
stop = event.stop;
data = (len > 0)?(uint8_t*)malloc(len):NULL;
if(len && data == NULL){
log_e("Malloc (%u) Failed", len);
}
len = i2c_slave_read_rx(i2c, data, len);
if(i2c->receive_callback){
i2c->receive_callback(i2c->num, data, len, stop, i2c->arg);
}
free(data);
// Read
} else if(event.event == I2C_SLAVE_EVT_TX){
if(i2c->request_callback){
i2c->request_callback(i2c->num, i2c->arg);
}
i2c_ll_stretch_clr(i2c->dev);
}
}
}
vTaskDelete(NULL);
}

View File

@ -0,0 +1,35 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
#include "stddef.h"
#include "esp_err.h"
typedef void (*i2c_slave_request_cb_t) (uint8_t num, void * arg);
typedef void (*i2c_slave_receive_cb_t) (uint8_t num, uint8_t * data, size_t len, bool stop, void * arg);
esp_err_t i2cSlaveAttachCallbacks(uint8_t num, i2c_slave_request_cb_t request_callback, i2c_slave_receive_cb_t receive_callback, void * arg);
esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t frequency, size_t rx_len, size_t tx_len);
esp_err_t i2cSlaveDeinit(uint8_t num);
size_t i2cSlaveWrite(uint8_t num, const uint8_t *buf, uint32_t len, uint32_t timeout_ms);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// modified Nov 2017 by Chuck Todd <StickBreaker> to support Interrupt Driven I/O
// modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
#ifndef _ESP32_HAL_I2C_H_
#define _ESP32_HAL_I2C_H_
@ -22,58 +23,16 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include <esp_err.h>
// External Wire.h equivalent error Codes
typedef enum {
I2C_ERROR_OK=0,
I2C_ERROR_DEV,
I2C_ERROR_ACK,
I2C_ERROR_TIMEOUT,
I2C_ERROR_BUS,
I2C_ERROR_BUSY,
I2C_ERROR_MEMORY,
I2C_ERROR_CONTINUE,
I2C_ERROR_NO_BEGIN
} i2c_err_t;
struct i2c_struct_t;
typedef struct i2c_struct_t i2c_t;
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed);
void i2cRelease(i2c_t *i2c); // free ISR, Free DQ, Power off peripheral clock. Must call i2cInit() to recover
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis);
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis, uint32_t *readCount);
i2c_err_t i2cFlush(i2c_t *i2c);
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
uint32_t i2cGetFrequency(i2c_t * i2c);
uint32_t i2cGetStatus(i2c_t * i2c); // Status register of peripheral
//Functions below should be used only if well understood
//Might be deprecated and removed in future
i2c_err_t i2cAttachSCL(i2c_t * i2c, int8_t scl);
i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl);
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda);
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
//Stickbreakers ISR Support
i2c_err_t i2cProcQueue(i2c_t *i2c, uint32_t *readCount, uint16_t timeOutMillis);
i2c_err_t i2cAddQueueWrite(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
i2c_err_t i2cAddQueueRead(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
//stickbreaker debug support
uint32_t i2cDebug(i2c_t *, uint32_t setBits, uint32_t resetBits);
// Debug actions have 3 currently defined locus
// 0xXX------ : at entry of ProcQueue
// 0x--XX---- : at exit of ProcQueue
// 0x------XX : at entry of Flush
//
// bit 0 causes DumpI2c to execute
// bit 1 causes DumpInts to execute
// bit 2 causes DumpCmdqueue to execute
// bit 3 causes DumpStatus to execute
// bit 4 causes DumpFifo to execute
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed);
esp_err_t i2cDeinit(uint8_t i2c_num);
esp_err_t i2cSetClock(uint8_t i2c_num, uint32_t frequency);
esp_err_t i2cGetClock(uint8_t i2c_num, uint32_t * frequency);
esp_err_t i2cWrite(uint8_t i2c_num, uint16_t address, const uint8_t* buff, size_t size, uint32_t timeOutMillis);
esp_err_t i2cRead(uint8_t i2c_num, uint16_t address, uint8_t* buff, size_t size, uint32_t timeOutMillis, size_t *readCount);
esp_err_t i2cWriteReadNonStop(uint8_t i2c_num, uint16_t address, const uint8_t* wbuff, size_t wsize, uint8_t* rbuff, size_t rsize, uint32_t timeOutMillis, size_t *readCount);
bool i2cIsInit(uint8_t i2c_num);
#ifdef __cplusplus
}

View File

@ -99,9 +99,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_v(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_VERBOSE);}while(0)
#endif
#else
#define log_v(format, ...)
#define isr_log_v(format, ...)
#define log_buf_v(b,l)
#define log_v(format, ...) do {} while(0)
#define isr_log_v(format, ...) do {} while(0)
#define log_buf_v(b,l) do {} while(0)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
@ -115,9 +115,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_d(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_DEBUG);}while(0)
#endif
#else
#define log_d(format, ...)
#define isr_log_d(format, ...)
#define log_buf_d(b,l)
#define log_d(format, ...) do {} while(0)
#define isr_log_d(format, ...) do {} while(0)
#define log_buf_d(b,l) do {} while(0)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
@ -131,9 +131,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_i(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_INFO);}while(0)
#endif
#else
#define log_i(format, ...)
#define isr_log_i(format, ...)
#define log_buf_i(b,l)
#define log_i(format, ...) do {} while(0)
#define isr_log_i(format, ...) do {} while(0)
#define log_buf_i(b,l) do {} while(0)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_WARN
@ -147,9 +147,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_w(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_WARN);}while(0)
#endif
#else
#define log_w(format, ...)
#define isr_log_w(format, ...)
#define log_buf_w(b,l)
#define log_w(format, ...) do {} while(0)
#define isr_log_w(format, ...) do {} while(0)
#define log_buf_w(b,l) do {} while(0)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
@ -163,9 +163,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_e(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_ERROR);}while(0)
#endif
#else
#define log_e(format, ...)
#define isr_log_e(format, ...)
#define log_buf_e(b,l)
#define log_e(format, ...) do {} while(0)
#define isr_log_e(format, ...) do {} while(0)
#define log_buf_e(b,l) do {} while(0)
#endif
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_NONE
@ -179,9 +179,9 @@ void log_print_buf(const uint8_t *b, size_t len);
#define log_buf_n(b,l) do {ESP_LOG_BUFFER_HEXDUMP(TAG, b, l, ESP_LOG_ERROR);}while(0)
#endif
#else
#define log_n(format, ...)
#define isr_log_n(format, ...)
#define log_buf_n(b,l)
#define log_n(format, ...) do {} while(0)
#define isr_log_n(format, ...) do {} while(0)
#define log_buf_n(b,l) do {} while(0)
#endif
#include "esp_log.h"

View File

@ -546,16 +546,16 @@ float rmtSetTick(rmt_obj_t* rmt, float tick)
size_t channel = rmt->channel;
#if CONFIG_IDF_TARGET_ESP32C3
int apb_div = _LIMIT(tick/25.0, 256);
float apb_tick = 25.0 * apb_div;
int apb_div = _LIMIT(tick/25.0f, 256);
float apb_tick = 25.0f * apb_div;
RMT.tx_conf[channel].div_cnt = apb_div & 0xFF;
RMT.tx_conf[channel].conf_update = 1;
return apb_tick;
#else
int apb_div = _LIMIT(tick/12.5, 256);
int apb_div = _LIMIT(tick/12.5f, 256);
int ref_div = _LIMIT(tick/1000, 256);
float apb_tick = 12.5 * apb_div;
float ref_tick = 1000.0 * ref_div;
float apb_tick = 12.5f * apb_div;
float ref_tick = 1000.0f * ref_div;
if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) {
RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF;
RMT.conf_ch[channel].conf1.ref_always_on = 1;

View File

@ -90,17 +90,10 @@ typedef void (*voidFuncPtr)(void);
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
void ARDUINO_ISR_ATTR __timerISR(void * arg){
#if CONFIG_IDF_TARGET_ESP32
uint32_t s0 = TIMERG0.int_st_timers.val;
uint32_t s1 = TIMERG1.int_st_timers.val;
TIMERG0.int_clr_timers.val = s0;
TIMERG1.int_clr_timers.val = s1;
#else
uint32_t s0 = TIMERG0.int_st.val;
uint32_t s1 = TIMERG1.int_st.val;
TIMERG0.int_clr.val = s0;
TIMERG1.int_clr.val = s1;
#endif
uint8_t status = (s1 & 3) << 2 | (s0 & 3);
uint8_t i = 4;
//restart the timers that should autoreload
@ -239,19 +232,19 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
}
timer->dev->config.enable = 0;
if(timer->group) {
#if CONFIG_IDF_TARGET_ESP32
TIMERG1.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
#else
TIMERG1.int_clr.val = BIT(timer->timer);
TIMERG1.int_ena_timers.val &= ~BIT(timer->timer);
#endif
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
} else {
TIMERG0.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
TIMERG0.int_ena.val &= ~BIT(timer->timer);
#else
TIMERG0.int_clr.val = BIT(timer->timer);
TIMERG0.int_ena_timers.val &= ~BIT(timer->timer);
#endif
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
}
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
timer->dev->config.use_xtal = 0;
@ -289,19 +282,19 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
timer->dev->config.edge_int_en = 0;
timer->dev->config.alarm_en = 0;
if(timer->num & 2){
#if CONFIG_IDF_TARGET_ESP32
TIMERG1.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
#else
TIMERG1.int_ena_timers.val &= ~BIT(timer->timer);
#endif
TIMERG1.int_clr_timers.val |= BIT(timer->timer);
#else
TIMERG1.int_clr.val = BIT(timer->timer);
#endif
} else {
TIMERG0.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
TIMERG0.int_ena.val &= ~BIT(timer->timer);
#else
TIMERG0.int_clr.val = BIT(timer->timer);
TIMERG0.int_ena_timers.val &= ~BIT(timer->timer);
#endif
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
}
__timerInterruptHandlers[timer->num] = NULL;
} else {
@ -333,9 +326,17 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
}
if(timer->group){
#if CONFIG_IDF_TARGET_ESP32
TIMERG1.int_ena.val |= BIT(timer->timer);
#else
TIMERG1.int_ena_timers.val |= BIT(timer->timer);
#endif
} else {
#if CONFIG_IDF_TARGET_ESP32
TIMERG0.int_ena.val |= BIT(timer->timer);
#else
TIMERG0.int_ena_timers.val |= BIT(timer->timer);
#endif
}
}
if(intr_handle){

View File

@ -269,7 +269,7 @@ void uartWrite(uart_t* uart, uint8_t c)
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
{
if(uart == NULL) {
if(uart == NULL || data == NULL || !len) {
return;
}

View File

@ -31,6 +31,11 @@
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#ifdef __cplusplus
extern "C" {

View File

@ -39,7 +39,7 @@ static const char * FAT12_FILE_SYSTEM_TYPE = "FAT12";
static uint16_t fat12_sectors_per_alloc_table(uint32_t sector_num){
uint32_t required_bytes = (((sector_num * 3)+1)/2);
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & DISK_SECTOR_SIZE)?1:0);
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & (DISK_SECTOR_SIZE - 1))?1:0);
}
static uint8_t * fat12_add_table(uint8_t * dst, fat_boot_sector_t * boot){
@ -68,7 +68,7 @@ static const char * FAT16_FILE_SYSTEM_TYPE = "FAT16";
static uint16_t fat16_sectors_per_alloc_table(uint32_t sector_num){
uint32_t required_bytes = sector_num * 2;
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & DISK_SECTOR_SIZE)?1:0);
return (required_bytes / DISK_SECTOR_SIZE) + ((required_bytes & (DISK_SECTOR_SIZE - 1))?1:0);
}
static uint8_t * fat16_add_table(uint8_t * dst, fat_boot_sector_t * boot){
@ -129,7 +129,7 @@ fat_boot_sector_t * fat_add_boot_sector(uint8_t * dst, uint16_t sector_num, uint
boot->num_heads = 1;
boot->hidden_sectors_count = 0;
boot->total_sectors_32 = 0;
boot->physical_drive_number = 0x00;
boot->physical_drive_number = 0x80;
boot->reserved0 = 0x00;
boot->extended_boot_signature = 0x29;
boot->serial_number = serial_number;

View File

@ -12,7 +12,7 @@ static int base64_decode_value_signed(int8_t value_in){
static const int8_t decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
static const int8_t decoding_size = sizeof(decoding);
value_in -= 43;
if (value_in < 0 || value_in > decoding_size) return -1;
if (value_in < 0 || value_in >= decoding_size) return -1;
return decoding[(int)value_in];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

384
docs/source/api/i2c.rst Normal file
View File

@ -0,0 +1,384 @@
###
I2C
###
About
-----
I2C (Inter-Integrated Circuit) / TWI (Two-wire Interface) is a widely used serial communication to connect devices in a short distance. This is one of the most common peripherals used to connect sensors, EEPROMs, RTC, ADC, DAC, displays, OLED, and many other devices and microcontrollers.
This serial communication is considered as a low-speed bus, and multiple devices can be connected on the same two-wires bus, each with a unique 7-bits address (up to 128 devices). These two wires are called SDA (serial data line) and SCL (serial clock line).
.. note:: The SDA and SCL lines require pull-up resistors. See the device datasheet for more details about the resistors' values and the operating voltage.
I2C Modes
*********
The I2C can be used in two different modes:
* **I2C Master Mode**
* In this mode, the ESP32 generates the clock signal and initiates the communication with the slave device.
.. figure:: ../_static/arduino_i2c_master.png
:align: center
:width: 720
:figclass: align-center
* **I2C Slave Mode**
* The slave mode, the clock is generated by the master device and responds to the master if the destination address is the same as the destination.
.. figure:: ../_static/arduino_i2c_slave.png
:align: center
:width: 520
:figclass: align-center
Arduino-ESP32 I2C API
---------------------
The ESP32 I2C library is based on the `Arduino Wire Library`_ and implements a few more APIs, described in this documentation.
I2C Common API
**************
Here are the common functions used for master and slave modes.
begin
^^^^^
This function is used to start the peripheral using the default configuration.
.. code-block:: arduino
bool begin();
This function will return ``true`` if the peripheral was initialized correctly.
setPins
^^^^^^^
This function is used to define the ``SDA`` and ``SCL`` pins.
.. note:: Call this function before ``begin`` to change the pins from the default ones.
.. code-block:: arduino
bool setPins(int sdaPin, int sclPin);
* ``sdaPin`` sets the GPIO to be used as the I2C peripheral data line.
* ``sclPin`` sets the GPIO to be used as the I2C peripheral clock line.
The default pins may vary from board to board. On the *Generic ESP32* the default I2C pins are:
* ``sdaPin`` **GPIO21**
* ``sclPin`` **GPIO22**
This function will return ``true`` if the peripheral was configured correctly.
setClock
^^^^^^^^
Use this function to set the bus clock. The default value will be used if this function is not used.
.. code-block:: arduino
bool setClock(uint32_t frequency);
* ``frequency`` sets the bus frequency clock.
This function will return ``true`` if the clock was configured correctly.
getClock
^^^^^^^^
Use this function to get the bus clock.
.. code-block:: arduino
uint32_t getClock();
This function will return the current frequency configuration.
setTimeOut
^^^^^^^^^^
Set the bus timeout given in milliseconds. The default value is 50ms.
.. code-block:: arduino
void setTimeOut(uint16_t timeOutMillis);
* ``timeOutMillis`` sets the timeout in ms.
getTimeOut
^^^^^^^^^^
Get the bus timeout in milliseconds.
.. code-block:: arduino
uint16_t getTimeOut();
This function will return the current timeout configuration.
.. _i2c write:
write
^^^^^
This function writes data to the buffer.
.. code-block:: arduino
size_t write(uint8_t);
or
.. code-block:: arduino
size_t write(const uint8_t *, size_t);
The return will be the size of the data added to the buffer.
.. _i2c end:
end
^^^
This function will finish the communication and release all the allocated resources. After calling ``end`` you need to use ``begin`` again in order to initialize the I2C driver again.
.. code-block:: arduino
bool end();
I2C Master Mode
***************
This mode is used to initiate communication to the slave.
Basic Usage
^^^^^^^^^^^
To start using I2C master mode on the Arduino, the first step is to include the ``Wire.h`` header to the sketch.
.. code-block:: arduino
#include "Wire.h"
Now, we can start the peripheral configuration by calling ``begin`` function.
.. code-block:: arduino
Wire.begin();
By using ``begin`` without any arguments, all the settings will be done by using the default values. To set the values by your own, see the function description. This function is described here: `i2c begin`_
After calling ``begin``, we can start the transmission by calling ``beginTransmission`` and passing the I2C slave address:
.. code-block:: arduino
Wire.beginTransmission(I2C_DEV_ADDR);
To write some bytes to the slave, use the ``write`` function.
.. code-block:: arduino
Wire.write(x);
You can pass different data types using ``write`` function. This function is described here: `i2c write`_
.. note:: The ``write`` function does not write directly to the slave device but adds to the I2C buffer. To do so, you need to use the ``endTransmission`` function to send the buffered bytes to the slave device.
.. code-block:: arduino
Wire.endTransmission(true);
After calling ``endTransmission``, the data stored in the I2C buffer will be transmitted to the slave device.
Now you can request a reading from the slave device. The ``requestFrom`` will ask for a readout to the selected device by giving the address and the size.
.. code-block:: arduino
Wire.requestFrom(I2C_DEV_ADDR, SIZE);
and the ``readBytes`` will read it.
.. code-block:: arduino
Wire.readBytes(temp, error);
.. _i2c begin:
I2C Master APIs
***************
Here are the I2C master APIs. These function are intended to be used only for master mode.
begin
^^^^^
In master mode, the ``begin`` function can be used by passing the **pins** and **bus frequency**. Use this function only for the master mode.
.. code-block:: arduino
bool begin(int sdaPin, int sclPin, uint32_t frequency)
Alternatively, you can use the ``begin`` function without any argument to use all default values.
This function will return ``true`` if the peripheral was initialized correctly.
beginTransmission
^^^^^^^^^^^^^^^^^
This function is used to star a communication process with the slave device. Call this function by passing the slave ``address`` before writing the message to the buffer.
.. code-block:: arduino
void beginTransmission(uint16_t address)
endTransmission
^^^^^^^^^^^^^^^
After writing to the buffer using `i2c write`_, use the function ``endTransmission`` to send the message to the slave device address defined on the ``beginTransmission`` function.
.. code-block:: arduino
uint8_t endTransmission(bool sendStop);
* ``sendStop`` enables **(true)** or disables **(false)** the stop signal *(only used in master mode)*.
Calling the this function without ``sendStop`` is equivalent to ``sendStop = true``.
.. code-block:: arduino
uint8_t endTransmission(void);
This function will return the error code.
requestFrom
^^^^^^^^^^^
To read from the slave device, use the ``requestFrom`` function.
.. code-block:: arduino
uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop)
* ``address`` set the device address.
* ``size`` define the size to be requested.
* ``sendStop`` enables (true) or disables (false) the stop signal.
This function will return the number of bytes read from the device.
Example Application - WireMaster.ino
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here is an example of how to use the I2C in Master Mode.
.. literalinclude:: ../../../libraries/Wire/examples/WireMaster/WireMaster.ino
:language: arduino
I2C Slave Mode
**************
This mode is used to accept communication from the master.
Basic Usage
^^^^^^^^^^^
To start using I2C as slave mode on the Arduino, the first step is to include the ``Wire.h`` header to the scketch.
.. code-block:: arduino
#include "Wire.h"
Before calling ``begin`` we must create two callback functions to handle the communication with the master device.
.. code-block:: arduino
Wire.onReceive(onReceive);
and
.. code-block:: arduino
Wire.onRequest(onRequest);
The ``onReceive`` will handle the request from the master device uppon a slave read request and the ``onRequest`` will handle the answer to the master.
Now, we can start the peripheral configuration by calling ``begin`` function with the device address.
.. code-block:: arduino
Wire.begin((uint8_t)I2C_DEV_ADDR);
By using ``begin`` without any arguments, all the settings will be done by using the default values. To set the values by your own, see the function description. This function is described here: `i2c begin`_
**For ESP32 only!**
Use the function ``slaveWrite`` in order to pre-write to the slave response buffer. This is used only for the ESP32 in order to add the slave capability on the chip and keep compatability with Arduino.
.. code-block:: arduino
Wire.slaveWrite((uint8_t *)message, strlen(message));
I2C Slave APIs
**************
Here are the I2C slave APIs. These function are intended to be used only for slave mode.
begin
^^^^^
In slave mode, the ``begin`` function must be used by passing the **slave address**. You can also define the **pins** and the **bus frequency**.
.. code-block:: arduino
bool Wire.begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
This function will return ``true`` if the peripheral was initialized correctly.
onReceive
^^^^^^^^^
The ``onReceive`` function is used to define the callback for the data received from the master.
.. code-block:: arduino
void onReceive( void (*)(int) );
onRequest
^^^^^^^^^
The ``onRequest`` function is used to define the callback for the data to be send to the master.
.. code-block:: arduino
void onRequest( void (*)(void) );
slaveWrite
^^^^^^^^^^
The ``slaveWrite`` function writes on the slave response buffer before receiving the response message. This function is only used for adding the slave compatability for the ESP32.
.. warning:: This function is only required for the ESP32. You **don't** need to use for ESP32-S2 and ESP32-C3.
.. code-block:: arduino
size_t slaveWrite(const uint8_t *, size_t);
Example Application - WireSlave.ino
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here is an example of how to use the I2C in Slave Mode.
.. literalinclude:: ../../../libraries/Wire/examples/WireSlave/WireSlave.ino
:language: arduino
.. _Arduino Wire Library: https://www.arduino.cc/en/reference/wire

View File

@ -26,7 +26,7 @@ a Wi-Fi network.
:width: 520
:figclass: align-center
This mode can be used for serving a HTTP or HTTPS server inside the ESP32, for example.
This mode can be used for serving an HTTP or HTTPS server inside the ESP32, for example.
Working as STA
**************
@ -38,12 +38,34 @@ The STA mode is used to connect the ESP32 to a Wi-Fi network, provided by an Acc
:width: 520
:figclass: align-center
If you need to connect your project to the Internet, this is the mode you are looking for.
This is the mode to be used if you want to connect your project to the Internet.
API Description
---------------
Here is the description about the WiFi API.
Here is the description of the WiFi API.
Common API
----------
Here are the common APIs that are used for both modes, AP and STA.
useStaticBuffers
****************
This function is used to set the memory allocation mode for the Wi-Fi buffers.
.. code-block:: arduino
static void useStaticBuffers(bool bufferMode);
* Set ``true`` to use the Wi-Fi buffers memory allocation as **static**.
* Set ``false`` to set the buffers memory allocation to **dynamic**.
The use of dynamic allocation is recommended to save memory and reduce resources usage. However, the dynamic performs slightly slower than the static allocation.
Use static allocation if you want to have more performance and if your application is multi-tasking.
By default, the memory allocation will be set to **dynamic** if this function is not being used.
WiFiAP
------

View File

@ -166,9 +166,7 @@ Debian/Ubuntu
mkdir -p ~/Arduino/hardware/espressif && \
cd ~/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32 && \
git submodule update --init --recursive && \
cd tools && \
cd esp32/tools && \
python3 get.py
- Restart Arduino IDE.
@ -181,9 +179,7 @@ Debian/Ubuntu
mkdir -p espressif && \
cd espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32 && \
git submodule update --init --recursive && \
cd tools && \
cd esp32/tools && \
python3 get.py
Fedora
@ -203,9 +199,7 @@ Fedora
mkdir -p ~/Arduino/hardware/espressif && \
cd ~/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32 && \
git submodule update --init --recursive && \
cd tools && \
cd esp32/tools && \
python get.py
- Restart Arduino IDE.
@ -228,9 +222,7 @@ openSUSE
mkdir -p ~/Arduino/hardware/espressif && \
cd ~/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32 && \
git submodule update --init --recursive && \
cd tools && \
cd esp32/tools && \
python get.py
- Restart Arduino IDE.
@ -246,10 +238,8 @@ macOS
mkdir -p ~/Documents/Arduino/hardware/espressif && \
cd ~/Documents/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 --depth 1 && \
cd esp32 && \
git submodule update --init --recursive --depth 1 && \
cd tools && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32/tools && \
python get.py
Where ``~/Documents/Arduino`` represents your sketch book location as per "Arduino" > "Preferences" > "Sketchbook location" (in the IDE once started). Adjust the command above accordingly.

View File

@ -2,16 +2,68 @@
Libraries
#########
Here is where the Libraries API's descriptions are located.
Here is where the Libraries API's descriptions are located:
Supported Peripherals
---------------------
Currently, the Arduino ESP32 supports the following peripherals with Arduino style. Some other peripherals are not supported yet, but it's supported using ESP-IDF style.
+-------------+-------------+---------+--------------------+
| Peripheral | Arduino API | ESP-IDF | Comment |
+=============+=============+=========+====================+
| ADC | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| DAC | No | No | |
+-------------+-------------+---------+--------------------+
| GPIO | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| SDIO/SPI | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| I2C | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| I2S | No | Yes | In Development |
+-------------+-------------+---------+--------------------+
| Wi-Fi | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| Bluetooth | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| RMT | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| Touch | Yes | Yes | ESP32 & ESP32-S2 |
+-------------+-------------+---------+--------------------+
| Timer | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| UART | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| Hall Sensor | Yes | Yes | Only for ESP32 |
+-------------+-------------+---------+--------------------+
| LEDC | Yes | Yes | |
+-------------+-------------+---------+--------------------+
| Motor PWM | No | No | |
+-------------+-------------+---------+--------------------+
| TWAI | No | No | |
+-------------+-------------+---------+--------------------+
| Ethernet | Yes | Yes | Only for ESP32 |
+-------------+-------------+---------+--------------------+
| USB | Yes | Yes | Only for ESP32-S2 |
+-------------+-------------+---------+--------------------+
Some peripherals are not available for all ESP32 families. To see more details about it, see the corresponding datasheet.
APIs
----
The Arduino ESP32 offers some unique APIs, described in this section:
.. toctree::
:maxdepth: 1
:caption: API's:
Bluetooth <api/bluetooth>
Deep Sleep <api/deepsleep>
ESPNOW <api/espnow>
GPIO <api/gpio>
I2C <api/i2c>
RainMaker <api/rainmaker>
Reset Reason <api/reset_reason>
Wi-Fi <api/wifi>

View File

@ -12,31 +12,57 @@ Here are some of the most common issues around the ESP32 development using Ardui
Installing
----------
Here are the common issues during the installation.
Building
--------
Missing Python: "python": executable file not found in $PATH
************************************************************
You are trying to build your sketch using Ubuntu and this message appears:
.. code-block:: bash
"exec: "python": executable file not found in $PATH
Error compiling for board ESP32 Dev Module"
Solution
^^^^^^^^
To avoid this error, you can install the ``python-is-python3`` package to create the symbolic links.
.. code-block:: bash
sudo apt install python-is-python3
If you are not using Ubuntu, you can check if you have the Python correctly installed or the presence of the symbolic links/environment variables.
Flashing
--------
Why is my board not flashing/uploading when I try to upload my sketch?
**********************************************************************
If you are trying to upload a new sketch and your board isn't responding, there are some possible reasons.
To be able to upload the sketch via serial interface, the ESP32 must be in the download mode. The download mode allows you to upload the sketch over the serial port and to get into it, you need to keep the **GPIO0** in LOW while a resetting (**EN** pin) cycle.
If you are trying to upload a new sketch and your board is not responding, there are some possible reasons.
Possible fatal error message from the Arduino IDE:
*A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header*
Solution
^^^^^^^^
Here are some steps that you can try to:
* Check your USB cable and try a new one.
* Change the USB port.
* Check your power supply.
* In some instances, you must keep **GPIO0** LOW during the uploading process via serial interface.
* Hold-down the **“BOOT”** button in your ESP32 board while uploading/flashing.
* In some instances, you must keep **GPIO0** LOW during the uploading process via the serial interface.
* Hold down the **“BOOT”** button in your ESP32 board while uploading/flashing.
In some development boards, you can try adding the reset delay circuit, as decribed in the *Power-on Sequence* section on the `ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf>`_ in order to get into the download mode automatically.
In some development boards, you can try adding the reset delay circuit, as described in the *Power-on Sequence* section on the `ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf>`_ in order to get into the download mode automatically.
Hardware
--------
@ -44,7 +70,10 @@ Hardware
Why is my computer not detecting my board?
**************************************************
If your board is not detected after connecting into the USB, you can try to:
If your board is not being detected after connecting to the USB, you can try to:
Solution
^^^^^^^^
* Check if the USB driver is missing. - `USB Driver Download Link <https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers>`_
* Check your USB cable and try a new one.

View File

@ -191,7 +191,7 @@ uint8_t* BLECharacteristic::getData() {
* @brief Retrieve the current length of the data of the characteristic.
* @return Amount of databytes of the characteristic.
*/
uint8_t BLECharacteristic::getLength() {
size_t BLECharacteristic::getLength() {
return m_value.getLength();
} // getLength

View File

@ -62,7 +62,7 @@ public:
BLEUUID getUUID();
std::string getValue();
uint8_t* getData();
uint8_t getLength();
size_t getLength();
void indicate();
void notify(bool is_notification = true);

View File

@ -11,27 +11,27 @@
#include "EEPROM.h"
// Instantiate eeprom objects with parameter/argument names and sizes
EEPROMClass NAMES("eeprom0", 0x500);
EEPROMClass HEIGHT("eeprom1", 0x200);
EEPROMClass AGE("eeprom2", 0x100);
EEPROMClass NAMES("eeprom0");
EEPROMClass HEIGHT("eeprom1");
EEPROMClass AGE("eeprom2");
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("Testing EEPROMClass\n");
if (!NAMES.begin(NAMES.length())) {
if (!NAMES.begin(0x500)) {
Serial.println("Failed to initialise NAMES");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
if (!HEIGHT.begin(HEIGHT.length())) {
if (!HEIGHT.begin(0x200)) {
Serial.println("Failed to initialise HEIGHT");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
if (!AGE.begin(AGE.length())) {
if (!AGE.begin(0x100)) {
Serial.println("Failed to initialise AGE");
Serial.println("Restarting...");
delay(1000);

View File

@ -34,7 +34,6 @@ EEPROMClass::EEPROMClass(void)
, _size(0)
, _dirty(false)
, _name("eeprom")
, _user_defined_size(0)
{
}
@ -45,17 +44,15 @@ EEPROMClass::EEPROMClass(uint32_t sector)
, _size(0)
, _dirty(false)
, _name("eeprom")
, _user_defined_size(0)
{
}
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
EEPROMClass::EEPROMClass(const char* name)
: _handle(0)
, _data(0)
, _size(0)
, _dirty(false)
, _name(name)
, _user_defined_size(user_defined_size)
{
}
@ -133,7 +130,7 @@ bool EEPROMClass::begin(size_t size) {
_data = (uint8_t*) malloc(size);
if(!_data) {
log_e("Not enough memory for %d bytes in EEPROM");
log_e("Not enough memory for %d bytes in EEPROM", size);
return false;
}
_size = size;
@ -215,7 +212,7 @@ uint8_t * EEPROMClass::getDataPtr() {
*/
uint16_t EEPROMClass::length ()
{
return _user_defined_size;
return _size;
}
/*

View File

@ -35,7 +35,7 @@ typedef uint32_t nvs_handle;
class EEPROMClass {
public:
EEPROMClass(uint32_t sector);
EEPROMClass(const char* name, uint32_t user_defined_size);
EEPROMClass(const char* name);
EEPROMClass(void);
~EEPROMClass(void);
@ -112,7 +112,6 @@ class EEPROMClass {
size_t _size;
bool _dirty;
const char* _name;
uint32_t _user_defined_size;
};
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)

View File

@ -14,6 +14,7 @@
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM

View File

@ -113,6 +113,25 @@
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1

View File

@ -0,0 +1,9 @@
name=Ethernet
version=2.0.0
author=Hristo Gochkov
maintainer=Hristo Gochkov <hristo@espressif.com>
sentence=Enables network connection (local and Internet) using the ESP32 Ethernet.
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through Ethernet. The IP address can be assigned statically or through a DHCP. The library can also manage DNS.
category=Communication
url=
architectures=esp32

View File

@ -237,12 +237,6 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
if(esp_eth_set_default_handlers(eth_netif) != ESP_OK){
log_e("esp_eth_set_default_handlers failed");
return false;
}
esp_eth_mac_t *eth_mac = NULL;
#if CONFIG_ETH_SPI_ETHERNET_DM9051
if(type == ETH_PHY_DM9051){
@ -288,7 +282,12 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ
break;
#endif
case ETH_PHY_KSZ8081:
#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4,3,0)
eth_phy = esp_eth_phy_new_ksz8081(&phy_config);
#else
log_e("unsupported ethernet type 'ETH_PHY_KSZ8081'");
#endif
break;
default:
break;
}

View File

@ -168,7 +168,7 @@ size_t F_Fat::freeBytes()
bool F_Fat::exists(const char* path)
{
File f = open(path, "r");
File f = open(path, "r",false);
return (f == true) && !f.isDirectory();
}

View File

@ -186,18 +186,18 @@ void File::rewindDirectory(void)
_p->rewindDirectory();
}
File FS::open(const String& path, const char* mode)
File FS::open(const String& path, const char* mode, const bool create)
{
return open(path.c_str(), mode);
return open(path.c_str(), mode, create);
}
File FS::open(const char* path, const char* mode)
File FS::open(const char* path, const char* mode, const bool create)
{
if (!_impl) {
return File();
}
return File(_impl->open(path, mode));
return File(_impl->open(path, mode, create));
}
bool FS::exists(const char* path)

View File

@ -89,8 +89,8 @@ class FS
public:
FS(FSImplPtr impl) : _impl(impl) { }
File open(const char* path, const char* mode = FILE_READ);
File open(const String& path, const char* mode = FILE_READ);
File open(const char* path, const char* mode = FILE_READ, const bool create = false);
File open(const String& path, const char* mode = FILE_READ, const bool create = false);
bool exists(const char* path);
bool exists(const String& path);

View File

@ -53,7 +53,7 @@ protected:
public:
FSImpl() : _mountpoint(NULL) { }
virtual ~FSImpl() { }
virtual FileImplPtr open(const char* path, const char* mode) = 0;
virtual FileImplPtr open(const char* path, const char* mode, const bool create) = 0;
virtual bool exists(const char* path) = 0;
virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
virtual bool remove(const char* path) = 0;

View File

@ -16,7 +16,7 @@
using namespace fs;
FileImplPtr VFSImpl::open(const char* fpath, const char* mode)
FileImplPtr VFSImpl::open(const char* fpath, const char* mode, const bool create)
{
if(!_mountpoint) {
log_e("File system is not mounted");
@ -37,7 +37,7 @@ FileImplPtr VFSImpl::open(const char* fpath, const char* mode)
sprintf(temp,"%s%s", _mountpoint, fpath);
struct stat st;
//file lound
//file found
if(!stat(temp, &st)) {
free(temp);
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
@ -47,12 +47,6 @@ FileImplPtr VFSImpl::open(const char* fpath, const char* mode)
return FileImplPtr();
}
//file not found but mode permits creation
if(mode && mode[0] != 'r') {
free(temp);
return std::make_shared<VFSFileImpl>(this, fpath, mode);
}
//try to open this as directory (might be mount point)
DIR * d = opendir(temp);
if(d) {
@ -61,7 +55,51 @@ FileImplPtr VFSImpl::open(const char* fpath, const char* mode)
return std::make_shared<VFSFileImpl>(this, fpath, mode);
}
log_e("%s does not exist", temp);
//file not found but mode permits file creation without folder creation
if((mode && mode[0] != 'r') && (!create)){
free(temp);
return std::make_shared<VFSFileImpl>(this, fpath, mode);
}
////file not found but mode permits file creation and folder creation
if((mode && mode[0] != 'r') && create){
char *token;
char *folder = (char *)malloc(strlen(fpath));
int start_index = 0;
int end_index = 0;
token = strchr(fpath+1,'/');
end_index = (token-fpath);
while (token != NULL)
{
memcpy(folder,fpath + start_index, end_index-start_index);
folder[end_index-start_index] = '\0';
if(!VFSImpl::mkdir(folder))
{
log_e("Creating folder: %s failed!",folder);
return FileImplPtr();
}
token=strchr(token+1,'/');
if(token != NULL)
{
end_index = (token-fpath);
memset(folder, 0, strlen(folder));
}
}
free(folder);
free(temp);
return std::make_shared<VFSFileImpl>(this, fpath, mode);
}
log_e("%s does not exist, no permits for creation", temp);
free(temp);
return FileImplPtr();
}

View File

@ -35,7 +35,7 @@ protected:
friend class VFSFileImpl;
public:
FileImplPtr open(const char* path, const char* mode) override;
FileImplPtr open(const char* path, const char* mode, const bool create) override;
bool exists(const char* path) override;
bool rename(const char* pathFrom, const char* pathTo) override;
bool remove(const char* path) override;

View File

@ -261,6 +261,10 @@ bool HTTPClient::beginInternal(String url, const char* expectedProtocol)
url.remove(0, (index + 3)); // remove http:// or https://
index = url.indexOf('/');
if (index == -1) {
index = url.length();
url += '/';
}
String host = url.substring(0, index);
url.remove(0, index); // remove host part
@ -459,6 +463,17 @@ void HTTPClient::setAuthorization(const char * auth)
}
}
/**
* set the Authorization type for the http request
* @param authType const char *
*/
void HTTPClient::setAuthorizationType(const char * authType)
{
if(authType) {
_authorizationType = authType;
}
}
/**
* set the timeout (ms) for establishing a connection to the server
* @param connectTimeout int32_t
@ -1174,7 +1189,9 @@ bool HTTPClient::sendHeader(const char * type)
if(_base64Authorization.length()) {
_base64Authorization.replace("\n", "");
header += F("Authorization: Basic ");
header += F("Authorization: ");
header += _authorizationType;
header += " ";
header += _base64Authorization;
header += "\r\n";
}

View File

@ -171,6 +171,7 @@ public:
void setUserAgent(const String& userAgent);
void setAuthorization(const char * user, const char * password);
void setAuthorization(const char * auth);
void setAuthorizationType(const char * authType);
void setConnectTimeout(int32_t connectTimeout);
void setTimeout(uint16_t timeout);
@ -251,6 +252,7 @@ protected:
String _headers;
String _userAgent = "ESP32HTTPClient";
String _base64Authorization;
String _authorizationType = "Basic";
/// Response handling
RequestArgument* _currentHeaders = nullptr;

View File

@ -45,7 +45,7 @@ LittleFSImpl::LittleFSImpl()
bool LittleFSImpl::exists(const char* path)
{
File f = open(path, "r");
File f = open(path, "r",false);
return (f == true);
}

View File

@ -36,7 +36,7 @@ SDMMCFS::SDMMCFS(FSImplPtr impl)
: FS(impl), _card(NULL)
{}
bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount_failed)
bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency)
{
if(_card) {
return true;
@ -46,7 +46,7 @@ bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount
sdmmc_host_t host;
host.flags = SDMMC_HOST_FLAG_4BIT;
host.slot = SDMMC_HOST_SLOT_1;
host.max_freq_khz = SDMMC_FREQ_DEFAULT;
host.max_freq_khz = sdmmc_frequency;
host.io_voltage = 3.3f;
host.init = &sdmmc_host_init;
host.set_bus_width = &sdmmc_host_set_bus_width;
@ -54,11 +54,10 @@ bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount
host.set_bus_ddr_mode = &sdmmc_host_set_bus_ddr_mode;
host.set_card_clk = &sdmmc_host_set_card_clk;
host.do_transaction = &sdmmc_host_do_transaction;
host.deinit_p = &sdspi_host_remove_device;
host.deinit = &sdmmc_host_deinit;
host.io_int_enable = &sdmmc_host_io_int_enable;
host.io_int_wait = &sdmmc_host_io_int_wait;
host.command_timeout_ms = 0;
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
#ifdef BOARD_HAS_1BIT_SDMMC
mode1bit = true;
#endif

View File

@ -21,6 +21,13 @@
#include "driver/sdmmc_types.h"
#include "sd_defines.h"
// If reading/writing to the SD card is unstable,
// you can define BOARD_MAX_SDMMC_FREQ with lower value (Ex. SDMMC_FREQ_DEFAULT)
// in pins_arduino.h for your board variant.
#ifndef BOARD_MAX_SDMMC_FREQ
#define BOARD_MAX_SDMMC_FREQ SDMMC_FREQ_HIGHSPEED
#endif
namespace fs
{
@ -31,7 +38,7 @@ protected:
public:
SDMMCFS(FSImplPtr impl);
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false, bool format_if_mount_failed=false);
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false, bool format_if_mount_failed=false, int sdmmc_frequency=BOARD_MAX_SDMMC_FREQ);
void end();
sdcard_type_t cardType();
uint64_t cardSize();

View File

@ -76,36 +76,24 @@ void setup() {
//set up slave select pins as outputs as the Arduino API
//doesn't handle automatically pulling SS low
pinMode(VSPI_SS, OUTPUT); //VSPI SS
pinMode(HSPI_SS, OUTPUT); //HSPI SS
pinMode(vspi->pinSS(), OUTPUT); //VSPI SS
pinMode(hspi->pinSS(), OUTPUT); //HSPI SS
}
// the loop function runs over and over again until power down or reset
void loop() {
//use the SPI buses
vspiCommand();
hspiCommand();
spiCommand(vspi, 0b01010101); // junk data to illustrate usage
spiCommand(hspi, 0b11001100);
delay(100);
}
void vspiCommand() {
byte data = 0b01010101; // junk data to illustrate usage
void spiCommand(SPIClass *spi, byte data) {
//use it as you would the regular arduino SPI API
vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(VSPI_SS, LOW); //pull SS slow to prep other end for transfer
vspi->transfer(data);
digitalWrite(VSPI_SS, HIGH); //pull ss high to signify end of data transfer
vspi->endTransaction();
}
void hspiCommand() {
byte stuff = 0b11001100;
hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(HSPI_SS, LOW);
hspi->transfer(stuff);
digitalWrite(HSPI_SS, HIGH);
hspi->endTransaction();
spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer
spi->transfer(data);
digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer
spi->endTransaction();
}

View File

@ -83,6 +83,7 @@ public:
void writePattern(const uint8_t * data, uint8_t size, uint32_t repeat);
spi_t * bus(){ return _spi; }
int8_t pinSS() { return _ss; }
};
extern SPIClass SPI;

View File

@ -39,7 +39,7 @@ SPIFFSImpl::SPIFFSImpl()
bool SPIFFSImpl::exists(const char* path)
{
File f = open(path, "r");
File f = open(path, "r",false);
return (f == true) && !f.isDirectory();
}

View File

@ -230,7 +230,7 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance){
// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol){
log_v("instance: %u, protocol:%u", instance, protocol);
arduino_usb_hid_event_data_t p = {0};
arduino_usb_hid_event_data_t p;
p.instance = instance;
p.set_protocol.protocol = protocol;
arduino_usb_event_post(ARDUINO_USB_HID_EVENTS, ARDUINO_USB_HID_SET_PROTOCOL_EVENT, &p, sizeof(arduino_usb_hid_event_data_t), portMAX_DELAY);
@ -241,7 +241,7 @@ void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol){
// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms).
bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate){
log_v("instance: %u, idle_rate:%u", instance, idle_rate);
arduino_usb_hid_event_data_t p = {0};
arduino_usb_hid_event_data_t p;
p.instance = instance;
p.set_idle.idle_rate = idle_rate;
arduino_usb_event_post(ARDUINO_USB_HID_EVENTS, ARDUINO_USB_HID_SET_IDLE_EVENT, &p, sizeof(arduino_usb_hid_event_data_t), portMAX_DELAY);

View File

@ -61,7 +61,7 @@ void USBHIDKeyboard::onEvent(arduino_usb_hid_keyboard_event_t event, esp_event_h
void USBHIDKeyboard::_onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t len){
if(report_id == HID_REPORT_ID_KEYBOARD){
arduino_usb_hid_keyboard_event_data_t p = {0};
arduino_usb_hid_keyboard_event_data_t p;
p.leds = buffer[0];
arduino_usb_event_post(ARDUINO_USB_HID_KEYBOARD_EVENTS, ARDUINO_USB_HID_KEYBOARD_LED_EVENT, &p, sizeof(arduino_usb_hid_keyboard_event_data_t), portMAX_DELAY);
}

View File

@ -124,7 +124,7 @@ uint16_t USBHIDVendor::_onGetFeature(uint8_t report_id, uint8_t* buffer, uint16_
return 0;
}
memcpy(buffer, feature, len);
arduino_usb_hid_vendor_event_data_t p = {0};
arduino_usb_hid_vendor_event_data_t p;
p.buffer = feature;
p.len = len;
arduino_usb_event_post(ARDUINO_USB_HID_VENDOR_EVENTS, ARDUINO_USB_HID_VENDOR_GET_FEATURE_EVENT, &p, sizeof(arduino_usb_hid_vendor_event_data_t), portMAX_DELAY);
@ -136,7 +136,7 @@ void USBHIDVendor::_onSetFeature(uint8_t report_id, const uint8_t* buffer, uint1
return;
}
memcpy(feature, buffer, len);
arduino_usb_hid_vendor_event_data_t p = {0};
arduino_usb_hid_vendor_event_data_t p;
p.buffer = feature;
p.len = len;
arduino_usb_event_post(ARDUINO_USB_HID_VENDOR_EVENTS, ARDUINO_USB_HID_VENDOR_SET_FEATURE_EVENT, &p, sizeof(arduino_usb_hid_vendor_event_data_t), portMAX_DELAY);
@ -153,7 +153,7 @@ void USBHIDVendor::_onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t
break;
}
}
arduino_usb_hid_vendor_event_data_t p = {0};
arduino_usb_hid_vendor_event_data_t p;
p.buffer = buffer;
p.len = len;
arduino_usb_event_post(ARDUINO_USB_HID_VENDOR_EVENTS, ARDUINO_USB_HID_VENDOR_OUTPUT_EVENT, &p, sizeof(arduino_usb_hid_vendor_event_data_t), portMAX_DELAY);

View File

@ -40,8 +40,8 @@ uint16_t tusb_vendor_load_descriptor(uint8_t * dst, uint8_t * itf)
}
void tud_vendor_rx_cb(uint8_t itf){
log_v("%u", len);
size_t len = tud_vendor_n_available(itf);
log_v("%u", len);
if(len){
uint8_t buffer[len];
len = tud_vendor_n_read(itf, buffer, len);
@ -146,7 +146,7 @@ void USBVendor::_onRX(const uint8_t* buffer, size_t len){
break;
}
}
arduino_usb_vendor_event_data_t p = {0};
arduino_usb_vendor_event_data_t p;
p.data.len = len;
arduino_usb_event_post(ARDUINO_USB_VENDOR_EVENTS, ARDUINO_USB_VENDOR_DATA_EVENT, &p, sizeof(arduino_usb_vendor_event_data_t), portMAX_DELAY);
}

View File

@ -25,6 +25,8 @@
index.htm is the default index (works on subfolders as well)
upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit
To retrieve the contents of SDcard, visit http://esp32sd.local/list?dir=/
dir is the argument that needs to be passed to the function PrintDirectory via HTTP Get request.
*/
#include <WiFi.h>

View File

@ -542,6 +542,20 @@ bool tcpipInit(){
* */
static bool lowLevelInitDone = false;
bool WiFiGenericClass::_wifiUseStaticBuffers = false;
bool WiFiGenericClass::useStaticBuffers(){
return _wifiUseStaticBuffers;
}
void WiFiGenericClass::useStaticBuffers(bool bufferMode){
if (lowLevelInitDone) {
log_w("WiFi already started. Call WiFi.mode(WIFI_MODE_NULL) before setting Static Buffer Mode.");
}
_wifiUseStaticBuffers = bufferMode;
}
bool wifiLowLevelInit(bool persistent){
if(!lowLevelInitDone){
lowLevelInitDone = true;
@ -557,6 +571,16 @@ bool wifiLowLevelInit(bool persistent){
}
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
if(!WiFiGenericClass::useStaticBuffers()) {
cfg.static_tx_buf_num = 0;
cfg.dynamic_tx_buf_num = 32;
cfg.tx_buf_type = 1;
cfg.cache_tx_buf_num = 1; // can't be zero!
cfg.static_rx_buf_num = 4;
cfg.dynamic_rx_buf_num = 32;
}
esp_err_t err = esp_wifi_init(&cfg);
if(err){
log_e("esp_wifi_init %d", err);
@ -644,7 +668,6 @@ wifi_ps_type_t WiFiGenericClass::_sleepEnabled = WIFI_PS_MIN_MODEM;
WiFiGenericClass::WiFiGenericClass()
{
}
const char * WiFiGenericClass::getHostname()

View File

@ -172,19 +172,23 @@ class WiFiGenericClass
bool setTxPower(wifi_power_t power);
wifi_power_t getTxPower();
bool initiateFTM(uint8_t frm_count=16, uint16_t burst_period=2, uint8_t channel=0, const uint8_t * mac=NULL);
bool initiateFTM(uint8_t frm_count=16, uint16_t burst_period=2, uint8_t channel=1, const uint8_t * mac=NULL);
static const char * getHostname();
static bool setHostname(const char * hostname);
static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); }
static esp_err_t _eventCallback(arduino_event_t *event);
static void useStaticBuffers(bool bufferMode);
static bool useStaticBuffers();
protected:
static bool _persistent;
static bool _long_range;
static wifi_mode_t _forceSleepLastMode;
static wifi_ps_type_t _sleepEnabled;
static bool _wifiUseStaticBuffers;
static int setStatusBits(int bits);
static int clearStatusBits(int bits);

View File

@ -66,3 +66,18 @@ To use PSK:
encryption for the connection
Please see the WiFiClientPSK example.
Specifying the ALPN Protocol
----------------------------
Application-Layer Protocol Negotiation (ALPN) is a Transport Layer Security (TLS) extension that allows
the application layer to negotiate which protocol should be performed over a secure connection in a manner
that avoids additional round trips and which is independent of the application-layer protocols.
For example, this is used with AWS IoT Custom Authorizers where an MQTT client must set the ALPN protocol to ```mqtt```:
```
const char *aws_protos[] = {"mqtt", NULL};
...
wiFiClient.setAlpnProtocols(aws_protos);
```

View File

@ -0,0 +1,97 @@
// WiFiClientShowPeerCredentials
//
// Example of a establishing a secure connection and then
// showing the fingerprint of the certificate. This can
// be useful in an IoT setting to know for sure that you
// are connecting to the right server. Especally in
// situations where you cannot hardcode a trusted root
// certificate for long periods of time (as they tend to
// get replaced more often than the lifecycle of IoT
// hardware).
//
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#ifndef WIFI_NETWORK
#define WIFI_NETWORK "MyWifiNetwork"
#endif
#ifndef WIFI_PASSWD
#define WIFI_PASSWD "MySecretWifiPassword"
#endif
#define URL "https://arduino.cc"
void demo() {
WiFiClientSecure *client = new WiFiClientSecure;
client->setInsecure(); //
HTTPClient https;
if (!https.begin(*client, URL )) {
Serial.println("HTTPS setup failed");
return;
};
https.setTimeout(5000);
int httpCode = https.GET();
if (httpCode != 200) {
Serial.print("Connect failed: ");
Serial.println(https.errorToString(httpCode));
return;
}
const mbedtls_x509_crt* peer = client->getPeerCertificate();
// Show general output / certificate information
//
char buf[1024];
int l = mbedtls_x509_crt_info (buf, sizeof(buf), "", peer);
if (l <= 0) {
Serial.println("Peer conversion to printable buffer failed");
return;
};
Serial.println();
Serial.println(buf);
uint8_t fingerprint_remote[32];
if (!client->getFingerprintSHA256(fingerprint_remote)) {
Serial.println("Failed to get the fingerprint");
return;
}
// Fingerprint late 2021
Serial.println("Expecting Fingerprint (SHA256): 70 CF A4 B7 5D 09 E9 2A 52 A8 B6 85 B5 0B D6 BE 83 47 83 5B 3A 4D 3C 3E 32 30 EC 1D 61 98 D7 0F");
Serial.print( " Received Fingerprint (SHA256): ");
for (int i = 0; i < 32; i++) {
Serial.print(fingerprint_remote[i], HEX);
Serial.print(" ");
};
Serial.println("");
};
void setup() {
Serial.begin(115200);
Serial.println("Started " __FILE__ " build " __DATE__ " " __TIME__);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NETWORK, WIFI_PASSWD);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Wifi fail - rebooting");
delay(5000);
ESP.restart();
}
}
void loop() {
bool already_tried = false;
if ((millis() < 1000) || already_tried)
return;
already_tried = true;
// Run the test just once.
demo();
}

View File

@ -29,6 +29,7 @@ connected KEYWORD2
setCACert KEYWORD2
setCertificate KEYWORD2
setPrivateKey KEYWORD2
setAlpnProtocols KEYWORD2
#######################################
# Constants (LITERAL1)

View File

@ -43,6 +43,7 @@ WiFiClientSecure::WiFiClientSecure()
_pskIdent = NULL;
_psKey = NULL;
next = NULL;
_alpn_protos = NULL;
}
@ -66,6 +67,7 @@ WiFiClientSecure::WiFiClientSecure(int sock)
_pskIdent = NULL;
_psKey = NULL;
next = NULL;
_alpn_protos = NULL;
}
WiFiClientSecure::~WiFiClientSecure()
@ -127,7 +129,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_ce
if(_timeout > 0){
sslclient->handshake_timeout = _timeout;
}
int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure);
int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos);
_lastError = ret;
if (ret < 0) {
log_e("start_ssl_client: %d", ret);
@ -147,7 +149,7 @@ int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskId
if(_timeout > 0){
sslclient->handshake_timeout = _timeout;
}
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure);
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos);
_lastError = ret;
if (ret < 0) {
log_e("start_ssl_client: %d", ret);
@ -341,3 +343,8 @@ void WiFiClientSecure::setHandshakeTimeout(unsigned long handshake_timeout)
{
sslclient->handshake_timeout = handshake_timeout * 1000;
}
void WiFiClientSecure::setAlpnProtocols(const char **alpn_protos)
{
_alpn_protos = alpn_protos;
}

View File

@ -31,7 +31,7 @@ protected:
sslclient_context *sslclient;
int _lastError = 0;
int _peek = -1;
int _peek = -1;
int _timeout = 0;
bool _use_insecure;
const char *_CA_cert;
@ -39,6 +39,7 @@ protected:
const char *_private_key;
const char *_pskIdent; // identity for PSK cipher suites
const char *_psKey; // key in hex for PSK cipher suites
const char **_alpn_protos;
public:
WiFiClientSecure *next;
@ -53,7 +54,7 @@ public:
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
int peek();
int peek();
size_t write(uint8_t data);
size_t write(const uint8_t *buf, size_t size);
int available();
@ -73,7 +74,9 @@ public:
bool loadPrivateKey(Stream& stream, size_t size);
bool verify(const char* fingerprint, const char* domain_name);
void setHandshakeTimeout(unsigned long handshake_timeout);
void setAlpnProtocols(const char **alpn_protos);
const mbedtls_x509_crt* getPeerCertificate() { return mbedtls_ssl_get_peer_cert(&sslclient->ssl_ctx); };
bool getFingerprintSHA256(uint8_t sha256_result[32]) { return get_peer_fingerprint(sslclient, sha256_result); };
int setTimeout(uint32_t seconds){ return 0; }
operator bool()

View File

@ -51,7 +51,7 @@ void ssl_init(sslclient_context *ssl_client)
}
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure)
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos)
{
char buf[512];
int ret, flags;
@ -156,6 +156,13 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
return handle_error(ret);
}
if (alpn_protos != NULL) {
log_v("Setting ALPN protocols");
if ((ret = mbedtls_ssl_conf_alpn_protocols(&ssl_client->ssl_conf, alpn_protos) ) != 0) {
return handle_error(ret);
}
}
// MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and
// MBEDTLS_SSL_VERIFY_NONE if not.
@ -418,22 +425,10 @@ bool verify_ssl_fingerprint(sslclient_context *ssl_client, const char* fp, const
fingerprint_local[i] = low | (high << 4);
}
// Get certificate provided by the peer
const mbedtls_x509_crt* crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx);
if (!crt)
{
log_d("could not fetch peer certificate");
return false;
}
// Calculate certificate's SHA256 fingerprint
uint8_t fingerprint_remote[32];
mbedtls_sha256_context sha256_ctx;
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha256_starts(&sha256_ctx, false);
mbedtls_sha256_update(&sha256_ctx, crt->raw.p, crt->raw.len);
mbedtls_sha256_finish(&sha256_ctx, fingerprint_remote);
if(!get_peer_fingerprint(ssl_client, fingerprint_remote))
return false;
// Check if fingerprints match
if (memcmp(fingerprint_local, fingerprint_remote, 32))
@ -449,6 +444,28 @@ bool verify_ssl_fingerprint(sslclient_context *ssl_client, const char* fp, const
return true;
}
bool get_peer_fingerprint(sslclient_context *ssl_client, uint8_t sha256[32])
{
if (!ssl_client) {
log_d("Invalid ssl_client pointer");
return false;
};
const mbedtls_x509_crt* crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx);
if (!crt) {
log_d("Failed to get peer cert.");
return false;
};
mbedtls_sha256_context sha256_ctx;
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha256_starts(&sha256_ctx, false);
mbedtls_sha256_update(&sha256_ctx, crt->raw.p, crt->raw.len);
mbedtls_sha256_finish(&sha256_ctx, sha256);
return true;
}
// Checks if peer certificate has specified domain in CN or SANs
bool verify_ssl_dn(sslclient_context *ssl_client, const char* domain_name)
{

View File

@ -29,12 +29,12 @@ typedef struct sslclient_context {
void ssl_init(sslclient_context *ssl_client);
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure);
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos);
void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key);
int data_to_read(sslclient_context *ssl_client);
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, size_t len);
int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length);
bool verify_ssl_fingerprint(sslclient_context *ssl_client, const char* fp, const char* domain_name);
bool verify_ssl_dn(sslclient_context *ssl_client, const char* domain_name);
bool get_peer_fingerprint(sslclient_context *ssl_client, uint8_t sha256[32]);
#endif

View File

@ -1,276 +0,0 @@
# Debugging I2C
With the release of Arduino-ESP32 V1.0.1 the I2C subsystem contains code to exhaustively report communication errors.
* Basic debugging can be enable by setting the *CORE DEBUG LEVEL* at or above *ERROR*. All errors will be directed the the *DEBUG OUTPUT* normally connected to `Serial()`.
* Enhanced debugging can be used to generate specified information at specific positions during the i2c communication sequence. Increase *CORE DEBUG LEVEL* to ***DEBUG***
## Enable Debug Buffer
The Enhanced debug features are enabled by uncommenting the `\\#define ENABLE_I2C_DEBUG_BUFFER` at line 45 of `esp32-hal-i2c.c`.
* When Arduino-Esp32 is installed in Windows with Arduino Boards Manager, `esp32-hal-i2c.c` can be found in:
`C:\Users\{user}\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\cores\esp32\`
* When Arduino-Esp32 Development version is installed from GitHub, `esp32-hal-i2c.c` can be found in:
`{arduino Sketch}\hardware\espressif\esp32\cores\esp32\`
```c++
//#define ENABLE_I2C_DEBUG_BUFFER
```
Change it to:
```c++
#define ENABLE_I2C_DEBUG_BUFFER
```
and recompile/upload the resulting code to your ESP32.
Enabling this `#define` will consume an additional 2570 bytes of RAM and include a commensurate amount of code FLASH. If you see the message `"Debug Buffer not Enabled"` in your console log I would suggest you un-comment the line and regenerate the error. Additional information will be supplied on the log console.
## Manually controlled Debugging
Manual logging of the i2c control data buffers can be accomplished by using the debug control function of `Wire()`:
```c++
uint32_t setDebugFlags( uint32_t setBits, uint32_t resetBits);
```
`setBits`, and `resetBits` manually cause output of the control structures to the log console. They are bit fields that enable/disable the reporting of individual control structures during specific phases of the i2c communications sequence. The 32bit values are divided into four 8bit fields. Currently only five bits are defined. ***If an error is detected during normal operations, the relevant control structure will bit added to the log irrespective of the current debug flags.***
* **bit 0** causes DumpI2c to execute
header information about current communications event,
and the dataQueue elements showing the logical i2c transaction commands
* **bit 1** causes DumpInts to execute
Actual sequence of interrupts handled during last communications event, cleared on entry into `ProcQueue()`.
* **bit 2** causes DumpCmdqueue to execute
The last block of commands to the i2c peripheral.
* **bit 3** causes DumpStatus to execute
A descriptive display of the 32bit i2c peripheral status word.
* **bit 4** causes DumpFifo to execute
A buffer listing the sequence of data added to the txFifo of the i2c peripheral.
Of the four division, only three are currently implemented:
* 0xXX - - - - - - : at entry of ProcQueue (`bitFlags << 24`)
* 0x - - XX - - - - : at exit of ProcQueue (`bitFlags << 16`)
* 0x - - - - - - XX : at entry of Flush (`bitFlags`)
For example, to display the sequence of Interrupts processed during the i2c communication transaction, **bit 1** would be set, and, since this information on Interrupt usage would only be valid after the communications have completed, the locus would be *at exit of ProcQueue*. The following code would be necessary.
### code
```c++
uint8_t flag = 1 << 1; // turn on bit 1
uint32_t debugFlag = flag << 16; // correctly position the 8bits of flag as the second byte of setBits.
Wire.setDebugFlags(debugFlag,0);// resetBits=0 says leave all current setBits as is.
Wire.requestFrom(id,byteCount); // read byteCount bytes from slave at id
Wire.setDebugFlags(0,debugFlag); // don't add any new debug, remove debugFlag
```
### output of log console
```
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x005baac5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x005baac5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x005baac6
```
# Debug Log example
### Code
To read eight bytes of data from a DS1307 RTCC
```
uint32_t debugFlag = 0x001F0000;
uint8_t ID = 0x68;
uint8_t block=8;
if(debugFlag >0){
Wire.setDebugFlags(debugFlag,0);
}
Wire.beginTransmission(ID);
Wire.write(lowByte(addr));
if((err=Wire.endTransmission(false))!=0) {
Serial.printf(" EndTransmission=%d(%s)",Wire.lastError(),Wire.getErrorText(Wire.lastError()));
if(err!=2) {
Serial.printf(", resetting\n");
if( !Wire.begin()) Serial.printf(" Reset Failed\n");
if(debugFlag >0) Wire.setDebugFlags(0,debugFlag);
return;
} else {
Serial.printf(", No Device present, aborting\n");
currentCommand= NO_COMMAND;
return;
}
}
err = Wire.requestFrom(ID,block,true);
if(debugFlag >0){
Wire.setDebugFlags(0,debugFlag);
}
```
### output of log console
```
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdc78
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb843c
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb85c4 bits=10
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb85f4
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb858c
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=2
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=1
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=0
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x001F0000
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [0] 7bit 68 W buf@=0x3ffc04b2, len=1, pos=1, ctrl=11101
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: . 00
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [1] 7bit 68 R STOP buf@=0x3ffc042c, len=8, pos=8, ctrl=11111
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: 5P...... 35 50 07 06 13 09 18 00
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x000073d5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x000073d5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x000073d6
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 0] Y RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 1] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 2] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 3] Y RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 4] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 5] Y READ val[0] exp[0] en[0] bytes[7]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 6] Y READ val[1] exp[0] en[0] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 7] Y STOP val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 8] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 9] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [10] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [11] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [12] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [13] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [14] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [15] N RSTART val[0] exp[0] en[0] bytes[0]
[I][esp32-hal-i2c.c:385] i2cDumpStatus(): ack(0) sl_rw(0) to(0) arb(0) busy(0) sl(1) trans(0) rx(0) tx(0) sclMain(5) scl(6)
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): WRITE 0x68 0
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): READ 0x68
```
## Explaination of log output
### DumpI2c
```
[I][esp32-hal-i2c.c:437] i2cTriggerDumps(): after ProcQueue
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdc78
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb843c
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb85c4 bits=10
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb85f4
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb858c
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=2
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=1
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=0
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x001F0000
```
variable | description
---- | ----
**i2c** | *memory address for control block*
**dev** | *memory address for access to i2c peripheral registers*
**date** | *revision date of peripheral silicon 2016, 42 week*
**lock** | *hal lock handle*
**num** | *0,1 which peripheral is being controlled*
**mode** | *configuration of driver 0=none, 1=MASTER, 2=SLAVE, 3=MASTER and SLAVE*
**stage** | *internal STATE of driver 0=not configured, 1=startup, 2=running, 3=done*
**error** | *internal ERROR status 0=not configured, 1=ok, 2=error, 3=address NAK, 4=data NAK, 5=arbitration loss, 6=timeout*
**event** | *handle for interprocess FreeRTOS eventSemaphore for communication between ISR and APP*
**intr_handle** | *FreeRTOS handle for allocated interrupt*
**dq** | *memory address for data queue control block*
**queueCount** | *number of data operations in queue control block*
**queuePos** | *last executed data block*
**errorByteCnt** | *position in current data block when error occured -1=address byte*
**errorQueue** | *queue that was executing when error occurred*
**debugFlags** | *current specified error bits*
### DQ data
```
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [0] 7bit 68 W buf@=0x3ffc04b2, len=1, pos=1, ctrl=11101
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: . 00
[I][esp32-hal-i2c.c:288] i2cDumpDqData(): [1] 7bit 68 R STOP buf@=0x3ffc042c, len=8, pos=8, ctrl=11111
[I][esp32-hal-i2c.c:306] i2cDumpDqData(): 0x0000: 5P...... 35 50 07 06 13 09 18 00
```
variable | description
--- | ---
**[n]** | *index of data queue element*
**i2c address** | *7bit= 7bit i2c slave address, 10bit= 10bit i2c slave address*
**direction** | *W=Write, R=READ*
**STOP** | *command issued a I2C STOP, else if blank, a RESTART was issued by next dq element.*
**buf@** | *pointer to data buffer*
**len** | *length of data buffer*
**pos** | *last position used in buffer*
**ctrl** | *bit field for data queue control, this bits describe if all necessary commands have been added to peripheral command buffer. in order(START,ADDRESS_Write,DATA,STOP,ADDRESS_value*
**0xnnnn** | *data buffer content, displayable followed by HEX, 32 bytes on a line.*
### DumpInts
```
[I][esp32-hal-i2c.c:346] i2cDumpInts(): 0 row count INTR TX RX Tick
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [01] 0x0001 0x0002 0x0003 0x0000 0x000073d5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [02] 0x0001 0x0200 0x0000 0x0000 0x000073d5
[I][esp32-hal-i2c.c:350] i2cDumpInts(): [03] 0x0001 0x0080 0x0000 0x0008 0x000073d6
```
variable | description
---- | ----
**row** | *array index*
**count** | *number of consecutive, duplicate interrupts*
**INTR** | *bit value of active interrupt (from ..\esp32\tools\sdk\include\soc\soc\i2c_struct.h)*
**TX** | *number of bytes added to txFifo*
**RX** | *number of bytes read from rxFifo*
**Tick** | *current tick counter from xTaskGetTickCountFromISR()*
### DumpCmdQueue
```
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 0] Y RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 1] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 2] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 3] Y RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 4] Y WRITE val[0] exp[0] en[1] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 5] Y READ val[0] exp[0] en[0] bytes[7]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 6] Y READ val[1] exp[0] en[0] bytes[1]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 7] Y STOP val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 8] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [ 9] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [10] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [11] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [12] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [13] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [14] N RSTART val[0] exp[0] en[0] bytes[0]
[E][esp32-hal-i2c.c:243] i2cDumpCmdQueue(): [15] N RSTART val[0] exp[0] en[0] bytes[0]
```
Column | description
---- | ----
**command** | *RSTART= generate i2c START sequence, WRITE= output byte(s), READ= input byte(s), STOP= generate i2c STOP sequence, END= continuation flag for peripheral to pause execution waiting for a refilled command list*
**val** | *value for ACK bit, 0 = LOW, 1= HIGH*
**exp** | *test of ACK bit 0=no, 1=yes*
**en** | *output of val, 0=no, 1=yes*
**bytes** | *number of byte to send(WRITE) or receive(READ) 1..255*
### DumpStatus
```
[I][esp32-hal-i2c.c:385] i2cDumpStatus(): ack(0) sl_rw(0) to(0) arb(0) busy(0) sl(1) trans(0) rx(0) tx(0) sclMain(5) scl(6)
```
variable | description
---- | ----
**ack** | *last value for ACK bit*
**sl_rw** | *mode for SLAVE operation 0=write, 1=read*
**to** | *timeout*
**arb** | *arbitration loss*
**busy** | *bus is inuse by other Master, or SLAVE is holding SCL,SDA*
**sl** | *last address on bus was equal to slave_addr*
**trans** | *a byte has moved though peripheral*
**rx** | *count of bytes in rxFifo*
**tx** | *count of bytes in txFifo*
**sclMain** | *state machine for i2c module. 0: SCL_MAIN_IDLE, 1: SCL_ADDRESS_SHIFT, 2: SCL_ACK_ADDRESS, 3: SCL_RX_DATA, 4: SCL_TX_DATA, 5: SCL_SEND_ACK, 6 :SCL_WAIT_ACK*
**scl** | *SCL clock state. 0: SCL_IDLE, 1: SCL_START, 2: SCL_LOW_EDGE, 3: SCL_LOW, 4: SCL_HIGH_EDGE, 5: SCL_HIGH, 6:SCL_STOP*
### DumpFifo
```
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): WRITE 0x68 0
[I][esp32-hal-i2c.c:424] i2cDumpFifo(): READ 0x68
```
Mode | datavalues
--- | ---
**WRITE** | the following bytes added to the txFifo are in response to a WRITE command
**READ** | the following bytes added to the txFifo are in response to a READ command

View File

@ -0,0 +1,30 @@
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t i = 0;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.begin();
}
void loop() {
delay(5000);
//Write message to the slave
Wire.beginTransmission(I2C_DEV_ADDR);
Wire.printf("Hello World! %u", i++);
uint8_t error = Wire.endTransmission(true);
Serial.printf("endTransmission: %u\n", error);
//Read 16 bytes from the slave
error = Wire.requestFrom(I2C_DEV_ADDR, 16);
Serial.printf("requestFrom: %u\n", error);
if(error){
uint8_t temp[error];
Wire.readBytes(temp, error);
log_print_buf(temp, error);
}
}

View File

@ -0,0 +1,28 @@
#include "Wire.h"
void setup() {
Serial.begin(115200);
Wire.begin();
}
void loop() {
byte error, address;
int nDevices = 0;
delay(5000);
Serial.println("Scanning for I2C devices ...");
for(address = 0x01; address < 0x7f; address++){
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0){
Serial.printf("I2C device found at address 0x%02X\n", address);
nDevices++;
} else if(error != 2){
Serial.printf("Error %d at address 0x%02X\n", error, address);
}
}
if (nDevices == 0){
Serial.println("No I2C devices found");
}
}

View File

@ -0,0 +1,37 @@
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t i = 0;
void onRequest(){
Wire.print(i++);
Wire.print(" Packets.");
Serial.println("onRequest");
}
void onReceive(int len){
Serial.printf("onReceive[%d]: ", len);
while(Wire.available()){
Serial.write(Wire.read());
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.onReceive(onReceive);
Wire.onRequest(onRequest);
Wire.begin((uint8_t)I2C_DEV_ADDR);
#if CONFIG_IDF_TARGET_ESP32
char message[64];
snprintf(message, 64, "%u Packets.", i++);
Wire.slaveWrite((uint8_t *)message, strlen(message));
#endif
}
void loop() {
}

View File

@ -11,13 +11,14 @@
#######################################
begin KEYWORD2
end KEYWORD2
setClock KEYWORD2
setClockStretchLimit KEYWORD2
getClock KEYWORD2
setTimeOut KEYWORD2
getTimeOut KEYWORD2
beginTransmission KEYWORD2
endTransmission KEYWORD2
requestFrom KEYWORD2
send KEYWORD2
receive KEYWORD2
onReceive KEYWORD2
onRequest KEYWORD2
@ -26,6 +27,7 @@ onRequest KEYWORD2
#######################################
Wire KEYWORD2
TwoWire KEYWORD2
#######################################
# Constants (LITERAL1)

View File

@ -20,6 +20,7 @@
Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support
Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support
Modified Nov 2017 by Chuck Todd (ctodd@cableone.net) - ESP32 ISR Support
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
*/
extern "C" {
@ -29,6 +30,7 @@ extern "C" {
}
#include "esp32-hal-i2c.h"
#include "esp32-hal-i2c-slave.h"
#include "Wire.h"
#include "Arduino.h"
@ -36,40 +38,32 @@ TwoWire::TwoWire(uint8_t bus_num)
:num(bus_num & 1)
,sda(-1)
,scl(-1)
,i2c(NULL)
,rxIndex(0)
,rxLength(0)
,rxQueued(0)
,txIndex(0)
,txLength(0)
,txAddress(0)
,txQueued(0)
,transmitting(0)
,last_error(I2C_ERROR_OK)
,_timeOutMillis(50)
,nonStop(false)
#if !CONFIG_DISABLE_HAL_LOCKS
,nonStopTask(NULL)
,lock(NULL)
#endif
,is_slave(false)
,user_onRequest(NULL)
,user_onReceive(NULL)
{}
TwoWire::~TwoWire()
{
flush();
if(i2c) {
i2cRelease(i2c);
i2c=NULL;
end();
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock != NULL){
vSemaphoreDelete(lock);
}
#endif
}
bool TwoWire::setPins(int sdaPin, int sclPin)
{
if(i2c) {
log_e("can not set pins if begin was already called");
return false;
}
sda = sdaPin;
scl = sclPin;
return true;
}
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
bool TwoWire::initPins(int sdaPin, int sclPin)
{
if(sdaPin < 0) { // default param passed
if(num == 0) {
@ -107,14 +101,195 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
sda = sdaPin;
scl = sclPin;
i2c = i2cInit(num, sda, scl, frequency);
if(!i2c) {
return true;
}
bool TwoWire::setPins(int sdaPin, int sclPin)
{
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock == NULL){
lock = xSemaphoreCreateMutex();
if(lock == NULL){
log_e("xSemaphoreCreateMutex failed");
return false;
}
}
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(!i2cIsInit(num)){
initPins(sdaPin, sclPin);
} else {
log_e("bus already initialized. change pins only when not.");
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return !i2cIsInit(num);
}
flush();
return true;
// Slave Begin
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
{
bool started = false;
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock == NULL){
lock = xSemaphoreCreateMutex();
if(lock == NULL){
log_e("xSemaphoreCreateMutex failed");
return false;
}
}
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(is_slave){
log_w("Bus already started in Slave Mode.");
started = true;
goto end;
}
if(i2cIsInit(num)){
log_e("Bus already started in Master Mode.");
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
if(i2cSlaveInit(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
log_e("Slave Init ERROR");
goto end;
}
is_slave = true;
started = true;
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return started;
}
// Master Begin
bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
{
bool started = false;
esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock == NULL){
lock = xSemaphoreCreateMutex();
if(lock == NULL){
log_e("xSemaphoreCreateMutex failed");
return false;
}
}
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(is_slave){
log_e("Bus already started in Slave Mode.");
goto end;
}
if(i2cIsInit(num)){
log_w("Bus already started in Master Mode.");
started = true;
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
err = i2cInit(num, sda, scl, frequency);
started = (err == ESP_OK);
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return started;
}
bool TwoWire::end()
{
esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
if(lock != NULL){
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(is_slave){
err = i2cSlaveDeinit(num);
if(err == ESP_OK){
is_slave = false;
}
} else if(i2cIsInit(num)){
err = i2cDeinit(num);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
}
#endif
return (err == ESP_OK);
}
uint32_t TwoWire::getClock()
{
uint32_t frequency = 0;
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
} else {
#endif
if(is_slave){
log_e("Bus is in Slave Mode");
} else {
i2cGetClock(num, &frequency);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
}
#endif
return frequency;
}
bool TwoWire::setClock(uint32_t frequency)
{
esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return false;
}
#endif
if(is_slave){
log_e("Bus is in Slave Mode");
err = ESP_FAIL;
} else {
err = i2cSetClock(num, frequency);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return (err == ESP_OK);
}
void TwoWire::setTimeOut(uint16_t timeOutMillis)
@ -127,118 +302,104 @@ uint16_t TwoWire::getTimeOut()
return _timeOutMillis;
}
void TwoWire::setClock(uint32_t frequency)
void TwoWire::beginTransmission(uint16_t address)
{
#if CONFIG_IDF_TARGET_ESP32S2
i2c = i2cInit(num, sda, scl, frequency);
if(!i2c) {
if(is_slave){
log_e("Bus is in Slave Mode");
return;
}
#if !CONFIG_DISABLE_HAL_LOCKS
if(nonStop && nonStopTask == xTaskGetCurrentTaskHandle()){
log_e("Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing...");
//release lock
xSemaphoreGive(lock);
}
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return;
}
#endif
i2cSetFrequency(i2c, frequency);
}
size_t TwoWire::getClock()
{
return i2cGetFrequency(i2c);
}
/* stickBreaker Nov 2017 ISR, and bigblock 64k-1
*/
i2c_err_t TwoWire::writeTransmission(uint16_t address, uint8_t *buff, uint16_t size, bool sendStop)
{
last_error = i2cWrite(i2c, address, buff, size, sendStop, _timeOutMillis);
return last_error;
}
i2c_err_t TwoWire::readTransmission(uint16_t address, uint8_t *buff, uint16_t size, bool sendStop, uint32_t *readCount)
{
last_error = i2cRead(i2c, address, buff, size, sendStop, _timeOutMillis, readCount);
return last_error;
}
void TwoWire::beginTransmission(uint16_t address)
{
transmitting = 1;
nonStop = false;
txAddress = address;
txIndex = txQueued; // allow multiple beginTransmission(),write(),endTransmission(false) until endTransmission(true)
txLength = txQueued;
last_error = I2C_ERROR_OK;
}
/*stickbreaker isr
*/
uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransaction(), Wire.write()
{
if(transmitting == 1) {
// txlength is howmany bytes in txbuffer have been use
last_error = writeTransmission(txAddress, &txBuffer[txQueued], txLength - txQueued, sendStop);
if(last_error == I2C_ERROR_CONTINUE){
txQueued = txLength;
} else if( last_error == I2C_ERROR_OK){
rxIndex = 0;
rxLength = rxQueued;
rxQueued = 0;
txQueued = 0; // the SendStop=true will restart all Queueing
}
} else {
last_error = I2C_ERROR_NO_BEGIN;
flush();
}
txIndex = 0;
txLength = 0;
transmitting = 0;
return (last_error == I2C_ERROR_CONTINUE)?I2C_ERROR_OK:last_error; // Don't return Continue for compatibility.
}
/* @stickBreaker 11/2017 fix for ReSTART timeout, ISR
*/
uint8_t TwoWire::endTransmission(bool sendStop)
{
if(is_slave){
log_e("Bus is in Slave Mode");
return 4;
}
esp_err_t err = ESP_OK;
if(sendStop){
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
} else {
//mark as non-stop
nonStop = true;
#if !CONFIG_DISABLE_HAL_LOCKS
nonStopTask = xTaskGetCurrentTaskHandle();
#endif
}
switch(err){
case ESP_OK: return 0;
case ESP_FAIL: return 2;
case ESP_ERR_TIMEOUT: return 5;
default: break;
}
return 4;
}
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop)
{
//use internal Wire rxBuffer, multiple requestFrom()'s may be pending, try to share rxBuffer
uint32_t cnt = rxQueued; // currently queued reads, next available position in rxBuffer
if(cnt < (I2C_BUFFER_LENGTH-1) && (size + cnt) <= I2C_BUFFER_LENGTH) { // any room left in rxBuffer
rxQueued += size;
} else { // no room to receive more!
log_e("rxBuff overflow %d", cnt + size);
cnt = 0;
last_error = I2C_ERROR_MEMORY;
flush();
return cnt;
if(is_slave){
log_e("Bus is in Slave Mode");
return 0;
}
last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt);
rxIndex = 0;
rxLength = cnt;
if( last_error != I2C_ERROR_CONTINUE){ // not a buffered ReSTART operation
// so this operation actually moved data, queuing is done.
rxQueued = 0;
txQueued = 0; // the SendStop=true will restart all Queueing or error condition
esp_err_t err = ESP_OK;
if(nonStop
#if !CONFIG_DISABLE_HAL_LOCKS
&& nonStopTask == xTaskGetCurrentTaskHandle()
#endif
){
if(address != txAddress){
log_e("Unfinished Repeated Start transaction! Expected address do not match! %u != %u", address, txAddress);
return 0;
}
nonStop = false;
rxIndex = 0;
rxLength = 0;
err = i2cWriteReadNonStop(num, address, txBuffer, txLength, rxBuffer, size, _timeOutMillis, &rxLength);
} else {
#if !CONFIG_DISABLE_HAL_LOCKS
//acquire lock
if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return 0;
}
#endif
rxIndex = 0;
rxLength = 0;
err = i2cRead(num, address, rxBuffer, size, _timeOutMillis, &rxLength);
}
if(last_error != I2C_ERROR_OK){ // ReSTART on read does not return any data
cnt = 0;
}
return cnt;
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
#endif
return rxLength;
}
size_t TwoWire::write(uint8_t data)
{
if(transmitting) {
if(txLength >= I2C_BUFFER_LENGTH) {
last_error = I2C_ERROR_MEMORY;
return 0;
}
txBuffer[txIndex] = data;
++txIndex;
txLength = txIndex;
return 1;
if(txLength >= I2C_BUFFER_LENGTH) {
return 0;
}
last_error = I2C_ERROR_NO_BEGIN; // no begin, not transmitting
return 0;
txBuffer[txLength++] = data;
return 1;
}
size_t TwoWire::write(const uint8_t *data, size_t quantity)
@ -262,8 +423,7 @@ int TwoWire::read(void)
{
int value = -1;
if(rxIndex < rxLength) {
value = rxBuffer[rxIndex];
++rxIndex;
value = rxBuffer[rxIndex++];
}
return value;
}
@ -281,11 +441,8 @@ void TwoWire::flush(void)
{
rxIndex = 0;
rxLength = 0;
txIndex = 0;
txLength = 0;
rxQueued = 0;
txQueued = 0;
i2cFlush(i2c); // cleanup
//i2cFlush(num); // cleanup
}
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
@ -333,56 +490,49 @@ uint8_t TwoWire::endTransmission(void)
return endTransmission(true);
}
/* stickbreaker Nov2017 better error reporting
*/
uint8_t TwoWire::lastError()
size_t TwoWire::slaveWrite(const uint8_t * buffer, size_t len)
{
return (uint8_t)last_error;
return i2cSlaveWrite(num, buffer, len, _timeOutMillis);
}
const char ERRORTEXT[] =
"OK\0"
"DEVICE\0"
"ACK\0"
"TIMEOUT\0"
"BUS\0"
"BUSY\0"
"MEMORY\0"
"CONTINUE\0"
"NO_BEGIN\0"
"\0";
char * TwoWire::getErrorText(uint8_t err)
void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, bool stop, void * arg)
{
uint8_t t = 0;
bool found = false;
char * message = (char*)&ERRORTEXT;
while(!found && message[0]) {
found = t == err;
if(!found) {
message = message + strlen(message) + 1;
t++;
}
TwoWire * wire = (TwoWire*)arg;
if(!wire->user_onReceive){
return;
}
if(!found) {
return NULL;
} else {
return message;
for(uint8_t i = 0; i < numBytes; ++i){
wire->rxBuffer[i] = inBytes[i];
}
wire->rxIndex = 0;
wire->rxLength = numBytes;
wire->user_onReceive(numBytes);
}
void TwoWire::onRequestService(uint8_t num, void * arg)
{
TwoWire * wire = (TwoWire*)arg;
if(!wire->user_onRequest){
return;
}
wire->txLength = 0;
wire->user_onRequest();
if(wire->txLength){
wire->slaveWrite((uint8_t*)wire->txBuffer, wire->txLength);
}
}
/*stickbreaker Dump i2c Interrupt buffer, i2c isr Debugging
*/
uint32_t TwoWire::setDebugFlags( uint32_t setBits, uint32_t resetBits){
return i2cDebug(i2c,setBits,resetBits);
void TwoWire::onReceive( void (*function)(int) )
{
user_onReceive = function;
}
bool TwoWire::busy(void){
return ((i2cGetStatus(i2c) & 16 )==16);
// sets function called on slave read
void TwoWire::onRequest( void (*function)(void) )
{
user_onRequest = function;
}
TwoWire Wire = TwoWire(0);
TwoWire Wire1 = TwoWire(1);

View File

@ -20,17 +20,20 @@
Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support
Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support
Modified November 2017 by Chuck Todd <stickbreaker on GitHub> to use ISR and increase stability.
Modified Nov 2021 by Hristo Gochkov <Me-No-Dev> to support ESP-IDF API
*/
#ifndef TwoWire_h
#define TwoWire_h
#include <esp32-hal.h>
#if !CONFIG_DISABLE_HAL_LOCKS
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#endif
#include "Stream.h"
#define STICKBREAKER 'V1.1.0'
#ifndef I2C_BUFFER_LENGTH
#define I2C_BUFFER_LENGTH 128
#endif
@ -43,28 +46,28 @@ protected:
uint8_t num;
int8_t sda;
int8_t scl;
i2c_t * i2c;
uint8_t rxBuffer[I2C_BUFFER_LENGTH];
uint16_t rxIndex;
uint16_t rxLength;
uint16_t rxQueued; //@stickBreaker
size_t rxIndex;
size_t rxLength;
uint8_t txBuffer[I2C_BUFFER_LENGTH];
uint16_t txIndex;
uint16_t txLength;
size_t txLength;
uint16_t txAddress;
uint16_t txQueued; //@stickbreaker
uint8_t transmitting;
/* slave Mode, not yet Stickbreaker
static user_onRequest uReq[2];
static user_onReceive uRcv[2];
void onRequestService(void);
void onReceiveService(uint8_t*, int);
*/
i2c_err_t last_error; // @stickBreaker from esp32-hal-i2c.h
uint16_t _timeOutMillis;
uint32_t _timeOutMillis;
bool nonStop;
#if !CONFIG_DISABLE_HAL_LOCKS
TaskHandle_t nonStopTask;
SemaphoreHandle_t lock;
#endif
private:
bool is_slave;
void (*user_onRequest)(void);
void (*user_onReceive)(int);
static void onRequestService(uint8_t, void *);
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
bool initPins(int sdaPin, int sclPin);
public:
TwoWire(uint8_t bus_num);
@ -74,20 +77,14 @@ public:
bool setPins(int sda, int scl);
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
// calling will attemp to recover hung bus
void setClock(uint32_t frequency); // change bus clock without initing hardware
size_t getClock(); // current bus clock rate in hz
bool begin(uint8_t slaveAddr, int sda=-1, int scl=-1, uint32_t frequency=0);
bool end();
void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
uint16_t getTimeOut();
uint8_t lastError();
char * getErrorText(uint8_t err);
//@stickBreaker for big blocks and ISR model
i2c_err_t writeTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true);
i2c_err_t readTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true, uint32_t *readCount=NULL);
bool setClock(uint32_t);
uint32_t getClock();
void beginTransmission(uint16_t address);
void beginTransmission(uint8_t address);
@ -134,22 +131,10 @@ public:
void onReceive( void (*)(int) );
void onRequest( void (*)(void) );
uint32_t setDebugFlags( uint32_t setBits, uint32_t resetBits);
bool busy();
size_t slaveWrite(const uint8_t *, size_t);
};
extern TwoWire Wire;
extern TwoWire Wire1;
/*
V1.1.0 08JAN2019 Support CPU Clock frequency changes
V1.0.2 30NOV2018 stop returning I2C_ERROR_CONTINUE on ReSTART operations, regain compatibility with Arduino libs
V1.0.1 02AUG2018 First Fix after release, Correct ReSTART handling, change Debug control, change begin()
to a function, this allow reporting if bus cannot be initialized, Wire.begin() can be used to recover
a hung bus busy condition.
V0.2.2 13APR2018 preserve custom SCL,SDA,Frequency when no parameters passed to begin()
V0.2.1 15MAR2018 Hardware reset, Glitch prevention, adding destructor for second i2c testing
*/
#endif

View File

@ -36,17 +36,17 @@
{
"packager": "esp32",
"name": "riscv32-esp-elf-gcc",
"version": "gcc8_4_0-esp-2021r1"
"version": "gcc8_4_0-esp-2021r2"
},
{
"packager": "esp32",
"name": "xtensa-esp32-elf-gcc",
"version": "gcc8_4_0-esp-2021r1"
"version": "gcc8_4_0-esp-2021r2"
},
{
"packager": "esp32",
"name": "xtensa-esp32s2-elf-gcc",
"version": "gcc8_4_0-esp-2021r1"
"version": "gcc8_4_0-esp-2021r2"
},
{
"packager": "esp32",
@ -69,124 +69,166 @@
"tools": [
{
"name": "riscv32-esp-elf-gcc",
"version": "gcc8_4_0-esp-2021r1",
"version": "gcc8_4_0-esp-2021r2",
"systems": [
{
"host": "x86_64-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"checksum": "SHA-256:3459618f33bbd5f54d7d7783e807cb6eef6472a220f2f1eb3faced735b9d13bb",
"size": "152812483"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"checksum": "SHA-256:812d735063da9d063b374b59f55832a96c41fbd27ddaef19000a75de8607ba21",
"size": "106837189"
},
{
"host": "aarch64-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"checksum": "SHA-256:712f1fbc3e08304a6f32aa18b346b16bbcb413b507b3d4c7c3211bf0d7dc4813",
"size": "103273444"
},
{
"host": "arm-linux-gnueabihf",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"checksum": "SHA-256:24b9e54b348bbd5fb816fc4c52abb47337c702beecdbba840750b7cfb9d38069",
"size": "151726623"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"checksum": "SHA-256:80a3342cda2cd4b6b75ebb2b36d5d12fce7d375cfadadcff01ec3a907f0a16a2",
"size": "103058744"
},
{
"host": "i686-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"checksum": "SHA-256:954d340ebffef12a2ce9be1ea004e6f45a8863f1e6f41f46fd3f04f58499627c",
"size": "155430963"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"checksum": "SHA-256:7f0162a81558ab0ed09d6c5d356def25b5cb3d5c2d61358f20152fa260ccc8ae",
"size": "109447789"
},
{
"host": "x86_64-apple-darwin",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"checksum": "SHA-256:612fb3a3f84f703222327bd16581df8f80fda8cdf137637fe5d611587d1b664e",
"size": "159836199"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"checksum": "SHA-256:3ff7e5427907cf8e271c1f959b70fb01e39625c3caf61a6567e7b38aa0c11578",
"size": "113672945"
},
{
"host": "i686-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/riscv32-esp-elf-gcc8_4_0-esp-2021r1-win32.zip",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r1-win32.zip",
"checksum": "SHA-256:5711eb407ffe44adddbd1281b6b575a5645e7193ca78faefa27dc5bc5b662bec",
"size": "191266312"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-win32.zip",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-win32.zip",
"checksum": "SHA-256:c8ff08883c1456c278fad85e1c43b7c6e251d525683214168655550e85c5b82e",
"size": "140809778"
},
{
"host": "x86_64-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/riscv32-esp-elf-gcc8_4_0-esp-2021r2-win64.zip",
"archiveFileName": "riscv32-esp-elf-gcc8_4_0-esp-2021r2-win64.zip",
"checksum": "SHA-256:6c04cb4728db928ec6473e63146b695b6dec686a0d40dd73dd3353f05247b19e",
"size": "142365782"
}
]
},
{
"name": "xtensa-esp32-elf-gcc",
"version": "gcc8_4_0-esp-2021r1",
"version": "gcc8_4_0-esp-2021r2",
"systems": [
{
"host": "x86_64-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"checksum": "SHA-256:44a0b467b9d2b759ab48b2f27aed684581f33c96e2842992781c4e045992c5b0",
"size": "86361217"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"checksum": "SHA-256:3eb3d68b27fa6ba5af6f88da21cb8face9be0094daaa8960793cfe570ab785ff",
"size": "90565318"
},
{
"host": "aarch64-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"checksum": "SHA-256:aa534be24e45e06b7080a6a3bb8cd9e3cfb818f5f8bce2244d7cfb5e91336541",
"size": "86860292"
},
{
"host": "arm-linux-gnueabihf",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"checksum": "SHA-256:fdacdb2a7bbf6293bcafda9b52463a4da8a2f3b7e1df9f83d35ff9d1efa22012",
"size": "84520407"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"checksum": "SHA-256:f0e49ce06fe7833ff5d76961dc2dac5449d320f823bb8c05a302cf85a3a6eb04",
"size": "86183421"
},
{
"host": "i686-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"checksum": "SHA-256:e2024096492dfaa50fc6ac336cd8faa2e395e8cebb617753eab0b5f16d3dd0dc",
"size": "88375391"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"checksum": "SHA-256:06de09b74652de43e5b22db3b7fc992623044baa75e9faaab68317a986715ba3",
"size": "92582250"
},
{
"host": "x86_64-apple-darwin",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"checksum": "SHA-256:7bbc6a2b94f009cd8a3351b9c7acf7a5caa1c4d3700500ead60f84965386a61b",
"size": "93357296"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"checksum": "SHA-256:96443f69c8569417c780ee749d91ef33cffe22153fffa30a0fbf12107d87381b",
"size": "97808961"
},
{
"host": "i686-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32-elf-gcc8_4_0-esp-2021r1-win32.zip",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r1-win32.zip",
"checksum": "SHA-256:e4f9fdda192abfc9807e3e7fcd6e9fea30c1a0cf3f3c5a5c961b5114fc8c9b7e",
"size": "105603626"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win32.zip",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win32.zip",
"checksum": "SHA-256:076a4171bdc33e5ced3952efffb233d70263dfa760e636704050597a9edf61db",
"size": "112578260"
},
{
"host": "x86_64-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win64.zip",
"archiveFileName": "xtensa-esp32-elf-gcc8_4_0-esp-2021r2-win64.zip",
"checksum": "SHA-256:c35b7998f7f503e0cb22055d1e279ae14b6b0e09bb3ff3846b17d552ece9c247",
"size": "115278695"
}
]
},
{
"name": "xtensa-esp32s2-elf-gcc",
"version": "gcc8_4_0-esp-2021r1",
"version": "gcc8_4_0-esp-2021r2",
"systems": [
{
"host": "x86_64-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-amd64.tar.gz",
"checksum": "SHA-256:b127baccfe6949ee7eaf3d0782ea772750a9b8e2732b16ce6bcc9dcd91f7209a",
"size": "86687290"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz",
"checksum": "SHA-256:a6e0947c92b823ca04f062522249f0a428357e0b056f1ff4c6bcabef83cf63a7",
"size": "90901736"
},
{
"host": "aarch64-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-arm64.tar.gz",
"checksum": "SHA-256:d2e5600fc194b508bd393b236a09fd62ed70afb6c36619d4b106b696a56ca66d",
"size": "87176557"
},
{
"host": "arm-linux-gnueabihf",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-armel.tar.gz",
"checksum": "SHA-256:7ca0d240f11e1c53c01a56257b0c968f876ab405142d1068d8c9b456d939554c",
"size": "84916701"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz",
"checksum": "SHA-256:3fff4199e986dd74660f17ca27d9414cb98f1b911a7f13bb3b22e784cb1156cf",
"size": "86581102"
},
{
"host": "i686-pc-linux-gnu",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-linux-i686.tar.gz",
"checksum": "SHA-256:9941f993ff84d1c606b45ffbeeb7bcdc5a72cf24e787bb9230390510fe3511c6",
"size": "88699953"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-linux-i686.tar.gz",
"checksum": "SHA-256:7732f9fb371d36b6b324820e300beecc33c2719921a61cf1cdb5bc625016b346",
"size": "92875986"
},
{
"host": "x86_64-apple-darwin",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-macos.tar.gz",
"checksum": "SHA-256:4b55b1a9ca7fc945be6fc3513802b6cece9264bee4cbca76013569cec2695973",
"size": "93757895"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-macos.tar.gz",
"checksum": "SHA-256:e6dd32782fcff8f633299b97d1c671d6b6513390aca2ddbd7543c2cc62e72d7e",
"size": "98212907"
},
{
"host": "i686-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r1/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-win32.zip",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r1-win32.zip",
"checksum": "SHA-256:c94ec1e45c81b7e4944d216bab4aa41d46849768d7761fd691661dab1a3df828",
"size": "106013515"
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win32.zip",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win32.zip",
"checksum": "SHA-256:41b917b35f6fbe7d30b7de91c32cf348c406acfa729a1eabc450d040dc46fbe2",
"size": "113022469"
},
{
"host": "x86_64-mingw32",
"url": "https://github.com/espressif/crosstool-NG/releases/download/esp-2021r2/xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win64.zip",
"archiveFileName": "xtensa-esp32s2-elf-gcc8_4_0-esp-2021r2-win64.zip",
"checksum": "SHA-256:a764c1a0ee743d69f8cbfadbe4426a2c15c0e233b0894244c7cadf3b4d7dd32a",
"size": "115696999"
}
]
},

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,7 @@ SUBTYPES = {
'coredump': 0x03,
'nvs_keys': 0x04,
'efuse': 0x05,
'undefined': 0x06,
'esphttpd': 0x80,
'fat': 0x81,
'spiffs': 0x82,
@ -91,6 +92,19 @@ def get_subtype_as_int(ptype, subtype):
return subtype
ALIGNMENT = {
APP_TYPE: 0x10000,
DATA_TYPE: 0x4,
}
STRICT_DATA_ALIGNMENT = 0x1000
def get_alignment_for_type(ptype):
return ALIGNMENT.get(ptype, ALIGNMENT[DATA_TYPE])
quiet = False
md5sum = True
secure = False
@ -143,8 +157,8 @@ class PartitionTable(list):
continue
try:
res.append(PartitionDefinition.from_csv(line, line_no + 1))
except InputError as e:
raise InputError('Error at line %d: %s' % (line_no + 1, e))
except InputError as err:
raise InputError('Error at line %d: %s' % (line_no + 1, err))
except Exception:
critical('Unexpected error parsing CSV line %d: %s' % (line_no + 1, line))
raise
@ -160,7 +174,7 @@ class PartitionTable(list):
raise InputError('CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x'
% (e.line_no, e.offset, last_end))
if e.offset is None:
pad_to = 0x10000 if e.type == APP_TYPE else 4
pad_to = get_alignment_for_type(e.type)
if last_end % pad_to != 0:
last_end += pad_to - (last_end % pad_to)
e.offset = last_end
@ -210,10 +224,10 @@ class PartitionTable(list):
# print sorted duplicate partitions by name
if len(duplicates) != 0:
print('A list of partitions that have the same name:')
critical('A list of partitions that have the same name:')
for p in sorted(self, key=lambda x:x.name):
if len(duplicates.intersection([p.name])) != 0:
print('%s' % (p.to_csv()))
critical('%s' % (p.to_csv()))
raise InputError('Partition names must be unique')
# check for overlaps
@ -225,6 +239,18 @@ class PartitionTable(list):
raise InputError('Partition at 0x%x overlaps 0x%x-0x%x' % (p.offset, last.offset, last.offset + last.size - 1))
last = p
# check that otadata should be unique
otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']]
if len(otadata_duplicates) > 1:
for p in otadata_duplicates:
critical('%s' % (p.to_csv()))
raise InputError('Found multiple otadata partitions. Only one partition can be defined with type="data"(1) and subtype="ota"(0).')
if len(otadata_duplicates) == 1 and otadata_duplicates[0].size != 0x2000:
p = otadata_duplicates[0]
critical('%s' % (p.to_csv()))
raise InputError('otadata partition must have size = 0x2000')
def flash_size(self):
""" Return the size that partitions will occupy in flash
(ie the offset the last partition ends at)
@ -274,11 +300,6 @@ class PartitionTable(list):
class PartitionDefinition(object):
MAGIC_BYTES = b'\xAA\x50'
ALIGNMENT = {
APP_TYPE: 0x10000,
DATA_TYPE: 0x04,
}
# dictionary maps flag name (as used in CSV flags list, property name)
# to bit set in flags words in binary format
FLAGS = {
@ -358,7 +379,9 @@ class PartitionDefinition(object):
def parse_subtype(self, strval):
if strval == '':
return 0 # default
if self.type == TYPES['app']:
raise InputError('App partition cannot have an empty subtype')
return SUBTYPES[DATA_TYPE]['undefined']
return parse_int(strval, SUBTYPES.get(self.type, {}))
def parse_address(self, strval):
@ -373,10 +396,15 @@ class PartitionDefinition(object):
raise ValidationError(self, 'Subtype field is not set')
if self.offset is None:
raise ValidationError(self, 'Offset field is not set')
align = self.ALIGNMENT.get(self.type, 4)
align = get_alignment_for_type(self.type)
if self.offset % align:
raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align))
if self.size % align and secure:
# The alignment requirement for non-app partition is 4 bytes, but it should be 4 kB.
# Print a warning for now, make it an error in IDF 5.0 (IDF-3742).
if self.type != APP_TYPE and self.offset % STRICT_DATA_ALIGNMENT:
critical('WARNING: Partition %s not aligned to 0x%x.'
'This is deprecated and will be considered an error in the future release.' % (self.name, STRICT_DATA_ALIGNMENT))
if self.size % align and secure and self.type == APP_TYPE:
raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align))
if self.size is None:
raise ValidationError(self, 'Size field is not set')

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -244,6 +244,14 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *
*/
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc);
/**
* @brief Returns number of ota partitions provided in partition table.
*
* @return
* - Number of OTA partitions
*/
uint8_t esp_ota_get_app_partition_count(void);
/**
* @brief This function is called to indicate that the running app is working well.
*

View File

@ -18,6 +18,11 @@
# define ASIO_NO_TYPEID
# endif // CONFIG_COMPILER_RTTI
//
// Supress OpenSSL deprecation warning, when building ASIO
//
#define ESP_OPENSSL_SUPPRESS_LEGACY_WARNING
//
// LWIP compatibility inet and address macros/functions
//

View File

@ -119,6 +119,15 @@ bool bootloader_common_label_search(const char *list, char *label);
*/
void bootloader_configure_spi_pins(int drv);
/**
* @brief Get flash CS IO
*
* Can be determined by eFuse values, or the default value
*
* @return Flash CS IO
*/
uint8_t bootloader_flash_get_cs_io(void);
/**
* @brief Calculates a sha-256 for a given partition or returns a appended digest.
*

View File

@ -10,6 +10,18 @@
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Read flash ID by sending RDID command (0x9F)
* @return flash raw ID
* mfg_id = (ID >> 16) & 0xFF;
flash_id = ID & 0xffff;
*/
uint32_t bootloader_read_flash_id(void);
#if SOC_CACHE_SUPPORT_WRAP
/**
* @brief Set the burst mode setting command for specified wrap mode.
@ -19,3 +31,22 @@
*/
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
#endif
/**
* @brief Unlock Flash write protect.
* Please do not call this function in SDK.
*
* @note This can be overridden because it's attribute weak.
*/
esp_err_t bootloader_flash_unlock(void);
/**
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
*
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
*/
esp_err_t bootloader_flash_xmc_startup(void);
#ifdef __cplusplus
}
#endif

View File

@ -77,4 +77,8 @@ period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm);
uint32_t osi_time_get_os_boottime_ms(void);
// This function returns whether the given |alarm| is active or not.
// Return true if active, false otherwise.
bool osi_alarm_is_active(osi_alarm_t *alarm);
#endif /*_ALARM_H_*/

View File

@ -467,7 +467,7 @@ typedef struct
{
uint16_t rx_len; /*!< pkt rx data length value */
uint16_t tx_len; /*!< pkt tx data length value */
}esp_ble_pkt_data_length_params_t;
} esp_ble_pkt_data_length_params_t;
/**
* @brief BLE encryption keys
@ -648,7 +648,7 @@ typedef enum {
typedef enum{
ESP_BLE_WHITELIST_REMOVE = 0X00, /*!< remove mac from whitelist */
ESP_BLE_WHITELIST_ADD = 0X01, /*!< add address to whitelist */
}esp_ble_wl_opration_t;
} esp_ble_wl_opration_t;
#if (BLE_42_FEATURE_SUPPORT == TRUE)
typedef enum {
ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_ADD = 0, /*!< Add device info into duplicate scan exceptional list */
@ -998,7 +998,7 @@ typedef union {
uint16_t conn_int; /*!< Current connection interval */
uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80.
Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec */
}update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */
} update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */
/**
* @brief ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT
*/
@ -1018,13 +1018,13 @@ typedef union {
struct ble_remove_bond_dev_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate the remove bond device operation success status */
esp_bd_addr_t bd_addr; /*!< The device address which has been remove from the bond list */
}remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
} remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
*/
struct ble_clear_bond_dev_cmpl_evt_param {
esp_bt_status_t status; /*!< Indicate the clear bond device operation success status */
}clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
} clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT
*/
@ -1032,7 +1032,7 @@ typedef union {
esp_bt_status_t status; /*!< Indicate the get bond device operation success status */
uint8_t dev_num; /*!< Indicate the get number device in the bond list */
esp_ble_bond_dev_t *bond_dev; /*!< the pointer to the bond device Structure */
}get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
} get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
/**
* @brief ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT
*/

View File

@ -380,7 +380,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
/**
* @brief Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service.
* Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need
* to used the esp_ble_gattc_search_service.
* to used the esp_ble_gattc_cache_refresh, then call esp_ble_gattc_get_service again.
*
* @param[in] gattc_if: Gatt client access interface.
* @param[in] conn_id: connection ID which identify the server.

Some files were not shown because too many files have changed in this diff Show More