mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-25 09:51:33 +02:00
Compare commits
83 Commits
Author | SHA1 | Date | |
---|---|---|---|
d218e58f96 | |||
14ece43654 | |||
ae7173d4d5 | |||
c7080b0a83 | |||
96c184d213 | |||
da72bc90b7 | |||
16a9cf781f | |||
b1497fb257 | |||
5e04eb48b6 | |||
674cf812e7 | |||
83884a0cda | |||
80b8262595 | |||
5747bfab67 | |||
4b9dc61447 | |||
a2d7c0dcf6 | |||
666cd3cde5 | |||
3e851b537a | |||
f410728444 | |||
79e0889a16 | |||
4aff6dde39 | |||
bb50046540 | |||
10258b4cc2 | |||
418ac74be0 | |||
caa8d07aaf | |||
15bbd0a187 | |||
02c3ec01cc | |||
cb5a490616 | |||
f257d6f126 | |||
aabbed0bbc | |||
a418058a66 | |||
96ad341451 | |||
2673b88582 | |||
67c99142d2 | |||
951c8bece5 | |||
4413dbbd87 | |||
ed53b6c8d4 | |||
2e53300da5 | |||
64c7f746fd | |||
1049be7d56 | |||
34c81be93b | |||
2fb2ef54ce | |||
49f525c91d | |||
b145e65975 | |||
951c32056a | |||
7a7bd37e51 | |||
a75602dc68 | |||
88789cd817 | |||
335cedf4f7 | |||
f9f70d2f73 | |||
5b207104aa | |||
1706af4656 | |||
bd54ee442b | |||
00214d5c2a | |||
381e88ec75 | |||
f87107dedb | |||
ce85cf03cc | |||
f2a20e8a38 | |||
c5bb8334d7 | |||
6de7f16f28 | |||
1688b7c179 | |||
36ff442698 | |||
93f10609f4 | |||
67583e84d6 | |||
108e467164 | |||
91bca6c074 | |||
204f360dce | |||
3f06a38f69 | |||
2f6f251400 | |||
e4acfbc54a | |||
79d53bdc4c | |||
f3f6dad14a | |||
0f174aae88 | |||
317be68cef | |||
1f4dd7f131 | |||
8be2f7b1cc | |||
9f827a66d5 | |||
e1cdbd7816 | |||
7a35be3e7e | |||
078671d273 | |||
541cef9149 | |||
6dfaf6cdd4 | |||
92ce408f4c | |||
453af3800c |
2
.github/scripts/check-cmakelists.sh
vendored
2
.github/scripts/check-cmakelists.sh
vendored
@ -15,7 +15,7 @@ git submodule update --init --recursive
|
||||
REPO_SRCS=`find cores/esp32/ libraries/ -name 'examples' -prune -o -name '*.c' -print -o -name '*.cpp' -print | sort`
|
||||
|
||||
# find all source files named in CMakeLists.txt COMPONENT_SRCS
|
||||
CMAKE_SRCS=`cmake --trace-expand -C CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort`
|
||||
CMAKE_SRCS=`cmake --trace-expand -P CMakeLists.txt 2>&1 | grep set\(srcs | cut -d'(' -f3 | sed 's/ )//' | sed 's/srcs //' | tr ' ;' '\n' | sort`
|
||||
|
||||
if ! diff -u0 --label "Repo Files" --label "srcs" <(echo "$REPO_SRCS") <(echo "$CMAKE_SRCS"); then
|
||||
echo "Source files in repo (-) and source files in CMakeLists.txt (+) don't match"
|
||||
|
79
.github/stale.yml
vendored
79
.github/stale.yml
vendored
@ -1,61 +1,26 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
# This workflow firstly warns and then closes issues that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information can be found here: https://github.com/actions/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
name: Mark stale issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 9 * * *'
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||
onlyLabels: []
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- "Type: For reference"
|
||||
- "Type: To be implemented"
|
||||
- "Type: Feature request"
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: "Status: Stale"
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
[STALE_SET] This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed in 14 days if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
unmarkComment: >
|
||||
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.'
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
exempt-issue-labels: 'Type: For reference,Type: To be implemented,Type: Feature request'
|
||||
stale-issue-label: 'Status: Stale'
|
27
.github/workflows/test_selfhosted_runner.yml
vendored
Normal file
27
.github/workflows/test_selfhosted_runner.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
name: Test Github action on self hosted RPI runnes
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Dummy test - self hosted GHR
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Test message 1
|
||||
run: echo "This is test message"
|
||||
- name: Test message 2
|
||||
run: echo "This is test message2"
|
||||
- name: List directory
|
||||
run: ls
|
||||
- name: Create copy of README
|
||||
run: cp README.md README2.md
|
||||
- name: Read README2
|
||||
run: cat README2.md
|
||||
- name: Delete README2
|
||||
run: rm README2.md
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ boards.sloeber.txt
|
||||
|
||||
# Ignore docs build (Sphinx)
|
||||
docs/build
|
||||
docs/source/_build
|
||||
|
@ -1,3 +1,27 @@
|
||||
# Check ESP-IDF version and error out if it is not in the supported range.
|
||||
#
|
||||
# Note for arduino-esp32 developers: to bypass the version check locally,
|
||||
# set ARDUINO_SKIP_IDF_VERSION_CHECK environment variable to 1. For example:
|
||||
# export ARDUINO_SKIP_IDF_VERSION_CHECK=1
|
||||
# idf.py build
|
||||
|
||||
set(min_supported_idf_version "4.4.0")
|
||||
set(max_supported_idf_version "4.4.99")
|
||||
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}")
|
||||
|
||||
if ("${idf_version}" AND NOT "$ENV{ARDUINO_SKIP_IDF_VERSION_CHECK}")
|
||||
if (idf_version VERSION_LESS min_supported_idf_version)
|
||||
message(FATAL_ERROR "Arduino-esp32 can be used with ESP-IDF versions "
|
||||
"between ${min_supported_idf_version} and ${max_supported_idf_version}, "
|
||||
"but an older version is detected: ${idf_version}.")
|
||||
endif()
|
||||
if (idf_version VERSION_GREATER max_supported_idf_version)
|
||||
message(FATAL_ERROR "Arduino-esp32 can be used with ESP-IDF versions "
|
||||
"between ${min_supported_idf_version} and ${max_supported_idf_version}, "
|
||||
"but a newer version is detected: ${idf_version}.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CORE_SRCS
|
||||
cores/esp32/base64.cpp
|
||||
cores/esp32/cbuf.cpp
|
||||
@ -7,6 +31,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 +79,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 +116,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 +199,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})
|
||||
|
||||
|
17
README.md
17
README.md
@ -1,26 +1,15 @@
|
||||
# Arduino core for the ESP32
|
||||
# Arduino core for the ESP32, ESP32-S2 and ESP32-C3
|
||||
|
||||
[](https://travis-ci.org/espressif/arduino-esp32)  [](https://docs.espressif.com/projects/arduino-esp32/en/latest/?badge=latest)
|
||||
 [](https://docs.espressif.com/projects/arduino-esp32/en/latest/?badge=latest)
|
||||
|
||||
### Need help or have a question? Join the chat at [](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## Contents
|
||||
|
||||
- [ESP32-S2 and ESP32-C3 Support](#esp32-s2-and-esp32-c3-support)
|
||||
- [Development Status](#development-status)
|
||||
- [Decoding Exceptions](#decoding-exceptions)
|
||||
- [Issue/Bug report template](#issuebug-report-template)
|
||||
|
||||
### ESP32-S2 and ESP32-C3 Support
|
||||
|
||||
If you want to test ESP32-S2 and/or ESP32-C3 through the board manager, please use the development release link:
|
||||
|
||||
```
|
||||
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
|
||||
```
|
||||
|
||||
Now you can install the latest 2.0.0 version from the boards manager.
|
||||
|
||||
### Development Status
|
||||
|
||||
Latest Stable Release [](https://github.com/espressif/arduino-esp32/releases/latest/) [](https://github.com/espressif/arduino-esp32/releases/latest/) [](https://github.com/espressif/arduino-esp32/releases/latest/)
|
||||
@ -43,7 +32,7 @@ You can use [Arduino-ESP32 Online Documentation](https://docs.espressif.com/proj
|
||||
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
|
||||
|
||||
### Issue/Bug report template
|
||||
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20).
|
||||
Before reporting an issue, make sure you've searched for similar one that was already created. Also make sure to go through all the issues labelled as [Type: For reference](https://github.com/espressif/arduino-esp32/issues?q=is%3Aissue+label%3A%22Type%3A+For+reference%22+).
|
||||
|
||||
Finally, if you are sure no one else had the issue, follow the [issue template](docs/ISSUE_TEMPLATE.md) while reporting any issue.
|
||||
|
||||
|
194
boards.txt
194
boards.txt
@ -57,13 +57,6 @@ esp32c3.menu.CDCOnBoot.default.build.cdc_on_boot=0
|
||||
esp32c3.menu.CDCOnBoot.cdc=Enabled
|
||||
esp32c3.menu.CDCOnBoot.cdc.build.cdc_on_boot=1
|
||||
|
||||
esp32c3.menu.UploadMode.default=UART0
|
||||
esp32c3.menu.UploadMode.default.upload.use_1200bps_touch=false
|
||||
esp32c3.menu.UploadMode.default.upload.wait_for_upload_port=false
|
||||
esp32c3.menu.UploadMode.cdc=Internal USB
|
||||
esp32c3.menu.UploadMode.cdc.upload.use_1200bps_touch=true
|
||||
esp32c3.menu.UploadMode.cdc.upload.wait_for_upload_port=true
|
||||
|
||||
esp32c3.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
|
||||
esp32c3.menu.PartitionScheme.default.build.partitions=default
|
||||
esp32c3.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
|
||||
@ -2071,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
|
||||
@ -2462,6 +2571,9 @@ esp32micromod.upload.extra_flags=
|
||||
esp32micromod.serial.disableDTR=true
|
||||
esp32micromod.serial.disableRTS=true
|
||||
|
||||
esp32micromod.build.tarch=xtensa
|
||||
esp32micromod.build.bootloader_addr=0x1000
|
||||
esp32micromod.build.target=esp32
|
||||
esp32micromod.build.mcu=esp32
|
||||
esp32micromod.build.core=esp32
|
||||
esp32micromod.build.variant=esp32micromod
|
||||
@ -3801,6 +3913,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
|
||||
@ -3915,11 +4034,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
|
||||
@ -3966,6 +4085,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
|
||||
@ -4131,6 +4257,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
|
||||
@ -4243,7 +4376,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
|
||||
@ -4268,7 +4401,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
|
||||
@ -4296,10 +4429,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
|
||||
@ -9386,19 +9519,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=
|
||||
@ -9544,10 +9690,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=
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -24,15 +24,47 @@
|
||||
#include "soc/periph_defs.h"
|
||||
#include "hal/usb_serial_jtag_ll.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ARDUINO_HW_CDC_EVENTS);
|
||||
|
||||
static RingbufHandle_t tx_ring_buf = NULL;
|
||||
static xQueueHandle rx_queue = NULL;
|
||||
static uint8_t rx_data_buf[64];
|
||||
static intr_handle_t intr_handle = NULL;
|
||||
static volatile bool initial_empty = false;
|
||||
static xSemaphoreHandle tx_lock = NULL;
|
||||
static uint32_t tx_timeout_ms = 200;
|
||||
static esp_event_loop_handle_t arduino_hw_cdc_event_loop_handle = NULL;
|
||||
|
||||
static esp_err_t arduino_hw_cdc_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, BaseType_t *task_unblocked){
|
||||
if(arduino_hw_cdc_event_loop_handle == NULL){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return esp_event_isr_post_to(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_data, event_data_size, task_unblocked);
|
||||
}
|
||||
|
||||
static esp_err_t arduino_hw_cdc_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg){
|
||||
if (!arduino_hw_cdc_event_loop_handle) {
|
||||
esp_event_loop_args_t event_task_args = {
|
||||
.queue_size = 5,
|
||||
.task_name = "arduino_hw_cdc_events",
|
||||
.task_priority = 5,
|
||||
.task_stack_size = 2048,
|
||||
.task_core_id = tskNO_AFFINITY
|
||||
};
|
||||
if (esp_event_loop_create(&event_task_args, &arduino_hw_cdc_event_loop_handle) != ESP_OK) {
|
||||
log_e("esp_event_loop_create failed");
|
||||
}
|
||||
}
|
||||
if(arduino_hw_cdc_event_loop_handle == NULL){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return esp_event_handler_register_with(arduino_hw_cdc_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
|
||||
}
|
||||
|
||||
static void hw_cdc_isr_handler(void *arg) {
|
||||
portBASE_TYPE xTaskWoken = 0;
|
||||
uint32_t usbjtag_intr_status = 0;
|
||||
arduino_hw_cdc_event_data_t event = {0};
|
||||
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
|
||||
|
||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
|
||||
@ -45,6 +77,7 @@ static void hw_cdc_isr_handler(void *arg) {
|
||||
initial_empty = true;
|
||||
//send event?
|
||||
//ets_printf("CONNECTED\n");
|
||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_CONNECTED_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||
}
|
||||
size_t queued_size;
|
||||
uint8_t *queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(tx_ring_buf, &queued_size, 64);
|
||||
@ -58,6 +91,8 @@ static void hw_cdc_isr_handler(void *arg) {
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
//send event?
|
||||
//ets_printf("TX:%u\n", queued_size);
|
||||
event.tx.len = queued_size;
|
||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_TX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||
}
|
||||
} else {
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
@ -77,6 +112,8 @@ static void hw_cdc_isr_handler(void *arg) {
|
||||
}
|
||||
//send event?
|
||||
//ets_printf("RX:%u/%u\n", i, rx_fifo_len);
|
||||
event.rx.len = i;
|
||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_RX_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||
}
|
||||
|
||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
|
||||
@ -84,6 +121,7 @@ static void hw_cdc_isr_handler(void *arg) {
|
||||
initial_empty = false;
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
//ets_printf("BUS_RESET\n");
|
||||
arduino_hw_cdc_event_post(ARDUINO_HW_CDC_EVENTS, ARDUINO_HW_CDC_BUS_RESET_EVENT, &event, sizeof(arduino_hw_cdc_event_data_t), &xTaskWoken);
|
||||
}
|
||||
|
||||
if (xTaskWoken == pdTRUE) {
|
||||
@ -95,13 +133,13 @@ static void ARDUINO_ISR_ATTR cdc0_write_char(char c) {
|
||||
if(xPortInIsrContext()){
|
||||
xRingbufferSendFromISR(tx_ring_buf, (void*) (&c), 1, NULL);
|
||||
} else {
|
||||
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, 0);
|
||||
xRingbufferSend(tx_ring_buf, (void*) (&c), 1, tx_timeout_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
|
||||
HWCDC::HWCDC() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
HWCDC::~HWCDC(){
|
||||
@ -113,16 +151,28 @@ HWCDC::operator bool() const
|
||||
return initial_empty;
|
||||
}
|
||||
|
||||
void HWCDC::onEvent(esp_event_handler_t callback){
|
||||
onEvent(ARDUINO_HW_CDC_ANY_EVENT, callback);
|
||||
}
|
||||
|
||||
void HWCDC::onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback){
|
||||
arduino_hw_cdc_event_handler_register_with(ARDUINO_HW_CDC_EVENTS, event, callback, this);
|
||||
}
|
||||
|
||||
void HWCDC::begin(unsigned long baud)
|
||||
{
|
||||
if(tx_lock == NULL) {
|
||||
tx_lock = xSemaphoreCreateMutex();
|
||||
}
|
||||
setRxBufferSize(256);//default if not preset
|
||||
setTxBufferSize(256);//default if not preset
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,8 +182,19 @@ void HWCDC::end()
|
||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT | USB_SERIAL_JTAG_INTR_BUS_RESET);
|
||||
esp_intr_free(intr_handle);
|
||||
intr_handle = NULL;
|
||||
if(tx_lock != NULL) {
|
||||
vSemaphoreDelete(tx_lock);
|
||||
}
|
||||
setRxBufferSize(0);
|
||||
setTxBufferSize(0);
|
||||
if (arduino_hw_cdc_event_loop_handle) {
|
||||
esp_event_loop_delete(arduino_hw_cdc_event_loop_handle);
|
||||
arduino_hw_cdc_event_loop_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HWCDC::setTxTimeoutMs(uint32_t timeout){
|
||||
tx_timeout_ms = timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -157,21 +218,57 @@ size_t HWCDC::setTxBufferSize(size_t tx_queue_len){
|
||||
|
||||
int HWCDC::availableForWrite(void)
|
||||
{
|
||||
if(tx_ring_buf == NULL){
|
||||
return -1;
|
||||
if(tx_ring_buf == NULL || tx_lock == NULL){
|
||||
return 0;
|
||||
}
|
||||
return xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return 0;
|
||||
}
|
||||
size_t a = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||
xSemaphoreGive(tx_lock);
|
||||
return a;
|
||||
}
|
||||
|
||||
size_t HWCDC::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), size, 200 / portTICK_PERIOD_MS) != pdTRUE){
|
||||
log_e("Write Failed");
|
||||
if(buffer == NULL || size == 0 || tx_ring_buf == NULL || tx_lock == NULL){
|
||||
return 0;
|
||||
}
|
||||
// Now trigger the ISR to read data from the ring buffer.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return 0;
|
||||
}
|
||||
size_t max_size = xRingbufferGetMaxItemSize(tx_ring_buf);
|
||||
size_t space = xRingbufferGetCurFreeSize(tx_ring_buf);
|
||||
size_t to_send = size, so_far = 0;
|
||||
|
||||
if(space > size){
|
||||
space = size;
|
||||
}
|
||||
// Non-Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||
if(xRingbufferSend(tx_ring_buf, (void*) (buffer), space, 0) != pdTRUE){
|
||||
size = 0;
|
||||
} else {
|
||||
to_send -= space;
|
||||
so_far += space;
|
||||
// Now trigger the ISR to read data from the ring buffer.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
|
||||
while(to_send){
|
||||
if(max_size > to_send){
|
||||
max_size = to_send;
|
||||
}
|
||||
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||
if(xRingbufferSend(tx_ring_buf, (void*) (buffer+so_far), max_size, tx_timeout_ms / portTICK_PERIOD_MS) != pdTRUE){
|
||||
size = so_far;
|
||||
break;
|
||||
}
|
||||
so_far += max_size;
|
||||
to_send -= max_size;
|
||||
// Now trigger the ISR to read data from the ring buffer.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(tx_lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -182,15 +279,23 @@ size_t HWCDC::write(uint8_t c)
|
||||
|
||||
void HWCDC::flush(void)
|
||||
{
|
||||
if(tx_ring_buf == NULL){
|
||||
if(tx_ring_buf == NULL || tx_lock == NULL){
|
||||
return;
|
||||
}
|
||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return;
|
||||
}
|
||||
UBaseType_t uxItemsWaiting = 0;
|
||||
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
if(uxItemsWaiting){
|
||||
// Now trigger the ISR to read data from the ring buffer.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
while(uxItemsWaiting){
|
||||
delay(5);
|
||||
vRingbufferGetInfo(tx_ring_buf, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||
}
|
||||
xSemaphoreGive(tx_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -17,16 +17,41 @@
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_event.h"
|
||||
#include "Stream.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ARDUINO_HW_CDC_EVENTS);
|
||||
|
||||
typedef enum {
|
||||
ARDUINO_HW_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
|
||||
ARDUINO_HW_CDC_CONNECTED_EVENT = 0,
|
||||
ARDUINO_HW_CDC_BUS_RESET_EVENT,
|
||||
ARDUINO_HW_CDC_RX_EVENT,
|
||||
ARDUINO_HW_CDC_TX_EVENT,
|
||||
ARDUINO_HW_CDC_MAX_EVENT,
|
||||
} arduino_hw_cdc_event_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
size_t len;
|
||||
} rx;
|
||||
struct {
|
||||
size_t len;
|
||||
} tx;
|
||||
} arduino_hw_cdc_event_data_t;
|
||||
|
||||
class HWCDC: public Stream
|
||||
{
|
||||
public:
|
||||
HWCDC();
|
||||
~HWCDC();
|
||||
|
||||
void onEvent(esp_event_handler_t callback);
|
||||
void onEvent(arduino_hw_cdc_event_t event, esp_event_handler_t callback);
|
||||
|
||||
size_t setRxBufferSize(size_t);
|
||||
size_t setTxBufferSize(size_t);
|
||||
void setTxTimeoutMs(uint32_t timeout);
|
||||
void begin(unsigned long baud=0);
|
||||
void end();
|
||||
|
||||
|
@ -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) {}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -62,63 +62,40 @@ void tud_cdc_rx_cb(uint8_t itf)
|
||||
|
||||
// Invoked when received send break
|
||||
void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms){
|
||||
//isr_log_v("itf: %u, duration_ms: %u", itf, duration_ms);
|
||||
//log_v("itf: %u, duration_ms: %u", itf, duration_ms);
|
||||
}
|
||||
|
||||
// Invoked when space becomes available in TX buffer
|
||||
void tud_cdc_tx_complete_cb(uint8_t itf){
|
||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL && devices[itf]->tx_sem != NULL){
|
||||
xSemaphoreGive(devices[itf]->tx_sem);
|
||||
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
|
||||
devices[itf]->_onTX();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
|
||||
if(itf >= MAX_USB_CDC_DEVICES || devices[itf] == NULL || devices[itf]->tx_sem == NULL){
|
||||
return 0;
|
||||
static void ARDUINO_ISR_ATTR cdc0_write_char(char c){
|
||||
if(devices[0] != NULL){
|
||||
devices[0]->write(c);
|
||||
}
|
||||
if(!tud_cdc_n_connected(itf)){
|
||||
return 0;
|
||||
}
|
||||
size_t tosend = size, sofar = 0;
|
||||
while(tosend){
|
||||
uint32_t space = tud_cdc_n_write_available(itf);
|
||||
if(!space){
|
||||
//make sure that we do not get previous semaphore
|
||||
xSemaphoreTake(devices[itf]->tx_sem, 0);
|
||||
//wait for tx_complete
|
||||
if(xSemaphoreTake(devices[itf]->tx_sem, 200 / portTICK_PERIOD_MS) == pdTRUE){
|
||||
space = tud_cdc_n_write_available(itf);
|
||||
}
|
||||
if(!space){
|
||||
return sofar;
|
||||
}
|
||||
}
|
||||
if(tosend < space){
|
||||
space = tosend;
|
||||
}
|
||||
uint32_t sent = tud_cdc_n_write(itf, buffer + sofar, space);
|
||||
if(!sent){
|
||||
return sofar;
|
||||
}
|
||||
sofar += sent;
|
||||
tosend -= sent;
|
||||
tud_cdc_n_write_flush(itf);
|
||||
//xSemaphoreTake(devices[itf]->tx_sem, portMAX_DELAY);
|
||||
}
|
||||
return sofar;
|
||||
}
|
||||
|
||||
static void ARDUINO_ISR_ATTR cdc0_write_char(char c)
|
||||
{
|
||||
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
|
||||
}
|
||||
|
||||
static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
|
||||
((USBCDC*)arg)->_onUnplugged();
|
||||
}
|
||||
|
||||
USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL), tx_sem(NULL) {
|
||||
USBCDC::USBCDC(uint8_t itfn)
|
||||
: itf(itfn)
|
||||
, bit_rate(0)
|
||||
, stop_bits(0)
|
||||
, parity(0)
|
||||
, data_bits(0)
|
||||
, dtr(false)
|
||||
, rts(false)
|
||||
, connected(false)
|
||||
, reboot_enable(true)
|
||||
, rx_queue(NULL)
|
||||
, tx_lock(NULL)
|
||||
, tx_timeout_ms(250)
|
||||
{
|
||||
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
|
||||
if(itf < MAX_USB_CDC_DEVICES){
|
||||
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
|
||||
@ -153,9 +130,8 @@ size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
|
||||
|
||||
void USBCDC::begin(unsigned long baud)
|
||||
{
|
||||
if(tx_sem == NULL){
|
||||
tx_sem = xSemaphoreCreateBinary();
|
||||
xSemaphoreTake(tx_sem, 0);
|
||||
if(tx_lock == NULL) {
|
||||
tx_lock = xSemaphoreCreateMutex();
|
||||
}
|
||||
setRxBufferSize(256);//default if not preset
|
||||
devices[itf] = this;
|
||||
@ -166,18 +142,21 @@ void USBCDC::end()
|
||||
connected = false;
|
||||
devices[itf] = NULL;
|
||||
setRxBufferSize(0);
|
||||
if (tx_sem != NULL) {
|
||||
vSemaphoreDelete(tx_sem);
|
||||
tx_sem = NULL;
|
||||
if(tx_lock != NULL) {
|
||||
vSemaphoreDelete(tx_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void USBCDC::setTxTimeoutMs(uint32_t timeout){
|
||||
tx_timeout_ms = timeout;
|
||||
}
|
||||
|
||||
void USBCDC::_onUnplugged(void){
|
||||
if(connected){
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -199,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 {
|
||||
@ -229,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);
|
||||
@ -254,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;
|
||||
@ -272,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);
|
||||
}
|
||||
|
||||
@ -336,23 +315,73 @@ size_t USBCDC::read(uint8_t *buffer, size_t size)
|
||||
|
||||
void USBCDC::flush(void)
|
||||
{
|
||||
if(itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL){
|
||||
if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)){
|
||||
return;
|
||||
}
|
||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return;
|
||||
}
|
||||
tud_cdc_n_write_flush(itf);
|
||||
xSemaphoreGive(tx_lock);
|
||||
}
|
||||
|
||||
int USBCDC::availableForWrite(void)
|
||||
{
|
||||
if(itf >= MAX_USB_CDC_DEVICES || tx_sem == NULL){
|
||||
return -1;
|
||||
if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)){
|
||||
return 0;
|
||||
}
|
||||
return tud_cdc_n_write_available(itf);
|
||||
if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return 0;
|
||||
}
|
||||
size_t a = tud_cdc_n_write_available(itf);
|
||||
xSemaphoreGive(tx_lock);
|
||||
return a;
|
||||
}
|
||||
|
||||
size_t USBCDC::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
return tinyusb_cdc_write(itf, buffer, size);
|
||||
if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)){
|
||||
return 0;
|
||||
}
|
||||
if(xPortInIsrContext()){
|
||||
BaseType_t taskWoken = false;
|
||||
if(xSemaphoreTakeFromISR(tx_lock, &taskWoken) != pdPASS){
|
||||
return 0;
|
||||
}
|
||||
} else if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){
|
||||
return 0;
|
||||
}
|
||||
size_t to_send = size, so_far = 0;
|
||||
while(to_send){
|
||||
if(!tud_cdc_n_connected(itf)){
|
||||
size = so_far;
|
||||
break;
|
||||
}
|
||||
size_t space = tud_cdc_n_write_available(itf);
|
||||
if(!space){
|
||||
tud_cdc_n_write_flush(itf);
|
||||
continue;
|
||||
}
|
||||
if(space > to_send){
|
||||
space = to_send;
|
||||
}
|
||||
size_t sent = tud_cdc_n_write(itf, buffer+so_far, space);
|
||||
if(sent){
|
||||
so_far += sent;
|
||||
to_send -= sent;
|
||||
tud_cdc_n_write_flush(itf);
|
||||
} else {
|
||||
size = so_far;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(xPortInIsrContext()){
|
||||
BaseType_t taskWoken = false;
|
||||
xSemaphoreGiveFromISR(tx_lock, &taskWoken);
|
||||
} else {
|
||||
xSemaphoreGive(tx_lock);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t USBCDC::write(uint8_t c)
|
||||
|
@ -18,6 +18,9 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_event.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "Stream.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_CDC_EVENTS);
|
||||
@ -58,7 +61,8 @@ public:
|
||||
void onEvent(esp_event_handler_t callback);
|
||||
void onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback);
|
||||
|
||||
size_t setRxBufferSize(size_t);
|
||||
size_t setRxBufferSize(size_t size);
|
||||
void setTxTimeoutMs(uint32_t timeout);
|
||||
void begin(unsigned long baud=0);
|
||||
void end();
|
||||
|
||||
@ -113,7 +117,6 @@ public:
|
||||
void _onRX(void);
|
||||
void _onTX(void);
|
||||
void _onUnplugged(void);
|
||||
xSemaphoreHandle tx_sem;
|
||||
|
||||
protected:
|
||||
uint8_t itf;
|
||||
@ -126,6 +129,8 @@ protected:
|
||||
bool connected;
|
||||
bool reboot_enable;
|
||||
xQueueHandle rx_queue;
|
||||
xSemaphoreHandle tx_lock;
|
||||
uint32_t tx_timeout_ms;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
848
cores/esp32/esp32-hal-i2c-slave.c
Executable 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);
|
||||
}
|
35
cores/esp32/esp32-hal-i2c-slave.h
Executable file
35
cores/esp32/esp32-hal-i2c-slave.h
Executable 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
@ -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
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp32-hal-matrix.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
@ -331,3 +332,21 @@ double ledcChangeFrequency(uint8_t chan, double freq, uint8_t bit_num)
|
||||
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
|
||||
return res_freq;
|
||||
}
|
||||
|
||||
static int8_t pin_to_channel[SOC_GPIO_PIN_COUNT] = { 0 };
|
||||
static int cnt_channel = SOC_LEDC_CHANNEL_NUM;
|
||||
void analogWrite(uint8_t pin, int value) {
|
||||
// Use ledc hardware for internal pins
|
||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||
if (pin_to_channel[pin] == 0) {
|
||||
if (!cnt_channel) {
|
||||
log_e("No more analogWrite channels available! You can have maximum %u", SOC_LEDC_CHANNEL_NUM);
|
||||
return;
|
||||
}
|
||||
pin_to_channel[pin] = cnt_channel--;
|
||||
ledcAttachPin(pin, cnt_channel);
|
||||
ledcSetup(cnt_channel, 1000, 8);
|
||||
}
|
||||
ledcWrite(pin_to_channel[pin] - 1, value);
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -368,13 +368,9 @@ void uartSetDebug(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || uart->num >= SOC_UART_NUM) {
|
||||
s_uart_debug_nr = -1;
|
||||
//ets_install_putc1(NULL);
|
||||
//return;
|
||||
} else
|
||||
if(s_uart_debug_nr == uart->num) {
|
||||
return;
|
||||
} else
|
||||
s_uart_debug_nr = uart->num;
|
||||
} else {
|
||||
s_uart_debug_nr = uart->num;
|
||||
}
|
||||
uart_install_putc();
|
||||
}
|
||||
|
||||
|
@ -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" {
|
||||
@ -85,6 +90,8 @@ void yield(void);
|
||||
#include "esp32-hal-psram.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
void analogWrite(uint8_t pin, int value);
|
||||
|
||||
//returns chip temperature in Celsius
|
||||
float temperatureRead();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
BIN
docs/source/_static/arduino_i2c_master.png
Normal file
BIN
docs/source/_static/arduino_i2c_master.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
BIN
docs/source/_static/arduino_i2c_slave.png
Normal file
BIN
docs/source/_static/arduino_i2c_slave.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
384
docs/source/api/i2c.rst
Normal file
384
docs/source/api/i2c.rst
Normal 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
|
@ -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
|
||||
------
|
||||
|
@ -10,6 +10,8 @@ For a simplified method, see `lib-builder <lib_builder>`_.
|
||||
Installation
|
||||
------------
|
||||
|
||||
.. note:: Latest Arduino Core ESP32 version is now compatible with [ESP-IDF v4.4](https://github.com/espressif/esp-idf/tree/release/v4.4). Please consider this compability when using Arduino as component in ESP-IDF.
|
||||
|
||||
- Download and install `ESP-IDF <https://github.com/espressif/esp-idf>`_.
|
||||
- Create blank idf project (from one of the examples).
|
||||
- In the project folder, create a new folder called `components` and clone this repository inside the new created folder.
|
||||
|
@ -35,8 +35,8 @@ Here are the ESP32 series supported by the Arduino-ESP32 project:
|
||||
SoC Stable Development Datasheet
|
||||
======== ====== =========== ===================================
|
||||
ESP32 Yes Yes `ESP32 Datasheet`_
|
||||
ESP32-S2 No Yes `ESP32-S2 Datasheet`_
|
||||
ESP32-C3 No Yes `ESP32-C3 Datasheet`_
|
||||
ESP32-S2 Yes Yes `ESP32-S2 Datasheet`_
|
||||
ESP32-C3 Yes Yes `ESP32-C3 Datasheet`_
|
||||
ESP32-S3 No No Not Available Yet
|
||||
======== ====== =========== ===================================
|
||||
|
||||
|
@ -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.
|
||||
|
@ -2,16 +2,88 @@
|
||||
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 APIs.
|
||||
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Peripheral | ESP32 | ESP32-S2 | ESP32-C3 | Comments |
|
||||
+===============+===============+===============+===============+===============================+
|
||||
| ADC | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Bluetooth | Yes | Not Supported | Not Supported | Bluetooth Classic |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| BLE | Yes | Not Supported | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| DAC | Yes | Yes | Not Supported | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Ethernet | Yes | Not Supported | Not Supported | (*) |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| GPIO | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Hall Sensor | Yes | Not Supported | Not Supported | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| I2C | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| I2S | No | No | No | WIP |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| LEDC | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Motor PWM | No | Not Supported | Not Supported | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Pulse Counter | No | No | No | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| RMT | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| SDIO | No | No | No | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| SPI | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Timer | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Temp. Sensor | Not Supported | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Touch | Yes | Yes | Not Supported | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| TWAI | No | No | No | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| UART | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| USB | Not Supported | Yes | Yes | ESP32-C3 only CDC/JTAG |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
| Wi-Fi | Yes | Yes | Yes | |
|
||||
+---------------+---------------+---------------+---------------+-------------------------------+
|
||||
|
||||
Notes
|
||||
^^^^^
|
||||
|
||||
(*) SPI Ethernet is supported by all ESP32 families and RMII only for ESP32.
|
||||
|
||||
.. note:: Some peripherals are not available for all ESP32 families. To see more details about it, see the corresponding SoC at `Product Selector <https://products.espressif.com>`_ page.
|
||||
|
||||
Datasheet
|
||||
^^^^^^^^^
|
||||
|
||||
* `ESP32 <https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf>`_
|
||||
* `ESP32-S2 <https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf>`_
|
||||
* `ESP32-C3 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf>`_
|
||||
|
||||
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>
|
||||
|
@ -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.
|
||||
|
113
docs/source/tutorials/blink.rst
Normal file
113
docs/source/tutorials/blink.rst
Normal file
@ -0,0 +1,113 @@
|
||||
##########################
|
||||
Blink Interactive Tutorial
|
||||
##########################
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This is the interactive blink tutorial using `Wokwi`_. For this tutorial, you don't need the ESP32 board or the Arduino toolchain.
|
||||
|
||||
.. note:: If you don't want to use this tutorial with the simulation, you can copy and paste the :ref:`blink_example_code` from `Wokwi`_ editor and use it on the `Arduino IDE`_ or `PlatformIO`_.
|
||||
|
||||
About this Tutorial
|
||||
-------------------
|
||||
|
||||
This tutorial is the most basic for any get started. In this tutorial, we will show how to set a GPIO pin as an output to drive a LED to blink each 1 second.
|
||||
|
||||
Step by step
|
||||
------------
|
||||
|
||||
In order to make this simple blink tutorial, you'll need to do the following steps.
|
||||
|
||||
1. **Define the GPIO for the LED.**
|
||||
|
||||
.. code-block::
|
||||
|
||||
#define LED 2
|
||||
|
||||
This ``#define LED 2`` will be used to set the GPIO2 as the ``LED`` output pin.
|
||||
|
||||
2. **Setup.**
|
||||
|
||||
Inside the ``setup()`` function, we need to add all things we want to run once during the startup.
|
||||
Here we'll add the ``pinMode`` function to set the pin as output.
|
||||
|
||||
.. code-block::
|
||||
|
||||
void setup() {
|
||||
pinMode(LED, OUTPUT);
|
||||
}
|
||||
|
||||
The first argument is the GPIO number, already defined and the second is the mode, here defined as an output.
|
||||
|
||||
3. **Main Loop.**
|
||||
|
||||
After the ``setup``, the code runs the ``loop`` function infinitely. Here we will handle the GPIO in order to get the LED blinking.
|
||||
|
||||
.. code-block::
|
||||
|
||||
void loop() {
|
||||
digitalWrite(LED, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(LED, LOW);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
The first function is the ``digitalWrite()`` with two arguments:
|
||||
|
||||
* GPIO: Set the GPIO pin. Here defined by our ``LED`` connected to the GPIO2.
|
||||
* State: Set the GPIO state as HIGH (ON) or LOW (OFF).
|
||||
|
||||
This first ``digitalWrite`` we will set the LED ON.
|
||||
|
||||
After the ``digitalWrite``, we will set a ``delay`` function in order to wait for some time, defined in milliseconds.
|
||||
|
||||
Now we can set the GPIO to ``LOW`` to turn the LED off and ``delay`` for more few milliseconds to get the LED blinking.
|
||||
|
||||
4. **Run the code.**
|
||||
|
||||
To run this code, you'll need a development board and the Arduino toolchain installed on your computer. If you don't have both, you can use the simulator to test and edit the code.
|
||||
|
||||
Simulation
|
||||
----------
|
||||
|
||||
This simulator is provided by `Wokwi`_ and you can test the blink code and play with some modifications to learn more about this example.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<iframe src="https://wokwi.com/arduino/projects/305566932847821378?embed=1" width="100%" height="400" border="0"></iframe>
|
||||
|
||||
Change the parameters, like the delay period, to test the code right on your browser. You can add more LEDs, change the GPIO, and more.
|
||||
|
||||
.. _blink_example_code:
|
||||
|
||||
Example Code
|
||||
------------
|
||||
|
||||
Here is the full blink code.
|
||||
|
||||
.. code-block::
|
||||
|
||||
#define LED 2
|
||||
|
||||
void setup() {
|
||||
pinMode(LED, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
digitalWrite(LED, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(LED, LOW);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* `ESP32 Datasheet`_ (Datasheet)
|
||||
* `Wokwi`_ (Wokwi Website)
|
||||
|
||||
.. _ESP32 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
|
||||
.. _Wokwi: https://wokwi.com/
|
||||
.. _PlatformIO: https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html#platformio
|
||||
.. _Arduino IDE: https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html#installing-using-boards-manager
|
@ -6,6 +6,7 @@ Tutorials
|
||||
:maxdepth: 2
|
||||
:caption: Tutorials:
|
||||
|
||||
Blink <blink>
|
||||
Basic <basic>
|
||||
DFU <dfu>
|
||||
GPIO Matrix and Pin Mux <io_mux>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
9
libraries/Ethernet/library.properties
Normal file
9
libraries/Ethernet/library.properties
Normal 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
|
@ -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;
|
||||
}
|
||||
@ -369,6 +368,10 @@ bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_typ
|
||||
log_e("esp_eth_init error: %d", err);
|
||||
}
|
||||
#endif
|
||||
// holds a few microseconds to let DHCP start and enter into a good state
|
||||
// FIX ME -- adresses issue https://github.com/espressif/arduino-esp32/issues/5733
|
||||
delay(50);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -397,7 +400,8 @@ bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, I
|
||||
if(err != ERR_OK){
|
||||
log_e("STA IP could not be configured! Error: %d", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(info.ip.addr){
|
||||
staticIP = true;
|
||||
} else {
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
```
|
@ -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();
|
||||
}
|
@ -29,6 +29,7 @@ connected KEYWORD2
|
||||
setCACert KEYWORD2
|
||||
setCertificate KEYWORD2
|
||||
setPrivateKey KEYWORD2
|
||||
setAlpnProtocols KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
30
libraries/Wire/examples/WireMaster/WireMaster.ino
Normal file
30
libraries/Wire/examples/WireMaster/WireMaster.ino
Normal 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);
|
||||
}
|
||||
}
|
28
libraries/Wire/examples/WireScan/WireScan.ino
Normal file
28
libraries/Wire/examples/WireScan/WireScan.ino
Normal 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");
|
||||
}
|
||||
}
|
37
libraries/Wire/examples/WireSlave/WireSlave.ino
Normal file
37
libraries/Wire/examples/WireSlave/WireSlave.ino
Normal 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() {
|
||||
|
||||
}
|
@ -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)
|
||||
|
@ -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,41 +441,46 @@ 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)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop));
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<uint8_t>(quantity), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t quantity, uint8_t sendStop)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(quantity), static_cast<bool>(sendStop));
|
||||
return requestFrom(address, static_cast<uint8_t>(quantity), static_cast<bool>(sendStop));
|
||||
}
|
||||
|
||||
/* Added to match the Arduino function definition: https://github.com/arduino/ArduinoCore-API/blob/173e8eadced2ad32eeb93bcbd5c49f8d6a055ea6/api/HardwareI2C.h#L39
|
||||
* See: https://github.com/arduino-libraries/ArduinoECCX08/issues/25
|
||||
*/
|
||||
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool stopBit)
|
||||
{
|
||||
return requestFrom((uint16_t)address, (uint8_t)len, stopBit);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), true);
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<uint8_t>(quantity), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint16_t address, uint8_t quantity)
|
||||
{
|
||||
return requestFrom(address, static_cast<size_t>(quantity), true);
|
||||
return requestFrom(address, static_cast<uint8_t>(quantity), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity)
|
||||
{
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), true);
|
||||
return requestFrom(static_cast<uint16_t>(address), static_cast<uint8_t>(quantity), true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
|
||||
{
|
||||
return static_cast<uint8_t>(requestFrom(static_cast<uint16_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop)));
|
||||
return static_cast<uint8_t>(requestFrom(static_cast<uint16_t>(address), static_cast<uint8_t>(quantity), static_cast<bool>(sendStop)));
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address)
|
||||
@ -333,56 +498,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);
|
||||
|
@ -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);
|
||||
@ -98,6 +95,7 @@ public:
|
||||
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size, uint8_t sendStop);
|
||||
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
|
||||
uint8_t requestFrom(uint16_t address, uint8_t size);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size, uint8_t sendStop);
|
||||
uint8_t requestFrom(uint8_t address, uint8_t size);
|
||||
@ -134,22 +132,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
|
||||
|
@ -23,30 +23,30 @@
|
||||
},
|
||||
"boards": [
|
||||
{
|
||||
"name": "ESP32 Dev Module"
|
||||
"name": "ESP32 Dev Board"
|
||||
},
|
||||
{
|
||||
"name": "WEMOS LoLin32"
|
||||
"name": "ESP32-S2 Dev Board"
|
||||
},
|
||||
{
|
||||
"name": "WEMOS D1 MINI ESP32"
|
||||
"name": "ESP32-C3 Dev Board"
|
||||
}
|
||||
],
|
||||
"toolsDependencies": [
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
50
platform.txt
50
platform.txt
File diff suppressed because one or more lines are too long
876
tools/esptool.py
876
tools/esptool.py
File diff suppressed because it is too large
Load Diff
@ -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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user