Compare commits

...

396 Commits

Author SHA1 Message Date
cf60cf4c3b Adding LITTLEFS after esp_littlefs (IDF) is built-in (#4483)
Tools idea: https://github.com/lorol/arduino-esp32fs-plugin
2020-11-03 23:06:40 +02:00
b5b45cd518 Update install-arduino-ide.sh 2020-11-03 21:25:02 +02:00
9a9fb2c3aa port 882b12c44e over
ports: 882b12c44e
2020-11-03 19:58:23 +02:00
41e392f661 Add esp-rainmaker support for ESP32 2020-11-03 11:12:53 +02:00
6be6abf35b Update IDF master to 357a27760 2020-11-02 23:19:24 +02:00
baaff8480e Update IDF and Camera 2020-10-15 00:19:54 +03:00
54140dc5ca Fix Arduino PIN counts 2020-10-14 21:09:15 +03:00
9f8b433196 Make esp32-hal-tinyusb.h conditional on tinyusb (#4155) 2020-10-14 15:26:51 +03:00
b7c3607b5b Update IDF and Tools 2020-10-13 16:52:16 +03:00
2b0dbdc12a Update .gitignore 2020-10-13 14:25:19 +03:00
b06735a33a Update platform.txt 2020-10-13 01:51:59 +03:00
537b1a6d3a Add camera support
first automated cmake build
2020-10-12 23:56:00 +03:00
440437c905 Try with speed optimization as opposed to debug. Coremark 240 -> 430 2020-10-11 19:51:11 +03:00
9bb8224159 Added ESP32-Wrover-Kit with distinct build.board (#4118)
* Added ESP32-Wrover-Kit with distinct build.board

* Fixed broken values

* Update boards.txt

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-10-03 02:18:02 +03:00
0db0af5932 Add board microS2 (#4314) 2020-10-03 02:00:48 +03:00
8d9d7bbca9 Makes ethernet get an IP when connected (#4234) 2020-10-01 14:40:15 +03:00
291c519642 Update WiFiMulti.cpp (#4099)
Fix for https://github.com/espressif/arduino-esp32/issues/3914 by syncing with https://github.com/espressif/arduino-esp32/blob/esp32s2/libraries/WiFi/src/WiFiSTA.cpp#L161
2020-09-30 15:33:05 +03:00
bbcc624c97 Update USB.cpp 2020-09-23 13:48:28 +03:00
2656452d04 Update boards.txt 2020-09-04 14:37:48 +03:00
273a8d79b4 Update platform.txt 2020-09-01 12:06:13 +03:00
42b4a9927d Update install-platformio-esp32.sh 2020-08-31 18:10:03 +03:00
383b999ddd Update platform.txt
Provided by @ESP32DE
2020-08-31 17:39:55 +03:00
52c284af75 Update IDF, tools and toolchains 2020-08-24 19:10:52 +03:00
5f057c7cac Some fixes 2020-08-22 23:37:42 +03:00
880fc0bdfb Add option to select the core used for Arduino and it's events 2020-08-16 17:52:09 +03:00
9eaa5873bf Update CMakeLists.txt 2020-07-23 16:13:37 +03:00
7678be447d Merge branch 'master' into esp32s2 2020-07-23 16:10:45 +03:00
c6f6522032 Update HardwareSerial.h 2020-07-23 15:49:54 +03:00
d2519843ad Added UM FeatherS2 and UM ProS2 boards to boards.txt (#4188)
* Added UM FeatherS2 and UM ProS2 boards to boards.txt
Updated the name of TinyPICO to UM TinyPICO in boards.txt

* Added VID/PID/Product names for TinyPICO, ProS2 & FeatherS2
Setup variant folders for each board

* Removed unneeded stuff from FeatherS2 & ProS2 menu options

* Added Serial CDC output default for FeatherS2 and ProS2

* Removed unneeded stuff from FeatherS2 & ProS2 menu options

* Rebase from upstream and fixed Serial Output settings for FeatherS2 and ProS2

Co-authored-by: Seon Rozenblum <seonr@3sprockets.com>
2020-07-23 10:32:44 +03:00
2cebf72876 Update CMakeLists.txt 2020-07-23 00:27:33 +03:00
4fa3cbab64 Improve CDC Logging support 2020-07-22 23:59:22 +03:00
280bf4d014 Create USB_NOT.h 2020-07-22 19:42:36 +03:00
dc0208ed1e Add option USB CDC to be used for Serial (starting USB early) 2020-07-22 19:16:22 +03:00
f58cba0b4f Add support for custom VID/PID and Board name to show in ArduinoIDE ports list 2020-07-22 13:46:59 +03:00
38057d66ad Update tinyusb 2020-07-20 00:57:06 +03:00
4d98cea085 Add Wire:setPins(sda, scl)
Fixes: https://github.com/espressif/arduino-esp32/issues/3779
2020-07-19 02:21:15 +03:00
33f4745635 Update USB.cpp 2020-07-18 17:52:06 +03:00
9f1ccb9c85 Some CDC and BTSerial compatibility fixes 2020-07-14 18:21:21 +03:00
ea04207c8f Add debug output to CDC 2020-07-02 14:14:07 +03:00
e06f9b7fa6 Handle persistent reboot better in CDC 2020-07-02 13:07:34 +03:00
2e19d27e3e Change driver attach api and remove DFU from CDC 2020-07-02 02:16:07 +03:00
b8fcea9a8d Update TinyUSB 2020-07-01 23:45:42 +03:00
46bde99c06 Update USBCDC.cpp 2020-06-30 18:10:52 +03:00
7f61d2044a Update libtinyusb.a 2020-06-30 01:29:59 +03:00
f13f84ddeb Fix compilation issues 2020-06-29 23:28:15 +03:00
096af056d1 Fix DTR/RTS state for ESP32S2 native USB 2020-06-29 22:43:54 +03:00
acadabb146 Update CMakeLists.txt 2020-06-29 18:39:25 +03:00
7d50114881 Add files to cmakelists and disconnect CDC if unplugged 2020-06-29 18:30:50 +03:00
be074eec80 Add TinyUSB HAL and CDC 2020-06-29 17:23:12 +03:00
bd96f7f159 Update IDF Libs 2020-06-28 15:38:58 +03:00
ca7ed86bbd Update TinyUSB Lib 2020-06-28 15:02:03 +03:00
a1bd429747 Fix GPIO Interrupts 2020-06-22 14:03:18 +03:00
11cad8747e Fixing static IP configuration so it doesn't get overwritten by DHCP as part of WiFi.begin(). (#4103)
Fixing DHCP client stop if WiFi.config() is called before WiFi.begin() (as done in WiFiClientStaticIP.ino)
2020-06-22 13:59:51 +03:00
2d7ec30a1b Update libtinyusb.a 2020-06-01 19:42:38 +03:00
ef961442d7 Add missing DFU driver 2020-06-01 19:13:18 +03:00
d5bd8e325c Try custom device descriptors 2020-06-01 18:09:38 +03:00
0a4b6599d2 again 2020-06-01 13:31:21 +03:00
8cb2a4ba3e change endpoints 2020-06-01 13:16:03 +03:00
d12af93ee2 TinyUSB adjust 2020-06-01 12:54:09 +03:00
7e9d75a974 Merge branch 'master' into esp32s2 2020-06-01 01:55:35 +03:00
61c98b8370 Update pins_arduino.h 2020-06-01 01:54:11 +03:00
b92c58d74b M5Stack's product offering includes various ESP32-based camera devices. (#4030)
They are all broadly similar, all being based on the ESP32-D0WD core, but have
some subtle differences between variants around PSRAM inclusion and camera pin
mappings.

The ESP32CAM "unit" product (SKU: U007) has no PSRAM and maps the
"Pixel Data 0" (Y2 GPIO/OV2640 D2) camera pin to IO17 rather than IO32 as is
the case with most other M5Stack ESP32 camera devices.

The ESP32CAM also requires the "hmirror" and "vflip" camera configuration
bits setting in order to capture a true image.

The relevant M5Stack pin configuration documentation can be found here:
https://docs.m5stack.com/#/en/unit/esp32cam?id=pinmap
2020-06-01 01:41:56 +03:00
35d9759fa6 Fix for issue 3974 m_connectedCount incorrectly decremented when no connection exists
There is no need to decrement if nothing was removed from removePeerDevice

Reference issue:
#3974
2020-06-01 01:35:01 +03:00
04267e12da Fix swapped USB pins issue 2020-05-30 17:36:26 +03:00
86494d5cb9 Update CMakeLists.txt 2020-05-30 17:28:25 +03:00
12a8779fd6 what happened to no-stub? 2020-05-30 16:50:24 +03:00
6ecd249a4a how about now? 2020-05-30 16:40:55 +03:00
b15f5bac79 what if functions are in the core? 2020-05-30 15:22:52 +03:00
3d7f9d9282 try to fix linking errors 2020-05-30 15:09:01 +03:00
dc3394d6ac hopefully all is here now 2020-05-30 14:50:26 +03:00
351a651295 Once again 2020-05-30 14:19:46 +03:00
d009787a6f Update TinyUSB 2020-05-30 14:06:28 +03:00
57b7e4c678 Add support for no-stub usb s2 flashing 2020-05-30 12:38:52 +03:00
345055050b Pull latest IDF and enable TinyUSB 2020-05-30 03:58:15 +03:00
09bff5027d Add a new board of KITS for IoT education (#3703)
* Add 'KITS Edu ESP32' board definition

add 'KITS Edu ESP32' board definition

* Modify board name

the board name was modified.

* Change the board name

Finally, we decided the board name.

- 'KITS ESP32 EDU'

Co-authored-by: Hamson Park <hamson.park@koreaits.com>
Co-authored-by: Hamson Park <hspark3235@gmail.com>
2020-05-29 11:46:25 +03:00
79f77afc98 update M5Camera pins (#4021)
* change m5camera pins

* add M5Camera version B pins

* add M5Camera version B pins
2020-05-22 12:59:33 +03:00
594ee6d249 Update SD_MMC.cpp (#4020)
According to ESP-IDF API
dc14d027ce/docs/en/api-reference/peripherals/sdmmc_host.rst :

"To configure the bus width, set the width field of :cpp:class:`sdmmc_slot_config_t`. For example, to set 1-line mode:

sdmmc_slot_config_t slot = SDMMC_SLOT_CONFIG_DEFAULT();
slot.width = 1;
"
2020-05-22 11:07:40 +03:00
934841e236 Added missing wifi_provisioning dependency. (#4003)
Co-authored-by: Paul <Paul.Martinsen@NumberEightInnovation.com>
2020-05-22 10:30:21 +03:00
cda6facdc7 Disable modem sleep by default on S2 for now. 2020-05-19 02:44:08 +03:00
eccbfdb48a add psram to malloc only if interrupts are not in IRAM 2020-05-19 02:03:24 +03:00
27e61dcaf5 fix psram always init 2020-05-19 01:56:52 +03:00
7553683bd2 fix issue with rtc wdt 2020-05-19 01:49:29 +03:00
40c325bd0a update idf libs, disable WDT on S2, use malloc for PSRAM 2020-05-19 01:18:55 +03:00
4f7e8065c0 Disable IRAM ISRs and functions by default 2020-05-19 00:08:10 +03:00
05db08e20a Update esp32-hal-gpio.c 2020-05-17 20:19:00 +03:00
ad067eab2d Update main.cpp 2020-05-17 15:36:41 +03:00
31d5120e04 some i2c fixes 2020-05-17 14:54:41 +03:00
d1110013af Update WPS.ino 2020-05-17 13:50:19 +03:00
caca107719 Update WiFiProv.ino 2020-05-17 13:41:45 +03:00
279f7e33be Update WiFiBlueToothSwitch.ino 2020-05-17 13:37:04 +03:00
f3835ea89f Update WiFiClientEvents.ino 2020-05-17 13:32:47 +03:00
0d61996917 more example fixes 2020-05-17 13:30:19 +03:00
88f1b235e6 fix wrong bootloader path in pio scripts 2020-05-17 13:23:29 +03:00
400aca52ce fix some examples 2020-05-17 13:12:58 +03:00
3fb164224d fix WiFi 2020-05-17 11:48:31 +03:00
cebaf93dd8 Fix PSRAM support 2020-05-14 19:02:35 +03:00
176e5b0e79 Update esp32-hal-uart.c 2020-05-14 04:03:26 +03:00
9a16cd4600 Update esp32-hal-uart.c 2020-05-14 03:04:10 +03:00
b769dd0de3 Fix Serial 2020-05-14 02:57:52 +03:00
7f1b7ade7b Update HardwareSerial.cpp 2020-05-13 19:26:34 +03:00
806e388d23 Add I2C IDF Wrapper 2020-05-13 19:04:26 +03:00
07f1bceef4 fix compile errors for esp32 2020-05-13 17:49:27 +03:00
aa61b75aa4 fix peripherals 2020-05-13 17:41:08 +03:00
48dfc89ccb Update on-push.sh 2020-05-12 20:07:29 +03:00
c6bae38ce9 Update install-platformio-esp32.sh 2020-05-12 16:46:10 +03:00
87d5f9d121 fix py script 2020-05-12 14:35:42 +03:00
ed2115e361 new try at pio 2020-05-12 14:32:24 +03:00
644f7a8a2f does not work 2020-05-12 13:09:59 +03:00
81cdcc9e27 how about now? 2020-05-12 12:48:36 +03:00
04988bdb21 try outputing the map 2020-05-12 12:36:15 +03:00
2103a789b6 Update on-push.sh 2020-05-12 12:19:26 +03:00
669cbec58e Update platformio-build-esp32.py 2020-05-12 11:38:56 +03:00
4f4bf07726 Update platformio-build-esp32.py 2020-05-12 11:36:45 +03:00
1840ba5c53 try pio again 2020-05-12 11:27:04 +03:00
20028a2027 Update on-push.sh 2020-05-12 03:10:19 +03:00
2977df4648 Update on-push.sh 2020-05-12 02:33:26 +03:00
5320123e04 Update WiFiTelnetToSerial.ino 2020-05-12 02:22:48 +03:00
0a0ee87ba5 skip more examples 2020-05-12 02:16:29 +03:00
1bb1160dea Update esp32-hal-i2c.c 2020-05-12 02:09:29 +03:00
a744383cbd Update SD_Update.ino 2020-05-12 02:01:04 +03:00
7ea54ab6aa Create .skip.esp32s2 2020-05-12 01:54:40 +03:00
fd70e0d071 skip some examples 2020-05-12 01:48:34 +03:00
0e3994c966 Update SPI_Multiple_Buses.ino 2020-05-12 01:26:40 +03:00
5d7032d4f2 Update TouchRead.ino 2020-05-12 01:21:00 +03:00
46abedcc1a disable BT Serial examples for S2 2020-05-12 01:16:30 +03:00
a6a68a9546 Update ResetReason.ino 2020-05-12 01:10:54 +03:00
062d4b123f Update on-push.sh 2020-05-12 01:04:27 +03:00
ad68da6e41 try s2 ci 2020-05-12 01:02:03 +03:00
f69b40dfff fix provision compilation 2020-05-12 00:43:43 +03:00
3a554c55f4 fix cmake check 2020-05-12 00:22:37 +03:00
03d3d6112b Update app_httpd.cpp 2020-05-12 00:07:11 +03:00
05df11e0d9 some compile fixes 2020-05-12 00:01:48 +03:00
c2be29eb97 Merge branch 'master' into esp32s2 2020-05-11 23:35:43 +03:00
49c47884a7 Update CameraWebServer.ino 2020-05-11 23:28:27 +03:00
0ea23fe38a Update esp32-hal-gpio.c 2020-05-11 21:36:23 +03:00
7f560284ff Add S2 variant 2020-05-11 20:24:34 +03:00
8569b2c893 Initial Commit 2020-05-11 20:00:33 +03:00
49b76649f1 HardwareSerial bugfix & improvement (#3713)
Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-05-05 17:55:58 +03:00
5d9bb5cf50 Allow using custom linker scripts (#3735)
Co-authored-by: Ivan Kravets <me@ikravets.com>
2020-05-04 16:47:14 +03:00
c8215315ae Add M5Stack-ATOM Board (#3883)
* Add M5Stack-ATOM Board

* Add M5Stack-ATOM Board

* Add M5Stack-ATOM Board

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-04-23 13:39:31 +03:00
4d118b36a2 Minor modifications in provisioning (#3919) 2020-04-21 14:39:26 +03:00
2c9b648502 Add support of unified provisioning to Arduino
1. WiFiProv.ino sketch is added that allows arduino users to do provisioning via SoftAP or BLE. WiFi.beginProvision( ) API is designed for provisioning in Arduino.
2. In WiFiProv.h provisioning class is defined.
3. WiFiProv.cpp contains implementation for provisioning class.
4. README.md file is added which contains detail information for working.
2020-04-15 23:37:55 +03:00
5508689ea3 Update install-platformio-esp32.sh 2020-04-13 12:47:34 +03:00
93d77859d9 Add fixes 2020-04-07 01:34:13 +03:00
0f772270fb add new board Handbit (#3807)
* add handbit

* add handbit pins_arduino

* Update boards.txt
2020-03-12 10:16:50 +02:00
13e02063d6 Move _STREAM_BOUNDARY before _STREAM_PART (#3720)
The boundary delimiter (_STREAM_BOUNDARY) needs to be send before the
body part (_STREAM_PART) too follow RFC2046. This caused ffplay/ffmpeg
to fail to open the MJPEG stream.
2020-02-14 11:03:38 +02:00
9b75c65fc7 Add Senses's WEIZEN board from Senses IoT platform (#3687)
* Add Senses's WEIZEN board from Senses IoT platform

* Add Senses's WEIZEN board (updated variant)
2020-01-29 17:08:14 +02:00
109ba7a3b4 Revert "std::shared_ptr Memory Leak (#3680)" (#3682)
This reverts commit b2c678877c.
2020-01-29 12:30:08 +02:00
b2c678877c std::shared_ptr Memory Leak (#3680)
* std::shared_ptr Memory Leak

clientSocketHande and _rxBuffer are std::shared_ptr, the stop() call was not correctly releasing them and the operator= had similar problems fix for #3679

* operator= second attempt

* operator= third time
2020-01-29 12:18:54 +02:00
856e596c79 Pass ethernet events to the main handler 2020-01-27 18:03:03 +02:00
354e485c4b get smart config to work as well 2020-01-27 17:34:30 +02:00
1c4966566c make ETH work 2020-01-27 16:22:07 +02:00
4bb60f68da Update package_esp32_index.template.json 2020-01-27 13:50:33 +02:00
ed220bd042 Minimize HardwareSerial Receive and Transmit delays (#3664)
* Minimize HardwareSerial Receive and Transmit delays

* Remove uartRxFifoToQueue from esp-hal-uart.h

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-01-27 00:38:06 +02:00
80f9f9aeec fix removeApbChangeCallback() error in spiStopBus() (#3675)
* fix removeApbChangeCallback() error in spiStopBus()

spiStartBus() was using spiStopBus() to init the hardware, one of spiStopBus() functions is to unregister the runtime CPU clock speed change callback. But, spiStartBus() only wanted to init the hardware.  This patch separates the hardware init into a standalone function spiInitBus() that both spiStartBus() and spiStopBus() call.

* Update esp32-hal-spi.c

capitalization problem
2020-01-27 00:20:19 +02:00
251d5ef92b Update CMakeLists.txt 2020-01-25 22:41:03 +02:00
8c723be135 Initial IDF-4.0 port
SmartConfig and ETH need some work to adapt to the new API
2020-01-25 16:24:19 +02:00
b50a1755c8 Use python3 in CI 2020-01-25 15:26:16 +02:00
bb0a194bb7 fix WiFiClient.connected() (#3654)
WiFiClient.connected() was hanging thinking there was still a connection when the remote had already closed. The one-liner in this patch addresses recv() returning 0 and errno==128. I couldn't find the corresponding errno for 128 but its caught by the case statement which includes EPIPE, ENOTCONN, ECONNRESET and ECONNABORTED so I assume its one of those. Broken pipe maybe?
```c
[D][WiFiClient.cpp:511] connected(): Disconnected: RES: 0, ERR: 128
```
EDIT: added comment to reflect that recv() can set errno when it returns 0.
2020-01-21 12:36:03 +02:00
ed59ae6482 Update README.md (#3653) 2020-01-21 12:35:05 +02:00
b4a9684a74 Fix SerialBT.flush (#3579)
* Fix flush

flush should not flush the read buffer, it should wait till all output is drained from the write buffer.

* Update BluetoothSerial.cpp

Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
2020-01-20 22:34:57 +02:00
1977370e6f IDF release/v3.3 (#3339)
* IDF release/v3.3 46b12a560

* fix build

* IDF release/v3.3 367c3c09c
2020-01-20 22:07:04 +02:00
307b1368dd Implement BTSerial onData to dynamically receive packets from SPP (#3649) 2020-01-20 19:43:52 +02:00
32d5654aa6 Implement rmtLoop to be able to continuously send pulses (#3650)
Number of pulses is limited to the reserved RMT memory for the channel. Very useful for PWM, Servo and other repeatable signals.
2020-01-20 19:43:13 +02:00
7637a739cc Fix recent commit d8b2098 (PR #3377) which includes esp_adc_cal component but does not update CMakeLists.txt (#3648) 2020-01-20 18:40:40 +02:00
cd85239252 Added file.close to examples (#3611) 2020-01-20 16:47:40 +02:00
ac9d04a400 Add BLEDevice::stopAdvertising() helper method to compliment startAdvertising(). (#3624) 2020-01-20 16:31:12 +02:00
2195109ecc Added the channel parameter to the scan fucntion in order to select which channel to scan. (#3638)
The default value is 0 (= all channels) to preserve backward compatibility.
2020-01-20 16:13:10 +02:00
8d938c849d Add HONEYLemon board (#3640)
* add board HONEYLemon
2020-01-20 16:12:02 +02:00
cb005fc8b5 Extend BLEDevice::setPower() to include powerType parameter. It's optional and set to ESP_BLE_PWR_TYPE_DEFAULT for compatibility. (#3623)
Extend BLEDevice::setPower() to include powerType parameter. It's optional and set to ESP_BLE_PWR_TYPE_DEFAULT for compatibility.
2020-01-20 16:09:02 +02:00
89351e3ade Update WiFiClient.cpp (#3608)
fixed the connected() function so that it only checks errno if recv returns a value of -1.

"in the even of an error, errno is set to indicate the error" --manpage

This fixes the ESP32 Webserver when dealing with a modern webserver with a slow SD card.
2020-01-20 16:08:17 +02:00
86de90fe24 Added partition and flash size menus for VintLabs boards (#3602)
add the partition and flash size menus for the VintLabs board definitions.
2020-01-20 16:07:53 +02:00
5960cd3e2a update coreESP32 boards.txt (#3569) 2020-01-20 16:06:55 +02:00
82e208c8c9 Fixed incorrect board name for TinyPICO - You can now use this to detect it's a TinyPICO at compile time.... (#3567)
#ifdef ARDUINO_TINYPICO
   // It's a TinyPICO!
#endif
2020-01-20 16:06:25 +02:00
e7c9813625 Added Piranha ESP-32 and Metro ESP-32 boards (#3542)
Added two boards from iarduino.ru based on ESP-32
2020-01-20 16:06:06 +02:00
dd78794311 Update CaptivePortal.ino (#3628)
Small change to insure wifi starts off and avoid crashing
2020-01-20 16:04:21 +02:00
0607d36734 HardwareSerial::write(const char*, ...) API compatibility to AVR, ESP8266, et al (#3585)
* API compatibility to AVR, ESP8266, et al

* Add non-blocking HardwareSerial::read(buffer, size) extension (ESP8266 portability)

* Refactor for fewer indirect calls.
2020-01-20 15:54:50 +02:00
6e77f7f3e5 Setting loging level to VERBOSE on Semaphore::take (#3545) 2020-01-20 15:50:19 +02:00
915d45de7d Defined BLE setAdvertisementType (#3535)
Currently we have no way to set BLE Advertisement Type.
We have an initial value of ADV_TYPE_IND and the member is private.

iBeacon should advertise with ADV_TYPE_NONCONN_IND.
esp-idf's example code specifies this value.

93a8603c54/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/ibeacon_demo.c (L57)
2020-01-20 15:42:38 +02:00
lj
c2b37d95e0 Updated BLERemoteCharacteristic to exposre esp_gatt_auth_req_t parame… (#3531)
* Updated BLERemoteCharacteristic to exposre esp_gatt_auth_req_t parameter for readValue and writeValue.

* Updated BLERemoteCharacteristic/Descriptor to expose a setAuth method to allow tweaking the authentication request type for that remotecharacteristic/descriptor without the need to add auth on each read/write.
2020-01-20 15:40:13 +02:00
2f13a960ac Add WIFI_REASON_CONNECTION_FAIL in WiFiGeneric.cpp (#3529)
`WIFI_REASON_CONNECTION_FAIL` has been added to `wifi_err_reason_t` some time ago:  
cec3fca4ad/tools/sdk/include/esp32/esp_wifi_types.h (L95)

But it was still missing from `system_event_reasons` in `WiFiGeneric.cpp` sometimes causing panics here:  
cec3fca4ad/libraries/WiFi/src/WiFiGeneric.cpp (L348)
2020-01-20 15:38:58 +02:00
579e04be25 Cleanup SPI_Multiple_Buses (#3527)
* Utilize prepoc symbols for SPI pins
* Adjusts for GPIO pins when ALTERNATE_PINS is set
2020-01-20 15:37:47 +02:00
5443d7ca93 Add TTGO T Journal Camera module & improve commenting (#3515)
Added pinout for TTGO T Journal device and improved the intent of comments.
2020-01-20 15:33:38 +02:00
7b3c1dfd50 Fix inability to use all buffers in RMT (#3512)
With the >= used let's say you have four RMT inputs, each using 2 channels wide for their receive buffer. This is 4*2 = 8 buffers which is the number of hardware buffers (MAX_CHANNELS). But, for the fourth input the starting buffer will be 6 (this is correct, the buffers used for each input are 0-1, 2-3, 4-5, 6-7). But, 6+2 = 8 which  is MAX_CHANNELS. This is valid but the >= would match against it and abort. It is correct to only abort if the value i+j is only greater than MAX_CHANNELS. Thus, a simple one character fix. Delete the equals sign.
2020-01-20 15:31:44 +02:00
85ef51ffbc BLE: reception support multiple service data (#3502)
* BLE: reception support multiple service data

* fix prev commit, i not inicialized
2020-01-20 15:30:29 +02:00
36075257c2 WString explicit converters to reduce Flash size (#3497)
* WString explicit converters to reduce Flash size

This is a port from the same patch for ESP8266: https://github.com/esp8266/Arduino/pull/6759/files
2020-01-20 15:29:16 +02:00
7de1717640 Fix replacing of headers with overlapping names. Fixes issue #3483 (#3487)
If two headers with overlapping names are added while replace == true, like in:
```cpp
http.addHeader("api_token",  "pMXFOLpinQqajaRQJYMeWObg2XYmcX1");
http.addHeader("token", "1234");
```
then replacing went wrong. This is fixed with this PR.
2020-01-20 15:27:51 +02:00
8869d39d79 Created variant for LilyGo TTGO LoRa32-OLED V2 (#3479)
Hi,

I have added a variant for the LilyGo TTGO LoRa32-OLED V2, which is similar to the LilyGo TTGO LoRa32-OLED V1 but with a different pinout. This will be useful for PlatformIO users, specially because I am also adding the board there as well.

Cheers.
2020-01-20 15:24:19 +02:00
Bob
cfe8526ec8 Add Uri with support for regexUri and globUri (#3441)
* Add Uri with support for staticUri, regexUri and globUri

* Add newline to end of files

* Update example

* Suppress gcc warnings (unused params)
2020-01-20 15:21:01 +02:00
c09ec5bd3d Added MGBOT IOTIK 32A and IOTIK 32B boards (#3427) 2020-01-20 15:19:35 +02:00
d8b2098461 Use IDF's ADC Driver and Add analogReadMilliVolts (#3377) 2020-01-20 15:18:56 +02:00
3fc974f3aa bugfix(touchpad):swap touch8 and touch9 #3584 (#3620) 2020-01-09 08:11:40 +02:00
9ad860758c Fix Memory leak in addApbChangeCallback() (#3560)
* `ledcWriteTone()` added a `apbcallback()` evertime the tone value was non zero.  
* `addApbChangeCallback()` did not detect duplicate callbacks.
* changed the apbcallback list to a double link to support roll forward, roll back execution.  This made the sequences of clock change callback start with the newest registered -> to oldest on the `before` then oldest -> newest after the clock change.  This made the UART debug log output have minimal gibberish during the clock change.
* change how the UART callback handled the MUTEX because if any `apbchangeCallback()` executed a `log_x()` a deadlock would occur.

This fixes #3555
2019-12-30 21:35:29 +02:00
cec3fca4ad Fix BluetoothSerial crash when restart (#3471)
* Update esp32-hal-bt.c

BluetoothSerial crash when restart:  this is because the BT controller remains in state  ESP_BT_CONTROLLER_STATUS_INITED instead of state  ESP_BT_CONTROLLER_STATUS_IDLE after the end() method.
in file esp_bt.h it is specified

> @brief Enable BT controller.
>                Due to a known issue, you cannot call esp_bt_controller_enable() a second time
>                 to change the controller mode dynamically. To change controller mode, call
>                esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode.

after **esp_bt_controller_disable()** the controller remains in state INITED so we do call the **esp_bt_controller_deinit()** function to put the controller into state IDLE.

i have modified the **esp32-hal-bt.c** file
line 57 and next
(i have insert the esp_bt_controller_deinit() function so the controller go into Idle state)
```c++
bool btStop(){
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
		log_i("bt stopped");
        return true;
    }
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
		log_i("bt enabled");
        if (esp_bt_controller_disable()) {
            log_e("BT Disable failed");
            return false;
        }
        while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
    }
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
		log_i("inited");
		if (esp_bt_controller_deinit()) {
			log_e("BT deint failed");
			return false;
		}
		while (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED);
        return true;
    }
    log_e("BT Stop failed");
    return false;
}
```

* Update esp32-hal-bt.c

remove while to avoid infinite loop
2019-11-11 18:31:09 +01:00
dac493fb92 SPI: Fix discarded-qalifiers warning when compiling with all warnings (#3458)
* SPI: Fix discarded-qalifiers warning when compiling with all warnings

This fixes an error introduced with changeset b847f41 which
tightened the use of const for read-only data. The helper
funtion __transferBytes also requires the const qualifier on
outgoing data. Without this change a warning is displayed
when compiling with the Arduino IDE set to display "All"
compiler warnings.

Tests:
 - Build an ESP32 SPI sketch that uses static const data to send
   to an SPI device using the SPI.transferBytes() API

* SPI:Ensure all local functions are marked static

This audits all functions in the esp32-hal-xpi.c module and
ensures that any functions entirely local to the module are
marked as static.

Tests:
 - Build with Arduino set to show all warnings and ensure none
   are displayed

* SPI: Remove unused local __spiTranslate24 function

This removes the __spiTranslate24() function which is unused.
2019-11-11 17:44:49 +01:00
bc3d11364f Fixed incorrect usage of xEventGroupWaitBits (#3446)
* Fixed incorrect usage of xEventGroupWaitBits

* Added parentheses and `!= 0`
2019-11-11 17:34:01 +01:00
f41beb92bf Fixed so configTime will not crash if tcpip is not initialized (#3470) 2019-11-11 15:50:56 +01:00
8c4ca5a235 Update BLE_client.ino (#3463)
fix typo
2019-11-11 15:49:34 +01:00
b3085d4a8b Add menu items Partition Scheme and Debug Level for node32s (#3455) 2019-11-11 15:47:26 +01:00
547c2d3346 Root CA of webserver has changed, minor changes (#3447) 2019-11-11 15:45:26 +01:00
7d2632c024 Implement Tx only Flush (#3433)
* add option to Flush() to only clear txQueue

Add the option to cause Flush() to just wait for tx data to clear the tx fifo and uart, leave the rx queue and rx fifo as is.

* support tx only flush()

* support tx only Flush()

* support txOnly for Flush()

* compatibility to Stream()

* compatibility for Stream()

* default value error

* default value error

* Update esp32-hal-uart.h

* Update esp32-hal-uart.c

* Update HardwareSerial.cpp

* sp

* correctly implement flushTxOnly()
2019-11-11 15:37:35 +01:00
e59355df71 Docs for lib builder (#3415)
* Docs for lib builder

* Typos and such
2019-11-11 15:30:52 +01:00
ec63d09e54 Fix WiFiGeneric event handler (#3412) 2019-11-11 14:24:50 +01:00
xk
188560e7f3 Some event log messages were off by one. (#3391)
This event name was missing in the list:
d5e2bb12ca/tools/sdk/include/esp32/esp_event_legacy.h (L43)

E.g., it was giving
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 24 - ETH_GOT_IP
When it should have been
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 24 - ETH_DISCONNECTED
2019-11-11 14:21:24 +01:00
91e095f5a7 Add an error message in case of invalid configured dependency mbedTLS. (#3364)
Especially if the user wants to use the library as component in IDF,
there are some pitfalls while doing make menuconfig. One is this missing
dependency which will now fail with a better error message with a hint to
the user how to fix it.

refs #2154 #3215
2019-10-17 09:48:36 +03:00
c8d8dc2265 Added partition size options for TinyPICO (#3358) 2019-10-15 01:32:40 +03:00
b847f41e24 SPI: Ensure all read-only data pointers are marked as const (#3356)
This changes all SPI functions that take data pointers which are
not modified so that the declaration is const. This allows them
to be used with const data (i.e. held in flash). No functional
changes are required.

The defnitions of spiWrite() and spiTransferBytes()  in
esp-hal-spi.h/c have been updated to be consistent.

Tests:
 - Build a simple sketch using SPI.writePattern() and
   SPI.transferBytes()  which uses const data and verify that the
   attached device functions as expected.
2019-10-14 20:39:27 +03:00
611ba8ea8a Update README.md (#3353) 2019-10-14 20:38:04 +03:00
0cab2483e6 Added a description README.md for libraries (#3349) 2019-10-14 20:37:09 +03:00
Luc
79e4339582 Remove warnings if no debug enabled (#3334) 2019-10-08 10:35:42 +03:00
a35035f827 fix authrization problem (#3329)
I compiled the sample "WebServer -> HttpAdvancedAuth". But the right username and password can not login in. I found the file "Webserver.h" may be have some problem. So I fix it. Please check it.
2019-10-08 10:34:36 +03:00
9ef3e2d2a6 Allow sketches to have custom partitions (#3328)
Add a file named `partitions.csv` to your sketch folder and define the partitions inside. In order to not get `Sketch too big`, please select appropriate partition scheme from the board menu
2019-10-07 02:07:15 +03:00
0cdfb0b193 Add support for WiFi long range mode (#3190)
* Add support for WiFi long range mode

* Update WiFiGeneric.cpp
2019-10-06 17:43:15 +03:00
e50613622e Fix typo in SPIFFS and FFAT examples (#3322)
* fix typo in SPIFFS example

* fix typo in FFAT example
2019-10-06 17:29:28 +03:00
24b277ad92 Add readFloat to BLE (#3321)
* Add readFloat

* Add readFloat to BLE
2019-10-06 17:28:53 +03:00
c2b3f2d6af Make yield() overridable (#2991) 2019-10-04 12:49:39 +03:00
8fb8e7d060 CI can be used on windows desktop with msys 2019-10-02 20:03:43 +03:00
048b26547a Update boards_manager.md 2019-10-02 16:06:15 +03:00
b10ed77aaf Update boards_manager.md 2019-10-02 15:58:58 +03:00
4638628873 Wait for client.available() to prevent ESP32 crashes (#3154)
* Wait for client.available() to prevent ESP32 crashes

* Removed user-specific SSID & passphrase
2019-10-02 14:45:42 +03:00
6f70e27011 Base64::encode : const correctness / String by reference passing (#3314)
Avoid passing String by-value, which is slightly less efficient
as it involves a full copy-constructor/tempstring creation.
2019-10-02 14:29:24 +03:00
d0b064a1ee Update CI scripts for better error handling (#3316) 2019-10-02 11:58:02 +03:00
85c77a9c3f Fix CI Builds for Linux (#3313) 2019-10-01 23:13:08 +03:00
c8e3f0c732 Support Pi 4 on 64bit kernel 2019-10-01 22:15:13 +03:00
5ad468f9dc Add ARM toolchain 2019-10-01 21:48:03 +03:00
38c4c06108 Support for Master mode, Pin and SSP (#3219)
* 20190916 - initial: support for Master mode, Pin and SSP

* 20190916 - initial: Add example app for Master mode

* 20190916 - initial: Force another build

* 20190916 - connect would use resolved address as preference and remove now redundant _remote_address

* 20190916 - rework set/reset/default pin logic

* 20190916 - cleanup: remove static vars, add/use constants, fix typos

* 20190916 - fix build issues and implement geoup events for status verification.

* 20190916 - remove extra lines,misc

* 20190916 - rework ESP_BT_GAP_DISC_RES_EVT, added SPP_DISCONNECTED bit for disconnect event. + timeout for disconnect()

* 20190916 - Small log change to improve log sequencing

* 20190916 - remove static from local vars

* 20190916 - Limited scope and duration for the scan, log device address during scan in info mode as it is very difficult to find out sometimes. Fixed get_name_from_eir() not resetting the name when called.

* 20190916 - break property for loop during scan when name matches.

* 20190916 - misc

* 20190916 - SPP_DISCONNECT state updates

* 20190916 - formatting, remove some strange syntax from initiator code

* 20190916 - Add comments to the example about connect(...) usage and timeouts

* 20190916 - fix disconnect() without timeout

* 20190916 - Add example comment to view BT address and name during connect(name)

* 20190916 - wording in example comments

* 20190916 - rework connect() and disconnect() methods to help with concurrency and more authoritative status returned back to caller. Automatic disconnect in connect() methods

* 20190916 - optimize code

* 20190916 - optimize code - more

* 20190916 - add timeout for pin set

* 20190916 - change scan mode to ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE

* 20190916 - update example code slightly

* 20190916 - increase READY_TIMEOUT to 10 secs

* 20190916 - typo in example and move waitForConnect() to static area

* 20190916 - update example comments

* 20190916 - update example comments

* 20190916 - update example comments

* 20190916 - add new example to remove paired devices from ESP32

* 20190916 - correct typo in example

* 20190916 - update example comment, add remove_bond_device() method for convenience.

* 20190916 - reword example comment.

* 20190916 - rename remove_bond_device()

* 20190916 - rename removePairedDevice() to unpairDevice()

* 20190916 - code review changes

* 20190916 - fix return value in setup() od example
2019-10-01 17:34:46 +03:00
b334b2c2f9 Add config, menu partition Wrover (#3147)
* add config, menu partition Wrover

* fix all boards
2019-10-01 17:10:16 +03:00
8a46697168 Fix for issue_3209. (#3210)
#include "esp32-hal-log.h" is mandatory is order to build BLEDevice.cpp.
It can't be left up to a compiler variable.
2019-10-01 16:32:47 +03:00
270a2759d9 Add pages action (#3311)
* Add script to handle updates to the docs folder

* Create gh-pages.yml

* Update on-pages.sh
2019-10-01 16:04:20 +03:00
01d9345d28 Update development JSON location 2019-10-01 12:14:07 +03:00
71e3d515f3 Fix BLEUUID toString (#3289)
uuid16 is Missing first 4 characters.
uuid is Missing last 2 characters.
2019-10-01 11:54:21 +03:00
64cfb33deb Add Added unimplemented getCharacteristicsByHandle function (#3277)
* Add Added unimplemented getCharacteristicsByHandle function

Defined in BLERemoteService.h
But, Not included in BLERemoteService.cpp

* Delete log output
2019-10-01 11:43:59 +03:00
5f1dff7dad IDF release/v3.2 d3e562907 (#3292) 2019-10-01 11:21:44 +03:00
40ebee1cb1 Update BluetoothSerial.cpp (#3308) 2019-10-01 11:10:31 +03:00
ed96d2a1b7 Use Github Actions for release (#3309)
* move scripts and tone down travis

* Update and rename main.yml to push.yml

* Create release.yml
2019-10-01 10:44:04 +03:00
caa391ab34 More efficient CI builds (#3303)
* More efficient CI builds

* Update main.yml
2019-09-30 12:10:48 +03:00
3b71e136e1 Builder scripts update (#3300) 2019-09-30 02:01:29 +03:00
1c77790a5b allow the examples to build in a more strict env (#3299) 2019-09-29 23:47:02 +03:00
5bff89f0be Fixed issue-3153 - Allocating enough memory to construct the entire UUID as a String. (#3297) 2019-09-29 23:03:48 +03:00
9bbd720d4c Update BLEDevice.cpp (#3267)
Pretty sure this was a typo as the deinit doesn't actually allow for reinit if that is an ifndef.  Changed in my local copy and can now deinit and reinit just fine.  Also, not sure why we are checking for the architecture here.  Just curious.
2019-09-26 21:50:16 +03:00
589bb7032d Update WiFiScan.h (#3266)
Add an accessor function for the useful wifi data
2019-09-26 21:03:08 +03:00
f8c06894c5 Better cleanup on mount failures, as the idf api now seems to assign handle and mountpoint before failing. Fixes #3265 (#3282) 2019-09-26 19:12:52 +03:00
a5c873b786 Update README.md 2019-09-24 23:32:13 +03:00
895a150840 Update README.md 2019-09-24 23:23:42 +03:00
ca88fdc273 Fixed FFat::end. Fixes #3244 (#3245)
* Fixed FFat::end. Fixes #3244

* Missed the handle check in format
2019-09-24 23:23:03 +03:00
f32083a6d0 Fix timerRestart
Closes: https://github.com/espressif/arduino-esp32/issues/2944

Thanks @atanisoft
2019-09-24 19:25:27 +03:00
b30e55efff Added partition size option for Pico Kit (#3258)
The original boards.txt was missing a menu option to select the FLASH partitioning options.
2019-09-24 19:21:35 +03:00
0ac2de7aab Add partition schemes to adafruit featheresp32 (#3255)
* Add partition schemes to adafruit featheresp32

* Removed minimal partition scheme
2019-09-24 19:21:08 +03:00
0eec630314 Add missing env to PIO CI build 2019-09-24 18:49:17 +03:00
731fd19bdf Update get.py
Enable insecure download for CI
2019-09-24 17:20:58 +03:00
298c6104a2 Added board defintion for VintLabs boards (#3252) 2019-09-24 12:26:15 +03:00
8ea12f89f3 Update pins (#3249) 2019-09-23 10:14:33 +03:00
b3ba80d570 nvs_handle is an int, was assigning NULL. Also cleaned up end to ensure no memory leak. (#3246) 2019-09-22 23:31:38 +03:00
Luc
a5935ce1cc Add sample for Time date for FatFS like SPIFFS (#3234) 2019-09-22 09:38:24 +03:00
96d6975bd5 Changed WeMosBat.name (#3240)
The old version would crash the Stino plugin, which appears not to support quotes in board names
2019-09-22 09:37:45 +03:00
9eaeeb660c Change the first argument of SPI::wrteBytes to be const (#3242)
fixes: https://github.com/espressif/arduino-esp32/issues/3241
2019-09-22 09:36:32 +03:00
e22d8b6787 Update stale messages for easier filtering 2019-09-21 16:12:22 +03:00
Luc
56fe2dbaff Fix F_Fat::format return false when succeed (#3220)
this is due to ussage of esp_err_t result; instead of boolean, ESP_OK =0 so it is false
2019-09-21 02:34:25 +03:00
06a399b84a Extend logging of ArduinoOTA (#3217) 2019-09-16 19:54:21 +03:00
4ce2cc3c1d Fix HTTP Client with SSL (#3216) 2019-09-16 19:14:32 +03:00
07390157df Fix Camera Example (#3202)
* Update app_httpd.cpp

* Stop LWIP from using PSRAM and enable OV7725
2019-09-13 01:19:53 +03:00
bab3a70f54 Added timeout to WiFiScan.cpp to prevent getting stuck at WIFI_SCAN_RUNNING (#3197)
* Added timeout to WiFiScan class to prevent haning at stucking at WIFI_SCAN_RUNNING when scan fails internally

* fixed tabs and returns, connected scanTimeout to max_scan_per_channel timeout

* Corrected tabs two

* Added static vars scanTimeout und scanStarted to WiFiScan.h protected section

* Fixed missing ; in line 64
2019-09-11 15:58:34 +03:00
cd4f9038ee Fix WiFi disconnect event not being propageted. (#3085)
Relative to #3006
2019-09-11 15:12:15 +03:00
7fe2812f7f Inline ESP::getCycleCount() to make it safe to call from ISRs (#3165)
* Inline ESP::getCycleCount() to make it safe to call from ISRs

* Attribute IRAM_ATTR ISR-safe function in addition to inlining.
2019-09-11 14:29:53 +03:00
Luc
9710fedaf0 Fix wrong values in .cvs files (#3196)
* Fix wrong values in .cvs files

Add missing upload size for partitions bigger than default one

* Add new partion to generic

Fix hardcoded partition for 16M flash
2019-09-10 22:52:51 +03:00
f5cacfee1a Remove extra connects from Client.h (#3191) 2019-09-09 09:36:22 +03:00
f71a4bd406 Bugfix/detect baudrate (#3188)
* Expose uartStartDetectBaudrate(uart_t *) in esp32-hal-uart.h and call it from HardwareSerial::begin() if baudrate detection is requested (by passing a baudrate of 0) to solve baudrate detection problems

* Avoid a division by zero error in uartGetBaudRate()
2019-09-09 00:59:32 +03:00
5f77b0108b Fix return of Print::print(timeinfo, format) (#3189) 2019-09-09 00:36:30 +03:00
717ca79ecb #3181 printf double vsnprintf() fix, malloc, va_end (#3184)
* Use loc_buf for small strings, check for error return from vsnprintf

* cleanup arg when bailing out of new

* Use malloc/free instead of new/delete in printf

* Return actual bytes written in printf

* FIX: write before free
2019-09-08 23:49:32 +03:00
07613b3158 Update URL to point to upstream repository (#3187)
Pointing to an old fork is misleading.
2019-09-08 23:15:46 +03:00
80ea521940 Add support for 160MHz rated CPUs (#3135)
Some ESP32 chips are rated only to 160MHz. This change adds support for them and does not allow frequency to be switched to 240MHz
2019-09-05 12:30:43 +03:00
5c04de6f39 Fix packager 2019-09-05 11:22:40 +03:00
0d163a1ce2 Update IDF 3.2 to 7dd492319 + WiFi fix (#3177) 2019-09-05 11:08:45 +03:00
2a7e509978 Fix long Ticker period conversion: cast ms to uint64_t when calculating us (#3175)
* Fix long Ticker period conversion

* Simplify long Ticker period conversion fix by using 1000ULL
2019-09-05 10:34:47 +03:00
1b8c7e34f9 Try bash only examples build (#3164) 2019-09-01 18:45:55 +03:00
7a574399b1 Rework the sketch builder to match the IDE (#3146)
* Rework the sketch builder to match the IDE

* Link the board to the home folder

* Rename files for clarity

* move ci files to own subfolder

* Update Github CI to use the new script locations
2019-08-28 01:28:11 +03:00
fd089d8fd3 Pull in ESP8266 String::replace() fixes, others (#3143)
Pull in bugfixes from the ESP8266 repo for problems in the SSO
implementation of replace().  See the following patches for full
details:

54240d2cc5 (diff-8d9e71e16d437343017df828f0528f63)
78a1a66e6d (diff-8d9e71e16d437343017df828f0528f63)
4e9358445a (diff-8d9e71e16d437343017df828f0528f63)

Fixes #3140
2019-08-27 20:05:36 +03:00
f356ccd54a Added the pragma line to the top (#3139)
* Removed pragme in BLERemoteService.cpp

* Added the line at the top and changed to warning
2019-08-27 10:21:27 +03:00
6daf773464 Fix travis deploy generating bad json 2019-08-21 03:29:23 +03:00
70a896481d Update Both CIs to run parallel jobs (#3120) 2019-08-21 01:56:05 +03:00
390da0d090 bump CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM to improve RX performance (#3119) 2019-08-20 22:07:56 +03:00
d5e2bb12ca Update IDF to 90747cc8b (#3118) 2019-08-20 21:11:00 +03:00
f4acac4c2b Bugfix/http client (#2867)
* Fix persistance issue found, see ESP8266 issue #6152

* Correcting the parsing of the header for HTTP1.0

* Send 'Connection: Close' header in case of HTTP1.0

* Let reuse connection depend on protocol used: HTTP1.0 or HTTP1.1

* Fixed reuse, added null ptr checks, added check for _trainsportTraits in connect() in case _client was set null

* Fix reuse connection issues, similar to ESP8266 PR #6176
2019-08-20 17:18:09 +03:00
5137fc5c80 Ble notification/indication status and timeout (#2998)
* add timed wait

* Added Notification/Indication data and status callbacks

* imply null-object pattern for BLE callback
2019-08-20 17:15:30 +03:00
03066e42ef Flush UART RX queue too (#3009) 2019-08-20 16:48:52 +03:00
cd5257ad78 ESP.getCpuFreqMHz fix (#3007)
* ESP.getCpuFreqMHz was returning the CONFIG_ variable.  Now calls the getCpuFrequencyMhz function.

* Changed the Esp function to uint32_t to match
2019-08-20 16:48:26 +03:00
ee6336a312 links http -> https (#3010)
more secure
2019-08-20 16:47:43 +03:00
61f71930e9 The progress callback is now correctly invoked with Update.write (#3024)
The progress callback was only invoked with Update.writeStream before
2019-08-20 16:45:57 +03:00
ec40c4c96f Cast TimerWakeup conversion factor as ULL (#3027) 2019-08-20 16:45:18 +03:00
2bda4a9617 Fix BLE stop advertising not working (#3034)
BLEAdvertising::handleGAPEvent -> ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT should NOT call start()!
2019-08-20 16:44:50 +03:00
91b9fae111 Add generic IP utilities (#3038)
* Add generic IP calculations

Add:
calculateNetworkID(IPAddress ip, IPAddress subnet) => Calculate the network id using the ip and subnet (e.g. 192.168.0.0)
calculateBroadcast(IPAddress ip, IPAddress subnet) => Calculate the broadcast ip using the ip and subnet (e.g. 192.168.0.255)
calculateSubnetCIDR(IPAddress subnetMask) => Calculate the subnet CIDR using the subnet (e.g. 24)

Add:
broadcastIP() => Retrieve the network id (e.g. 192.168.0.0)
networkID() => Retrieve the broadcast IP (e.g. 192.168.0.255)
subnetCIDR() => Retrieve the subnet CIDR (e.g. 24)

Add:
broadcastIP() => Retrieve the network id (e.g. 192.168.0.0)
networkID() => Retrieve the broadcast IP (e.g. 192.168.0.255)
subnetCIDR() => Retrieve the subnet CIDR (e.g. 24)

Add:
softAPBroadcastIP() => Retrieve the network id (e.g. 192.168.0.0)
softAPNetwrokID() => Retrieve the broadcast IP (e.g. 192.168.0.255)
softAPSubnetCIDR() => Retrieve the subnet CIDR (e.g. 24)
2019-08-20 16:42:55 +03:00
2a1fde7736 Include stdint for uint16_t (#3069) 2019-08-20 16:39:31 +03:00
a12d609b22 Corrected count of characteristics to get (#3082)
Only space for 1 characteristic is allocated, requesting 10 leads to stack corruption.
2019-08-20 16:38:59 +03:00
73576674b8 add core installation 1.0.2 (#3064)
* add core installation 1.0.2

* added 1.0.3
2019-08-20 16:38:34 +03:00
007a93ec7e Update Print.cpp (#3060)
#2891
2019-08-20 16:36:04 +03:00
a5f3fc6fad Magicbit Variant (#3107)
* Updated magicbit variant

* Added LED_BUILTIN
2019-08-20 15:44:12 +03:00
65e256c40a Try github CI (#3115) 2019-08-20 15:32:47 +03:00
fa55a2c91d Update stale.yml 2019-08-01 18:55:47 +03:00
a070884441 Update stale.yml 2019-08-01 11:05:05 +03:00
a9c8b46b1a Update stale.yml 2019-07-31 16:43:58 +03:00
6954150176 Create stale.yml 2019-07-31 10:04:08 +03:00
548f712df2 Fix empty libs being included with the builder (#2997) 2019-07-17 16:48:51 +03:00
56ce580b0e Fix incorrect definition of FPSTR() and move from pgmspace.h to WString.h (#1371) (#2961) 2019-07-17 10:16:47 +03:00
509d31ba51 create variant for magicbit board (#2987)
* create varient for magicbit board

* update boards.txt
2019-07-17 10:10:45 +03:00
9e32cec9a2 Update IDF to a8916daeb (#2992) 2019-07-17 10:09:43 +03:00
3376ea1bd5 Added more menu settings for TinyPICO - Fash mode and Flash speed. Set Flash mode default to QIO (#2976) 2019-07-16 17:15:13 +03:00
1c7e329140 RMT: Fix in bitshift of NeoPixel example project (#2986)
Fixed bit shift in demo application of using RMT peripheral. Init data array to be transmitted was off by one, as for the first iteration (i==0) the mask was 1<<8, which results in shifted RGB value in color variable
Closes https://github.com/espressif/arduino-esp32/issues/2921
2019-07-16 17:14:28 +03:00
c17b212cd0 WPA2 connection fix (significant improvement to connection time) (#2989)
* Config fix test

* Also force config even if equal
2019-07-16 17:12:20 +03:00
7dbda4988b Update boards.txt (#2933)
* Update boards.txt

Adding ESP32-WROOM-32 8MB flash option

* Update boards.txt

Fixing partition size and typo

* Update boards.txt
2019-07-10 09:13:09 +03:00
d1134fd45e Fix issue with semaphores (#2974) 2019-07-10 09:11:35 +03:00
d5fdd715ef WiFiClient.cpp - Fix connect() behavior (#2784)
* WiFiClient.cpp - Fix connect() behavior

* lwip_connect_r() : check return code
2019-07-09 19:48:05 +03:00
ca7106e97e Added convert method to EEPROM to transfer data from partition to nvs (#2841)
* Added convert method to transfer data from partition to nvs

* Could have sworn I changed the return when I made the label

* Empty state should be 0xFF.  Fixed some logging levels

* Set result on success
2019-07-09 19:47:06 +03:00
87e5787cf7 Added support for TinyPICO in the boards list (#2901) 2019-07-09 19:40:34 +03:00
c13d11e7d1 fix empty reply from server error (#2903)
The flush causes an empty response a client side.

see https://github.com/espressif/arduino-esp32/issues/2902
2019-07-09 19:39:12 +03:00
b0d8d4dd44 Change some WiFi buffer settings to match esp-idf. See #2899 (#2912) 2019-07-09 19:36:45 +03:00
05de017bd5 BLE Library onRead Callback fix and Client disconnect feature (#2913)
* BLEServer::disconnect()

* Invoke Read callback first, to make data update possible before read
2019-07-09 19:35:07 +03:00
e1548e9b7e Fix hang on client disconnect during upload (#2914) 2019-07-09 19:34:24 +03:00
c29ec9da3d Removed partitioning comments from EEPROM class example (#2920)
* Remove partitioning comments

* Revert "Remove partitioning comments"

This reverts commit b3b03a81572d352816819cff772231ba037dc338.

* Removed partitioning comments from EEPROM example
2019-07-09 19:34:04 +03:00
b3783fba95 fixed typo (#2927) 2019-07-09 19:31:38 +03:00
a22ec4a978 Reduce flash usage up to 214k in one click (#2929)
* std::stringstream -> std::string

* Fix small issues

* Small fix 2
2019-07-09 19:31:17 +03:00
20498cf8b1 Expand gitignore to cover files created by Visual Micro (#2934)
* Expand gitignore to cover files created by Visual Micro's Arduino IDE for Visual Studio

(cherry picked from commit d6209c79ea16a26564fe27e74e5f277160129847)

* Also ignore VS project files

(cherry picked from commit e0ec212bd41e75a3570a6098a66ee66787db58db)
2019-07-09 19:28:04 +03:00
02e51728c4 Fix Timeout Bug in WebServer (#2938) 2019-07-09 19:27:24 +03:00
d2816b2f32 Fix Unused Variable Warning (#2940)
Some Debugging variables were enabled at ERROR level instead of DEBUG.  Specifically `tAfter` and `tBefore`
2019-07-09 19:24:35 +03:00
2e32022611 ESP8266 => ESP32 tidyup, set correct default port (#2948)
Tidied up references to the ESP8266, and set the correct default port for the ESP32.
2019-07-09 19:24:10 +03:00
74ffdac74a fix for BLE Library Compile Error #2866 (#2876) 2019-07-09 19:23:01 +03:00
4ee17ec3ee Fix warning -Wempty-body by adding braces to 'if' stmt body (#2951) 2019-07-09 19:21:57 +03:00
476660f763 Cleanup WiFiMulti (#2955)
* Use macros for switch case labels

* Fixed spelling error in "too"

* Fix spacing

* Inline private functions that are only called once
2019-07-09 19:21:01 +03:00
Luc
f558e69181 Fix warnings in platformio (#2960)
Fix : warning: converting to non-pointer type 'int' from NULL [-Wconversion-null]
Fix : warning: unused variable 'res' [-Wunused-variable]
2019-07-09 19:19:16 +03:00
5bf3aab527 Make a selective menuconfig option for FFat (#2966) 2019-07-09 19:14:53 +03:00
1aced120ba docs: fix typo (#2973) 2019-07-09 19:14:27 +03:00
7d7824701f Fix persistance issue found, see ESP8266 issue #6152 (#2851) 2019-06-05 14:00:00 +02:00
89feacb813 Fix map() division by zero (#2848) 2019-06-05 13:48:13 +02:00
aae6f24a37 Update (#2838)
Added PoE-ISO and DevKit-Lipo.
For the other boards added alternative Serial (Serial1/Serial2) pins.
2019-06-05 13:44:52 +02:00
43b781a158 Update AsyncUDP library.json (#2837)
* Fix https://github.com/platformio/platform-espressif32/issues/186

* Drop library.json
2019-06-05 13:43:15 +02:00
e055b28d1a Ignore Werror-maybe-uninitialized from Azure IoT Library (#2824)
Ignore the error about a potentially uninitialized variable
in the Azure library that will occur when compiling as a component
in ESP-IDF.
2019-06-05 13:42:08 +02:00
714ba948e6 Update BLERemoteCharacteristic.cpp (#2800)
Prevents the error that is generated on free on row 186
When calling the function readValue() sometimes it gave an error on this free.
2019-06-05 13:38:49 +02:00
e57de64a3c Fixed multi_heap_free failed during setting the value of the characteristic in BLE Library. (#2789) 2019-06-05 13:37:06 +02:00
fd5a2f08f9 Fix #2750 (#2763)
* Fix #2750

* Fixes for pull comments

* latest modifications following comments from me-no-dev

* Move SPIFFSFSImpl to .cpp file
2019-05-14 00:15:35 +03:00
e9389e3122 Fix AsyncUDP buffer error
fixes: https://github.com/espressif/arduino-esp32/issues/2685
2019-05-13 23:18:38 +03:00
0acf19af8f Update IDF to v3.2 977854975 (#2771)
* Update IDF to v3.2 977854975

* Update app_httpd.cpp
2019-05-12 18:52:23 +03:00
aff2e42ac6 Add Pycom GPy board (#2754) 2019-05-11 11:24:11 +03:00
2743e7b739 Update mac.md (#2745) 2019-05-11 11:21:25 +03:00
c453a0037b Adding TTGO T1 board definition (#2744)
Fixes https://github.com/espressif/arduino-esp32/issues/2740
2019-05-11 11:20:57 +03:00
2f249edb8e Use std::abs for a float-compatible abs() function (#2738)
* Other Arduino cores uses a macro to redefine libc abs() to take any
  type, meaning abs(-3.3) == 3.3 not the normal libc result of 3.

* 1e4bf14a3 (#1783) replaced similar min, max macros with c++ stdlib. However
  this change includes <algorithm> after the line which defines the abs() macro.
  <algorithm> includes <cstdlib> which undefines abs() and re-defines it.

* This means abs() becomes the plain libc version again which only takes
  integers, so abs(-3.3) == 3. As reported here:
  https://github.com/espressif/esp-idf/issues/3405

This fix tries to keep in the spirit of #1783 by using libstdc++. The other
option would be to include <cstdlib> before defining the abs() macro, so it
doesn't get undef-ed again later on.
2019-05-11 11:18:39 +03:00
bd57ff4ab4 StreamString SSO fix (#2736)
As found by @mongozmaki in https://github.com/esp8266/Arduino/pull/6035

With SSO implementation in String, StreamString::write generates wrong
strings under some circumstances.  Reason is that String::len() returns
strlen(sso_buf) if SSO=true but with newly written data
(in StreamString::write) the null-termination missing at the time len()
is called.

Furthermore, len() is called twice which is inefficient if SSO=true.
2019-05-11 11:16:05 +03:00
43bf393dbf Fix semaphores in IDF & std::string assert (#2728)
* Fix semaphores in IDF & std::string assert 

Fixes the problem of giving a mutex from a callback with the latest IDF. Also addresses an occasional assert that happens when the btc_task callback gives the semaphore and causes an assert due to both cores potentially writing m_owner concurrently.

* Restored m_owner position in wait() as requested

* Reapply assert fix and move setting m_owner in ::give() 

Revert previous revert commit and move setting of m_owner in ::give to before giving the semaphore to prevent race condition possibility.
2019-05-11 11:03:09 +03:00
bea7bd1852 Implemented ability to change BLE address (#2690)
Implemented the ability to change the ESP32s BLE device address as
according the the BLE specification. This address is used when
advertising the ESP32 over BLE.
2019-05-11 11:02:26 +03:00
7dd537f8d3 Fix libgcc not being in rom
fixes: https://github.com/espressif/arduino-esp32/issues/2758
2019-05-09 13:07:49 +03:00
50d142950d Update esp32-hal-rmt.c 2019-05-01 20:10:41 +03:00
d13de284b8 Undo the redefinition of FPSTR from 8266 merge (#2726)
Fixes Arduino.h redefinition errors.
2019-04-30 16:52:14 +03:00
697d4ff7c4 Add board "WEMOS D1 MINI ESP32". (#2710) 2019-04-27 14:10:21 +03:00
ab309e40d5 Copy ESP8266 String w/SSO to ESP32 repo (#2715)
I redid the ESP8266 WString library to enable small string optimization
(SSO) a while back, and think it would be helpful even on the ESP32 with
its higher memory complement.

SSO avoids lots of tiny mallocs() on the heap which cause fragmentation
by using the memory in the class object itself to store the actual
string and only mallocing() for buffers that are larger than what can
fit in thie class object.  Modern C++ std::string implementations have
this optimization as well, but since we're using Arduino strings we had
to roll our own.
2019-04-26 19:41:42 +03:00
932666a03f Ensure that _size is properly set in begin (#2706)
* Ensure that _size is properly set in begin

* NULL check on _data assignment

* Changed _data to malloc in order to catch alloc fails
2019-04-26 19:39:22 +03:00
a0ad987029 Add TTGO T-Watch board definition (#2681) 2019-04-25 12:16:26 +03:00
271e5cd206 Fix Werror=reorder for idf.py build (#2707) 2019-04-25 12:02:21 +03:00
619568db5b Converted EEPROM library to use nvs instead of partition. (#2678)
* Converted EEPROM library to use nvs instead of partition.  Removed eeprom partition from all partition table CSV files.
* Changed variable names, added some comments, formatting as per me-no-dev's requests
* Checks for memory on malloc
* Moved include nvs.h from header to code
* Reworked the extra example to make it more clear how to actually use the library and persist data
2019-04-23 23:55:12 +03:00
0202ba7c21 Fix reorder error in WebServer (#2700) 2019-04-23 17:57:33 +03:00
119ece2b0f Portability from ESP8266, virtual Stream member functions. (#2701) 2019-04-23 17:56:49 +03:00
606446a830 Update ALKS board (#2694) 2019-04-23 10:52:24 +03:00
a28cf00295 add lolin32 CPU freq choice (#2682) 2019-04-22 22:00:23 +03:00
672e4faa92 Add optional support for CORS headers (#2688)
* add support for CORS headers

* remove accidental function impl

* rename setCORS to enableCORS, and add aliased function enableCrossOrigin
2019-04-22 21:52:39 +03:00
f8eebb5c39 Fix indentation 2019-04-17 23:27:32 +03:00
6bf104874a Add LGPL 2.1 License 2019-04-16 03:08:50 +02:00
9a9ff62216 Add connect with timeout to Client class 2019-04-15 18:01:43 +02:00
3d6e4e1b94 Use milliseconds for timeout 2019-04-15 17:27:54 +02:00
01d7ea7b80 Refactored use of LOG_X(LOG_TAG, ...) to log_x(...) (#2672)
* Replaced ARDUINO_VARIANT with const char

* Fixed missing return value

* Added quotes around defined value in macro (Issue #2193)

* Change logging from Error to Verbose when not found and default available

* Move Enter and Exit logging to Verbose Level

* Refactored LOG_X() into log_x()
2019-04-15 17:26:35 +02:00
Bob
af23d0bb10 Return empty string instead of "0" (#2673) 2019-04-15 17:23:42 +02:00
582e6433e9 Add proper timeout handling to WiFiClientSecure 2019-04-15 17:19:49 +02:00
ef07a84ade Update esp32-camera driver 2019-04-13 22:52:21 +02:00
ea043cdb14 Fix WiFi Multi not clearing password 2019-04-13 17:19:06 +02:00
c60092951f Add missing definitions 2019-04-13 17:18:25 +02:00
fa74767b2e Allow selecting in IDF the running core for Arduino's core tasks 2019-04-13 17:13:13 +02:00
d922557e01 Set default Serial1 pins for Adafruit Feather 32 2019-04-13 13:28:16 +02:00
33d4186b35 Add board "SparkFun LoRa Gateway 1-Channel". (#2664)
* Add board "SparkFun LoRa Gateway 1-Channel".

* Extend boards.txt.

Source: https://learn.sparkfun.com/tutorials/sparkfun-lora-gateway-1-channel-hookup-guide/all
2019-04-13 12:26:35 +02:00
6dab3f6777 Fix LEDC channels above 8 not properly clearing
Fixes: https://github.com/espressif/arduino-esp32/issues/2660
2019-04-12 17:49:44 +02:00
1efcd21ba9 replace with strerror (#2663) 2019-04-12 15:44:16 +02:00
7b5cd47d07 Set ESP-IDF to 3.2 (#2662)
* Set IDF to v3.2

* Remove BLE submodule

* Add BLE lib source

* Update Camera example to support OV3660
2019-04-12 15:43:53 +02:00
14126060a1 Properly allocate string and remove warning (#2652)
* Properly allocate string and remove warning

The former way generates the following warning:
ISO C++ forbids converting a string constant to 'char*'

This change makes a character array the size of the string with null ending. It's clearer and gets rid of the warning.

* Better way

Since this is technically immutable, the type should reflect this too.
2019-04-12 12:46:08 +02:00
25c0b52212 Alternative Improve _uploadReadByte (#2656)
* add opportunity for more than one retry to _uploadReadByte

* an alternative timeout-based method to making _uploadReadByte more resilient

* move timing variables in the correct scope

* implement and use client.getTimeout instead of hard-coded timeout in _uploadReadByte

* add missing return

* some refactoring to address respecting the timeout in a potentially deadlocked connection

* fix spelling in comment

* address review comments; move impl to cpp file for getTimeout, and remove local variable for currentMillis

* remove redundant cast

* need to check for timeout outside the inner while as well

* update WebUpdate example to print something in unexpected callback condition

* update log_e messages per review comments
2019-04-12 12:45:35 +02:00
e0beac88c9 File with more than 32,767 characters (#2566) 2019-04-11 16:54:40 +02:00
a87b2ec690 Fix AsyncUDP receive memory leak (#2607)
If _handler is set, pbuf_free is not called. ~AsyncUDPPacket() calls pbuf_free once but only after calling pbuf_ref in it's constructor. The refcount never reaches zero and the memory allocated for pbuf is never released.
2019-04-11 16:49:35 +02:00
6744565257 Also show how space is allocated for the default partitions (#2649)
Make all the partitions descriptions consistent, they now all show what space allocation you get.
2019-04-11 16:47:15 +02:00
da8b7c1b80 overload Preferences.getBytes similar to nvs so you can get size of t… (#2498)
* overload Preferences.getBytes similar to nvs so you can get size of the array.

* Cleaner implentation, with a separate function to get length.  Added an example
2019-04-10 02:45:38 +02:00
91508030d8 Hide log_v behind conditional define, reduce excessive logging (#2641)
@cyberman54 from #2250 recommended reducing unnecessary logging.
2019-04-10 02:43:21 +02:00
a0c975dfbc Reset retry counter upon successful write (#2638)
Currently  WiFiClient::write is unable to send messages over 25Kb, because of the hard-coded retry limit of 10, that is getting decremented on every successful send. Since we cannot send more than 2*MTU bytes in one go, and have only 10 retries, write() is limited to approximately 25Kb. Technically it is not a bug, as it correctly returns the number of sent bytes and the caller can set up futher retries. But not all libs are aware of this behavior, for example, WebServer is not.
I suggest improving current behavior by resetting retry counter every time we had a successful write, so the limit of 10 retries will apply to Failed writes only, and will not apply to Successful writes. This will allow to write() blobs of arbitrary sizes.
2019-04-10 02:41:29 +02:00
0906bf580f update getLocalTime(). (#2629)
* update getLocalTime().

* change count to millis in getLocalTime

* timeout logic.
2019-04-10 02:39:14 +02:00
53a4bf33b6 Added 2 ffat partition schemes for 4MB modules + improved descriptions. (#2623)
* Added 2 ffat partition schemes for 4MB modules + improved descriptions.

Existing format options were unclear on how much spiffs you were
getting. Also add missing 1MB App/3MB Spiffs split.
This addresses https://github.com/espressif/arduino-esp32/issues/1799

This makes it very clear what each option gives you, and also adds 2 options
to get ffat on 4MB chips..

* Added link to ffat howto.
2019-04-10 02:34:31 +02:00
92220b7643 Added PATCH request. (#2610) 2019-04-09 21:22:47 +02:00
dd649808d1 Add server connect timeout to HTTPClient (#2606) 2019-04-09 21:19:25 +02:00
67ee7c32e7 workaround for FS implementations that do not support fflush() (#2596)
https://github.com/espressif/arduino-esp32/issues/1293
2019-04-09 21:15:21 +02:00
8091c2cac7 Add M5Stick-C to board manager (#2594) 2019-04-09 21:13:15 +02:00
4930853edb Add support for ffat on 4MB ESP32 Dev Module and mhetesp32minikit board. (#2588)
* Update boards.txt

Add menu items for ffat on mhetesp32minikit board.

* Add partition table.

* Added ffat partition for 4MB ESP32 Dev Module.

* Added comment about partitioning schemes.
2019-04-09 21:11:17 +02:00
8e8c5035ea Added rmtDeinit to header. Fixes #2585 (#2587)
* Added rmtDeinit to header. Fixes #2585

* oops.  missing ;
2019-04-09 21:09:40 +02:00
1db72a27c4 Added ESP32-CAM board (#2572) 2019-04-09 21:09:13 +02:00
e28dce7eb7 Get Odroid-Go's PSRAM detected (#2564) 2019-04-09 21:07:53 +02:00
d5f71ce545 Added a parameter for max files in SD (#2563) 2019-04-09 21:07:25 +02:00
5032 changed files with 776640 additions and 284781 deletions

View File

@ -24,7 +24,7 @@ https://github.com/me-no-dev/EspExceptionDecoder
### Hardware: ### Hardware:
Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora? Board: ?ESP32 Dev Module? ?node32? ?ttgo_lora?
Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git? Core Installation version: ?1.0.0? ?1.0.1-rc4? ?1.0.1? ?1.0.1-git? ?1.0.2? ?1.0.3?
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component? IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
Flash Frequency: ?40Mhz? Flash Frequency: ?40Mhz?
PSRAM enabled: ?no? ?yes? PSRAM enabled: ?no? ?yes?

27
.github/scripts/check-cmakelists.sh vendored Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
#
# This script is for Travis. It checks all non-examples source files in libraries/ and cores/ are listed in
# CMakeLists.txt for the cmake-based IDF component
#
# If you see an error running this script, edit CMakeLists.txt and add any new source files into your PR
#
set -e
# pull all submodules
git submodule update --init --recursive
# find all source files in repo
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`
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"
echo "Edit CMakeLists.txt as appropriate to add/remove source files from COMPONENT_SRCS"
exit 1
fi
echo "CMakeLists.txt and repo source files match"
exit 0

36
.github/scripts/install-arduino-core-esp32.sh vendored Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32"
if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
echo "Installing ESP32 Arduino Core ..."
script_init_path="$PWD"
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
cd "$ARDUINO_USR_PATH/hardware/espressif"
echo "Installing Python Serial ..."
pip install pyserial > /dev/null
if [ "$OS_IS_WINDOWS" == "1" ]; then
echo "Installing Python Requests ..."
pip install requests > /dev/null
fi
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
echo "Linking Core..."
ln -s $GITHUB_WORKSPACE esp32
else
echo "Cloning Core Repository..."
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
fi
#echo "Updating Submodules ..."
cd esp32
#git submodule update --init --recursive > /dev/null 2>&1
echo "Installing Platform Tools ..."
cd tools && python get.py
cd $script_init_path
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
echo ""
fi

228
.github/scripts/install-arduino-ide.sh vendored Executable file
View File

@ -0,0 +1,228 @@
#!/bin/bash
#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
OSBITS=`arch`
if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1"
ARCHIVE_FORMAT="tar.xz"
if [[ "$OSBITS" == "i686" ]]; then
OS_NAME="linux32"
elif [[ "$OSBITS" == "x86_64" ]]; then
OS_NAME="linux64"
elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then
OS_NAME="linuxarm"
else
OS_NAME="$OSTYPE-$OSBITS"
echo "Unknown OS '$OS_NAME'"
exit 1
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
export OS_IS_MACOS="1"
ARCHIVE_FORMAT="zip"
OS_NAME="macosx"
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
export OS_IS_WINDOWS="1"
ARCHIVE_FORMAT="zip"
OS_NAME="windows"
else
OS_NAME="$OSTYPE-$OSBITS"
echo "Unknown OS '$OS_NAME'"
exit 1
fi
export OS_NAME
ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
if [ "$OS_IS_MACOS" == "1" ]; then
export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java"
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
elif [ "$OS_IS_WINDOWS" == "1" ]; then
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
else
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
export ARDUINO_USR_PATH="$HOME/Arduino"
fi
# Updated as of Nov 3rd 2020
ARDUINO_IDE_URL="https://github.com/espressif/arduino-esp32/releases/download/1.0.4/arduino-nightly-"
# Currently not working
#ARDUINO_IDE_URL="https://www.arduino.cc/download.php?f=/arduino-nightly-"
if [ ! -d "$ARDUINO_IDE_PATH" ]; then
echo "Installing Arduino IDE on $OS_NAME ..."
echo "Downloading '$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
if [ "$OS_IS_LINUX" == "1" ]; then
wget -O "arduino.$ARCHIVE_FORMAT" "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null
mv arduino-nightly "$ARDUINO_IDE_PATH"
else
curl -o "arduino.$ARCHIVE_FORMAT" -L "$ARDUINO_IDE_URL$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
unzip "arduino.$ARCHIVE_FORMAT" > /dev/null
if [ "$OS_IS_MACOS" == "1" ]; then
mv "Arduino.app" "/Applications/Arduino.app"
else
mv arduino-nightly "$ARDUINO_IDE_PATH"
fi
fi
rm -rf "arduino.$ARCHIVE_FORMAT"
mkdir -p "$ARDUINO_USR_PATH/libraries"
mkdir -p "$ARDUINO_USR_PATH/hardware"
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
echo ""
fi
function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
if [ "$#" -lt 2 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_sketch <fqbn> <path-to-ino> [extra-options]"
return 1
fi
local fqbn="$1"
local sketch="$2"
local xtra_opts="$3"
local win_opts=""
if [ "$OS_IS_WINDOWS" == "1" ]; then
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
fi
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
mkdir -p "$ARDUINO_BUILD_DIR"
mkdir -p "$ARDUINO_CACHE_DIR"
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
-fqbn=$fqbn \
-warnings="all" \
-tools "$ARDUINO_IDE_PATH/tools-builder" \
-tools "$ARDUINO_IDE_PATH/tools" \
-built-in-libraries "$ARDUINO_IDE_PATH/libraries" \
-hardware "$ARDUINO_IDE_PATH/hardware" \
-hardware "$ARDUINO_USR_PATH/hardware" \
-libraries "$ARDUINO_USR_PATH/libraries" \
-build-cache "$ARDUINO_CACHE_DIR" \
-build-path "$ARDUINO_BUILD_DIR" \
$win_opts $xtra_opts "$sketch"
}
function count_sketches() # count_sketches <examples-path> <target-mcu>
{
local examples="$1"
local target="$2"
rm -rf sketches.txt
if [ ! -d "$examples" ]; then
touch sketches.txt
return 0
fi
local sketches=$(find $examples -name *.ino)
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
continue
fi;
if [[ -f "$sketchdir/.skip.$target" ]]; then
continue
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_sketches() # build_sketches <fqbn> <target-mcu> <examples-path> <chunk> <total-chunks> [extra-options]
{
local fqbn=$1
local target="$2"
local examples=$3
local chunk_idex=$4
local chunks_num=$5
local xtra_opts=$6
if [ "$#" -lt 3 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_sketches <fqbn> <target-mcu <examples-path> [<chunk> <total-chunks>] [extra-options]"
return 1
fi
if [ "$#" -lt 5 ]; then
chunk_idex="0"
chunks_num="1"
xtra_opts=$4
fi
if [ "$chunks_num" -le 0 ]; then
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size=$(( $sketchcount / $chunks_num ))
local all_chunks=$(( $chunks_num * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
echo "End Sketch : $end_index"
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|| [ -f "$sketchdir/.skip.$target" ]; then
continue
fi
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
build_sketch "$fqbn" "$sketch" "$xtra_opts"
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
return 0
}

151
.github/scripts/install-platformio-esp32.sh vendored Executable file
View File

@ -0,0 +1,151 @@
#!/bin/bash
export PLATFORMIO_ESP32_PATH="$HOME/.platformio/packages/framework-arduinoespressif32"
PLATFORMIO_ESP32_URL="https://github.com/platformio/platform-espressif32.git#feature/idf-v4.0"
echo "Installing Python Wheel ..."
pip install wheel > /dev/null 2>&1
echo "Installing PlatformIO ..."
pip install -U https://github.com/platformio/platformio/archive/develop.zip > /dev/null 2>&1
echo "Installing Platform ESP32 ..."
python -m platformio platform install $PLATFORMIO_ESP32_URL > /dev/null 2>&1
echo "Replacing the framework version ..."
python -c "import json; import os; fp=open(os.path.expanduser('~/.platformio/platforms/espressif32/platform.json'), 'r+'); data=json.load(fp); data['packages']['framework-arduinoespressif32']['version'] = '*'; del data['packages']['framework-arduinoespressif32']['owner']; fp.seek(0); fp.truncate(); json.dump(data, fp); fp.close()"
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
echo "Linking Core..."
ln -s $GITHUB_WORKSPACE "$PLATFORMIO_ESP32_PATH"
else
echo "Cloning Core Repository ..."
git clone --recursive https://github.com/espressif/arduino-esp32.git "$PLATFORMIO_ESP32_PATH" > /dev/null 2>&1
fi
echo "PlatformIO for ESP32 has been installed"
echo ""
function build_pio_sketch(){ # build_pio_sketch <board> <options> <path-to-ino>
if [ "$#" -lt 3 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketch <board> <options> <path-to-ino>"
return 1
fi
local board="$1"
local options="$2"
local sketch="$3"
local sketch_dir=$(dirname "$sketch")
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
python -m platformio ci --board "$board" "$sketch_dir" --project-option="$options"
}
function count_sketches() # count_sketches <examples-path>
{
local examples="$1"
rm -rf sketches.txt
if [ ! -d "$examples" ]; then
touch sketches.txt
return 0
fi
local sketches=$(find $examples -name *.ino)
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
continue
fi;
if [[ -f "$sketchdir/.test.skip" ]]; then
continue
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_pio_sketches() # build_pio_sketches <board> <options> <examples-path> <chunk> <total-chunks>
{
if [ "$#" -lt 3 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketches <board> <options> <examples-path> [<chunk> <total-chunks>]"
return 1
fi
local board=$1
local options="$2"
local examples=$3
local chunk_idex=$4
local chunks_num=$5
if [ "$#" -lt 5 ]; then
chunk_idex="0"
chunks_num="1"
fi
if [ "$chunks_num" -le 0 ]; then
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size=$(( $sketchcount / $chunks_num ))
local all_chunks=$(( $chunks_num * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
echo "End Sketch : $end_index"
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|| [ -f "$sketchdir/.test.skip" ]; then
continue
fi
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
build_pio_sketch "$board" "$options" "$sketch"
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
return 0
}

6
package/merge_packages.py → .github/scripts/merge_packages.py vendored Normal file → Executable file
View File

@ -36,7 +36,11 @@ def pkgVersionNormalized(versionString):
verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE) verParts = re.split('\.|-rc', verStr, flags=re.IGNORECASE)
if len(verParts) == 3: if len(verParts) == 3:
verStr = str(versionString) + '-rc' + str(sys.maxint) if (sys.version_info > (3, 0)): # Python 3
verStr = str(versionString) + '-rc' + str(sys.maxsize)
else: # Python 2
verStr = str(versionString) + '-rc' + str(sys.maxint)
elif len(verParts) != 4: elif len(verParts) != 4:
print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr) print("pkgVersionNormalized WARNING: unexpected version format: {0})".format(verStr), file=sys.stderr)

131
.github/scripts/on-pages.sh vendored Normal file
View File

@ -0,0 +1,131 @@
#/bin/bash
set -e
function get_file_size(){
local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
eval `stat -s "$file"`
local res="$?"
echo "$st_size"
return $res
else
stat --printf="%s" "$file"
return $?
fi
}
#git_remove_from_pages <file>
function git_remove_from_pages(){
local path=$1
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type=`echo "$info" | jq -r '.type'`
if [ ! $type == "file" ]; then
if [ ! $type == "null" ]; then
echo "Wrong type '$type'"
else
echo "File is not on Pages"
fi
return 0
fi
local sha=`echo "$info" | jq -r '.sha'`
local message="Deleting "$(basename $path)
local json="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"sha\":\"$sha\"}"
echo "$json" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X DELETE --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
}
function git_upload_to_pages(){
local path=$1
local src=$2
if [ ! -f "$src" ]; then
>&2 echo "Input is not a file! Aborting..."
return 1
fi
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type=`echo "$info" | jq -r '.type'`
local message=$(basename $path)
local sha=""
local content=""
if [ $type == "file" ]; then
sha=`echo "$info" | jq -r '.sha'`
sha=",\"sha\":\"$sha\""
message="Updating $message"
elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'"
return 1
else
message="Creating $message"
fi
content=`base64 -i "$src"`
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
}
function git_safe_upload_to_pages(){
local path=$1
local file="$2"
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=`echo "$upload_res" | jq -r '.content.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
return 1
fi
echo "$upload_res" | jq -r '.content.download_url'
return $?
}
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
pages_added=`echo "$EVENT_JSON" | jq -r '.commits[].added[]'`
pages_modified=`echo "$EVENT_JSON" | jq -r '.commits[].modified[]'`
pages_removed=`echo "$EVENT_JSON" | jq -r '.commits[].removed[]'`
for page in $pages_added; do
if [[ $page != "README.md" && $page != "docs/"* ]]; then
continue
fi
echo "Adding '$page' to pages ..."
if [[ $page == "README.md" ]]; then
git_safe_upload_to_pages "index.md" "README.md"
else
git_safe_upload_to_pages "$page" "$page"
fi
done
for page in $pages_modified; do
if [[ $page != "README.md" && $page != "docs/"* ]]; then
continue
fi
echo "Modifying '$page' ..."
if [[ $page == "README.md" ]]; then
git_safe_upload_to_pages "index.md" "README.md"
else
git_safe_upload_to_pages "$page" "$page"
fi
done
for page in $pages_removed; do
if [[ $page != "README.md" && $page != "docs/"* ]]; then
continue
fi
echo "Removing '$page' from pages ..."
if [[ $page == "README.md" ]]; then
git_remove_from_pages "README.md" > /dev/null
else
git_remove_from_pages "$page" > /dev/null
fi
done
echo
echo "DONE!"

91
.github/scripts/on-push.sh vendored Executable file
View File

@ -0,0 +1,91 @@
#!/bin/bash
set -e
if [ ! -z "$TRAVIS_TAG" ]; then
echo "Skipping Test: Tagged build"
exit 0
fi
if [ ! -z "$GITHUB_WORKSPACE" ]; then
export TRAVIS_BUILD_DIR="$GITHUB_WORKSPACE"
export TRAVIS_REPO_SLUG="$GITHUB_REPOSITORY"
elif [ ! -z "$TRAVIS_BUILD_DIR" ]; then
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
else
export GITHUB_WORKSPACE="$PWD"
export GITHUB_REPOSITORY="espressif/arduino-esp32"
fi
CHUNK_INDEX=$1
CHUNKS_CNT=$2
BUILD_PIO=0
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
CHUNK_INDEX=0
CHUNKS_CNT=1
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
CHUNK_INDEX=$CHUNKS_CNT
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
fi
#echo "Updating submodules ..."
#git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
if [ "$BUILD_PIO" -eq 0 ]; then
# ArduinoIDE ESP32 Test
TARGET="esp32"
FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
source ./.github/scripts/install-arduino-ide.sh
source ./.github/scripts/install-arduino-core-esp32.sh
if [ "$OS_IS_WINDOWS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
elif [ "$OS_IS_MACOS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
else
# CMake Test
if [ "$CHUNK_INDEX" -eq 0 ]; then
bash "$ARDUINO_ESP32_PATH/.github/scripts/check-cmakelists.sh"
fi
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
fi
# ArduinoIDE ESP32S2 Test
TARGET="esp32s2"
FQBN="espressif:esp32:esp32s2:PSRAM=enabled,PartitionScheme=huge_app"
if [ "$OS_IS_WINDOWS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
elif [ "$OS_IS_MACOS" == "1" ]; then
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_sketch "$FQBN" "$ARDUINO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
else
build_sketches "$FQBN" "$TARGET" "$ARDUINO_ESP32_PATH/libraries" "$CHUNK_INDEX" "$CHUNKS_CNT"
fi
else
source ./.github/scripts/install-platformio-esp32.sh
# PlatformIO ESP32 Test
BOARD="esp32dev"
OPTIONS="board_build.partitions = huge_app.csv"
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/BLE/examples/BLE_server/BLE_server.ino" && \
build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino"
# PlatformIO ESP32 Test
# OPTIONS="board_build.mcu = esp32s2"
# build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient/WiFiClient.ino" && \
# build_pio_sketch "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino"
python -m platformio ci --board "$BOARD" "$PLATFORMIO_ESP32_PATH/libraries/WiFi/examples/WiFiClient" --project-option="board_build.mcu = esp32s2" --project-option="board_build.partitions = huge_app.csv"
#build_pio_sketches "$BOARD" "$OPTIONS" "$PLATFORMIO_ESP32_PATH/libraries"
fi

380
.github/scripts/on-release.sh vendored Executable file
View File

@ -0,0 +1,380 @@
#!/bin/bash
if [ ! $GITHUB_EVENT_NAME == "release" ]; then
echo "Wrong event '$GITHUB_EVENT_NAME'!"
exit 1
fi
EVENT_JSON=`cat $GITHUB_EVENT_PATH`
action=`echo $EVENT_JSON | jq -r '.action'`
if [ ! $action == "published" ]; then
echo "Wrong action '$action'. Exiting now..."
exit 0
fi
draft=`echo $EVENT_JSON | jq -r '.release.draft'`
if [ $draft == "true" ]; then
echo "It's a draft release. Exiting now..."
exit 0
fi
RELEASE_PRE=`echo $EVENT_JSON | jq -r '.release.prerelease'`
RELEASE_TAG=`echo $EVENT_JSON | jq -r '.release.tag_name'`
RELEASE_BRANCH=`echo $EVENT_JSON | jq -r '.release.target_commitish'`
RELEASE_ID=`echo $EVENT_JSON | jq -r '.release.id'`
RELEASE_BODY=`echo $EVENT_JSON | jq -r '.release.body'`
OUTPUT_DIR="$GITHUB_WORKSPACE/build"
PACKAGE_NAME="esp32-$RELEASE_TAG"
PACKAGE_JSON_MERGE="$GITHUB_WORKSPACE/.github/scripts/merge_packages.py"
PACKAGE_JSON_TEMPLATE="$GITHUB_WORKSPACE/package/package_esp32_index.template.json"
PACKAGE_JSON_DEV="package_esp32_dev_index.json"
PACKAGE_JSON_REL="package_esp32_index.json"
echo "Event: $GITHUB_EVENT_NAME, Repo: $GITHUB_REPOSITORY, Path: $GITHUB_WORKSPACE, Ref: $GITHUB_REF"
echo "Action: $action, Branch: $RELEASE_BRANCH, ID: $RELEASE_ID"
echo "Tag: $RELEASE_TAG, Draft: $draft, Pre-Release: $RELEASE_PRE"
function get_file_size(){
local file="$1"
if [[ "$OSTYPE" == "darwin"* ]]; then
eval `stat -s "$file"`
local res="$?"
echo "$st_size"
return $res
else
stat --printf="%s" "$file"
return $?
fi
}
function git_upload_asset(){
local name=$(basename "$1")
# local mime=$(file -b --mime-type "$1")
curl -k -X POST -sH "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" --data-binary @"$1" "https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$name"
}
function git_safe_upload_asset(){
local file="$1"
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_asset "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=`echo "$upload_res" | jq -r '.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
return 1
fi
echo "$upload_res" | jq -r '.browser_download_url'
return $?
}
function git_upload_to_pages(){
local path=$1
local src=$2
if [ ! -f "$src" ]; then
>&2 echo "Input is not a file! Aborting..."
return 1
fi
local info=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.object+json" -X GET "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path?ref=gh-pages"`
local type=`echo "$info" | jq -r '.type'`
local message=$(basename $path)
local sha=""
local content=""
if [ $type == "file" ]; then
sha=`echo "$info" | jq -r '.sha'`
sha=",\"sha\":\"$sha\""
message="Updating $message"
elif [ ! $type == "null" ]; then
>&2 echo "Wrong type '$type'"
return 1
else
message="Creating $message"
fi
content=`base64 -i "$src"`
data="{\"branch\":\"gh-pages\",\"message\":\"$message\",\"content\":\"$content\"$sha}"
echo "$data" | curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" -X PUT --data @- "https://api.github.com/repos/$GITHUB_REPOSITORY/contents/$path"
}
function git_safe_upload_to_pages(){
local path=$1
local file="$2"
local name=$(basename "$file")
local size=`get_file_size "$file"`
local upload_res=`git_upload_to_pages "$path" "$file"`
if [ $? -ne 0 ]; then
>&2 echo "ERROR: Failed to upload '$name' ($?)"
return 1
fi
up_size=`echo "$upload_res" | jq -r '.content.size'`
if [ $up_size -ne $size ]; then
>&2 echo "ERROR: Uploaded size does not match! $up_size != $size"
#git_delete_asset
return 1
fi
echo "$upload_res" | jq -r '.content.download_url'
return $?
}
function merge_package_json(){
local jsonLink=$1
local jsonOut=$2
local old_json=$OUTPUT_DIR/oldJson.json
local merged_json=$OUTPUT_DIR/mergedJson.json
echo "Downloading previous JSON $jsonLink ..."
curl -L -o "$old_json" "https://github.com/$GITHUB_REPOSITORY/releases/download/$jsonLink?access_token=$GITHUB_TOKEN" 2>/dev/null
if [ $? -ne 0 ]; then echo "ERROR: Download Failed! $?"; exit 1; fi
echo "Creating new JSON ..."
set +e
stdbuf -oL python "$PACKAGE_JSON_MERGE" "$jsonOut" "$old_json" > "$merged_json"
set -e
set -v
if [ ! -s $merged_json ]; then
rm -f "$merged_json"
echo "Nothing to merge"
else
rm -f "$jsonOut"
mv "$merged_json" "$jsonOut"
echo "JSON data successfully merged"
fi
rm -f "$old_json"
set +v
}
set -e
##
## PACKAGE ZIP
##
mkdir -p "$OUTPUT_DIR"
PKG_DIR="$OUTPUT_DIR/$PACKAGE_NAME"
PACKAGE_ZIP="$PACKAGE_NAME.zip"
echo "Updating submodules ..."
git -C "$GITHUB_WORKSPACE" submodule update --init --recursive > /dev/null 2>&1
mkdir -p "$PKG_DIR/tools"
# Copy all core files to the package folder
echo "Copying files for packaging ..."
cp -f "$GITHUB_WORKSPACE/boards.txt" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/programmers.txt" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/cores" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/libraries" "$PKG_DIR/"
cp -Rf "$GITHUB_WORKSPACE/variants" "$PKG_DIR/"
cp -f "$GITHUB_WORKSPACE/tools/espota.exe" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/espota.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/esptool.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.py" "$PKG_DIR/tools/"
cp -f "$GITHUB_WORKSPACE/tools/gen_esp32part.exe" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/partitions" "$PKG_DIR/tools/"
cp -Rf "$GITHUB_WORKSPACE/tools/sdk" "$PKG_DIR/tools/"
# Remove unnecessary files in the package folder
echo "Cleaning up folders ..."
find "$PKG_DIR" -name '*.DS_Store' -exec rm -f {} \;
find "$PKG_DIR" -name '*.git*' -type f -delete
# Replace tools locations in platform.txt
echo "Generating platform.txt..."
cat "$GITHUB_WORKSPACE/platform.txt" | \
sed "s/version=.*/version=$ver$extent/g" | \
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
> "$PKG_DIR/platform.txt"
# Add header with version information
echo "Generating core_version.h ..."
ver_define=`echo $RELEASE_TAG | tr "[:lower:].\055" "[:upper:]_"`
ver_hex=`git -C "$GITHUB_WORKSPACE" rev-parse --short=8 HEAD 2>/dev/null`
echo \#define ARDUINO_ESP32_GIT_VER 0x$ver_hex > "$PKG_DIR/cores/esp32/core_version.h"
echo \#define ARDUINO_ESP32_GIT_DESC `git -C "$GITHUB_WORKSPACE" describe --tags 2>/dev/null` >> "$PKG_DIR/cores/esp32/core_version.h"
echo \#define ARDUINO_ESP32_RELEASE_$ver_define >> "$PKG_DIR/cores/esp32/core_version.h"
echo \#define ARDUINO_ESP32_RELEASE \"$ver_define\" >> "$PKG_DIR/cores/esp32/core_version.h"
# Compress package folder
echo "Creating ZIP ..."
pushd "$OUTPUT_DIR" >/dev/null
zip -qr "$PACKAGE_ZIP" "$PACKAGE_NAME"
if [ $? -ne 0 ]; then echo "ERROR: Failed to create $PACKAGE_ZIP ($?)"; exit 1; fi
# Calculate SHA-256
echo "Calculating SHA sum ..."
PACKAGE_PATH="$OUTPUT_DIR/$PACKAGE_ZIP"
PACKAGE_SHA=`shasum -a 256 "$PACKAGE_ZIP" | cut -f 1 -d ' '`
PACKAGE_SIZE=`get_file_size "$PACKAGE_ZIP"`
popd >/dev/null
rm -rf "$PKG_DIR"
echo "'$PACKAGE_ZIP' Created! Size: $PACKAGE_SIZE, SHA-256: $PACKAGE_SHA"
echo
# Upload package to release page
echo "Uploading package to release page ..."
PACKAGE_URL=`git_safe_upload_asset "$PACKAGE_PATH"`
echo "Package Uploaded"
echo "Download URL: $PACKAGE_URL"
echo
##
## PACKAGE JSON
##
# Construct JQ argument with package data
jq_arg=".packages[0].platforms[0].version = \"$RELEASE_TAG\" | \
.packages[0].platforms[0].url = \"$PACKAGE_URL\" |\
.packages[0].platforms[0].archiveFileName = \"$PACKAGE_ZIP\" |\
.packages[0].platforms[0].size = \"$PACKAGE_SIZE\" |\
.packages[0].platforms[0].checksum = \"SHA-256:$PACKAGE_SHA\""
# Generate package JSONs
echo "Genarating $PACKAGE_JSON_DEV ..."
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
if [ "$RELEASE_PRE" == "false" ]; then
echo "Genarating $PACKAGE_JSON_REL ..."
cat "$PACKAGE_JSON_TEMPLATE" | jq "$jq_arg" > "$OUTPUT_DIR/$PACKAGE_JSON_REL"
fi
# Figure out the last release or pre-release
echo "Getting previous releases ..."
releasesJson=`curl -sH "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases" 2>/dev/null`
if [ $? -ne 0 ]; then echo "ERROR: Get Releases Failed! ($?)"; exit 1; fi
set +e
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[0].tag_name')
shopt -s nocasematch
if [ "$prev_any_release" == "$RELEASE_TAG" ]; then
prev_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false and .prerelease == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
prev_any_release=$(echo "$releasesJson" | jq -e -r '. | map(select(.draft == false)) | sort_by(.created_at | - fromdateiso8601) | .[1].tag_name')
fi
COMMITS_SINCE_RELEASE="$prev_any_release"
shopt -u nocasematch
set -e
# Merge package JSONs with previous releases
if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
echo "Merging with JSON from $prev_any_release ..."
merge_package_json "$prev_any_release/$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"
fi
if [ "$RELEASE_PRE" == "false" ]; then
COMMITS_SINCE_RELEASE="$prev_release"
if [ ! -z "$prev_release" ] && [ "$prev_release" != "null" ]; then
echo "Merging with JSON from $prev_release ..."
merge_package_json "$prev_release/$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"
fi
fi
echo "Previous Release: $prev_release"
echo "Previous (any)release: $prev_any_release"
echo
# Upload package JSONs
echo "Uploading $PACKAGE_JSON_DEV ..."
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_DEV" "$OUTPUT_DIR/$PACKAGE_JSON_DEV"`
echo
if [ "$RELEASE_PRE" == "false" ]; then
echo "Uploading $PACKAGE_JSON_REL ..."
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
echo "Pages URL: "`git_safe_upload_to_pages "$PACKAGE_JSON_REL" "$OUTPUT_DIR/$PACKAGE_JSON_REL"`
echo
fi
##
## RELEASE NOTES
##
# Create release notes
echo "Preparing release notes ..."
releaseNotes=""
# Process annotated tags
relNotesRaw=`git -C "$GITHUB_WORKSPACE" show -s --format=%b $RELEASE_TAG`
readarray -t msgArray <<<"$relNotesRaw"
arrLen=${#msgArray[@]}
if [ $arrLen > 3 ] && [ "${msgArray[0]:0:3}" == "tag" ]; then
ind=3
while [ $ind -lt $arrLen ]; do
if [ $ind -eq 3 ]; then
releaseNotes="#### ${msgArray[ind]}"
releaseNotes+=$'\r\n'
else
oneLine="$(echo -e "${msgArray[ind]}" | sed -e 's/^[[:space:]]*//')"
if [ ${#oneLine} -gt 0 ]; then
if [ "${oneLine:0:2}" == "* " ]; then oneLine=$(echo ${oneLine/\*/-}); fi
if [ "${oneLine:0:2}" != "- " ]; then releaseNotes+="- "; fi
releaseNotes+="$oneLine"
releaseNotes+=$'\r\n'
fi
fi
let ind=$ind+1
done
fi
# Append Commit Messages
if [ ! -z "$COMMITS_SINCE_RELEASE" ] && [ "$COMMITS_SINCE_RELEASE" != "null" ]; then
echo "Getting commits since $COMMITS_SINCE_RELEASE ..."
commitFile=$OUTPUT_DIR/commits.txt
git -C "$GITHUB_WORKSPACE" log --oneline $COMMITS_SINCE_RELEASE.. > "$OUTPUT_DIR/commits.txt"
releaseNotes+=$'\r\n##### Commits\r\n'
IFS=$'\n'
for next in `cat $commitFile`
do
IFS=' ' read -r commitId commitMsg <<< "$next"
commitLine="- [$commitId](https://github.com/$GITHUB_REPOSITORY/commit/$commitId) $commitMsg"
releaseNotes+="$commitLine"
releaseNotes+=$'\r\n'
done
rm -f $commitFile
fi
# Prepend the original release body
if [ "${RELEASE_BODY: -1}" == $'\r' ]; then
RELEASE_BODY="${RELEASE_BODY:0:-1}"
else
RELEASE_BODY="$RELEASE_BODY"
fi
RELEASE_BODY+=$'\r\n'
releaseNotes="$RELEASE_BODY$releaseNotes"
# Update release page
echo "Updating release notes ..."
releaseNotes=$(printf '%s' "$releaseNotes" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
releaseNotes=${releaseNotes:1:-1}
curlData="{\"body\": \"$releaseNotes\"}"
releaseData=`curl --data "$curlData" "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID?access_token=$GITHUB_TOKEN" 2>/dev/null`
if [ $? -ne 0 ]; then echo "ERROR: Updating Release Failed: $?"; exit 1; fi
echo "Release notes successfully updated"
echo
##
## SUBMODULE VERSIONS
##
# Upload submodules versions
echo "Generating submodules.txt ..."
git -C "$GITHUB_WORKSPACE" submodule status > "$OUTPUT_DIR/submodules.txt"
echo "Uploading submodules.txt ..."
echo "Download URL: "`git_safe_upload_asset "$OUTPUT_DIR/submodules.txt"`
echo ""
set +e
##
## DONE
##
echo "DONE!"

64
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,64 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 60
# 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
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- pinned
- security
- "to be implemented"
- "for reference"
- "move to PR"
- "enhancement"
# 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: 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

21
.github/workflows/gh-pages.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: GitHub Pages CI
on:
push:
branches:
- master
paths:
- 'README.md'
- 'docs/**'
jobs:
build-pages:
name: Build GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Copy Files
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash ./.github/scripts/on-pages.sh

58
.github/workflows/push.yml vendored Normal file
View File

@ -0,0 +1,58 @@
name: ESP32 Arduino CI
on:
push:
branches:
- master
- release/*
pull_request:
jobs:
# Ubuntu
build-arduino-linux:
name: Arduino ${{ matrix.chunk }} on ubuntu-latest
runs-on: ubuntu-latest
strategy:
matrix:
chunk: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Build Sketches
run: bash ./.github/scripts/on-push.sh ${{ matrix.chunk }} 15
# Windows and MacOS
build-arduino-win-mac:
name: Arduino on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Build Sketches
run: bash ./.github/scripts/on-push.sh
# PlatformIO on Windows, Ubuntu and Mac
build-platformio:
name: PlatformIO on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Build Sketches
run: bash ./.github/scripts/on-push.sh 1 1 #equal and non-zero to trigger PIO

20
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: ESP32 Arduino Release
on:
release:
types: published
jobs:
build:
name: Publish Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Build Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash ./.github/scripts/on-release.sh

11
.gitignore vendored
View File

@ -1,7 +1,18 @@
tools/xtensa-esp32-elf tools/xtensa-esp32-elf
tools/xtensa-esp32s2-elf
tools/dist tools/dist
tools/esptool tools/esptool
tools/esptool.exe tools/esptool.exe
tools/mkspiffs/mkspiffs tools/mkspiffs/mkspiffs
tools/mkspiffs/mkspiffs.exe tools/mkspiffs/mkspiffs.exe
.DS_Store .DS_Store
#Ignore files built by Visual Studio/Visual Micro
[Dd]ebug*/
[Rr]elease*/
.vs/
__vm/
*.vcxproj*
.vscode/
platform.sloeber.txt
boards.sloeber.txt

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "libraries/BLE"]
path = libraries/BLE
url = https://github.com/nkolban/ESP32_BLE_Arduino.git
[submodule "libraries/AzureIoT"]
path = libraries/AzureIoT
url = https://github.com/VSChina/ESP32_AzureIoT_Arduino

View File

@ -1,8 +1,6 @@
sudo: false sudo: false
language: python language: python
python:
- "2.7"
os: os:
- linux - linux
@ -10,22 +8,40 @@ os:
git: git:
depth: false depth: false
env: before_install:
global: - git submodule update --init --recursive
- secure: "l/4Dt+KQ/mACtGAHDUsPr66fUte840PZoQ4xpPikqWZI0uARu4l+Ym7+sHinnT6fBqrj8AJeBYGz4nFa8NK4LutZn9mSD40w+sxl0wSV4oHV8rzKe3Cd8+sMG3+o33yWoikMNjSvqa73Q0rm+SgrlInNdZbuAyixL+a2alaWSnGPm4F2xwUGj+S33TOy5P/Xp77CYtCV5S8vzyk/eEdNhoF0GYePJVdfuzCOUjXMyT5OWxORkzzQ7Hnn/Ka/RDfV8Si4HgujLQBrK5q6iPnNBFqBSqilYBepSMn4opnOBpIm0SCgePz7XQEFC83buA7GUcnCnfg38bf+dCwHaODf1d1PmqVRYt2QmfinexXtM4afAtL0iBUDtvrfnXHzwW9w82VeZhpbJSVh9DUQvB0IlsZeCz9J9PUBAi3N+SMX+9l+BomYwRUlPuKY+Ef2JKk9q6mxtUkky5R0daAlVxEhpVdQks1rT+T+NMoDMemxQ3SKEiqAHh6EgHecruszffmZ71uLX9MpERpew0qN+UFiafws+jkTjx+3yF9yut0Hf9sMbeAYzzkGzRqJTUEBJ6B29Cql8M0yRXCNN/8wuuTHhG8esstozga4ZQoIVrq7mEAgup376PTcNfr1+imbbWVQ7lJdYIuDe6OS5V3OX6np11vgK/DbhfyzvQv9Z1zAGnM="
- REMOTE_URL=https://github.com/$TRAVIS_REPO_SLUG/releases/download/$TRAVIS_TAG
script:
- bash $TRAVIS_BUILD_DIR/tools/build.sh
deploy: stages:
provider: script - build
skip_cleanup: true - deploy
script: bash $TRAVIS_BUILD_DIR/tools/deploy.sh -t$TRAVIS_TAG -a$ESP32_GITHUB_TOKEN -s$TRAVIS_REPO_SLUG -drelease
on: jobs:
tags: true include:
- name: "Build Arduino 0"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 0 10
- name: "Build Arduino 1"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 10
- name: "Build Arduino 2"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 2 10
- name: "Build Arduino 3"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 3 10
- name: "Build PlatformIO"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1
notifications: notifications:
email: email:

View File

@ -15,6 +15,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-spi.c cores/esp32/esp32-hal-spi.c
cores/esp32/esp32-hal-time.c cores/esp32/esp32-hal-time.c
cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-timer.c
cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-uart.c
cores/esp32/esp32-hal-rmt.c cores/esp32/esp32-hal-rmt.c
@ -31,6 +32,8 @@ set(CORE_SRCS
cores/esp32/stdlib_noniso.c cores/esp32/stdlib_noniso.c
cores/esp32/Stream.cpp cores/esp32/Stream.cpp
cores/esp32/StreamString.cpp cores/esp32/StreamString.cpp
cores/esp32/USB.cpp
cores/esp32/USBCDC.cpp
cores/esp32/wiring_pulse.c cores/esp32/wiring_pulse.c
cores/esp32/wiring_shift.c cores/esp32/wiring_shift.c
cores/esp32/WMath.cpp cores/esp32/WMath.cpp
@ -49,6 +52,7 @@ set(LIBRARY_SRCS
libraries/FS/src/vfs_api.cpp libraries/FS/src/vfs_api.cpp
libraries/HTTPClient/src/HTTPClient.cpp libraries/HTTPClient/src/HTTPClient.cpp
libraries/HTTPUpdate/src/HTTPUpdate.cpp libraries/HTTPUpdate/src/HTTPUpdate.cpp
libraries/LITTLEFS/src/LITTLEFS.cpp
libraries/NetBIOS/src/NetBIOS.cpp libraries/NetBIOS/src/NetBIOS.cpp
libraries/Preferences/src/Preferences.cpp libraries/Preferences/src/Preferences.cpp
libraries/SD_MMC/src/SD_MMC.cpp libraries/SD_MMC/src/SD_MMC.cpp
@ -71,6 +75,7 @@ set(LIBRARY_SRCS
libraries/WiFi/src/WiFi.cpp libraries/WiFi/src/WiFi.cpp
libraries/WiFi/src/WiFiGeneric.cpp libraries/WiFi/src/WiFiGeneric.cpp
libraries/WiFi/src/WiFiMulti.cpp libraries/WiFi/src/WiFiMulti.cpp
libraries/WiFi/src/WiFiProv.cpp
libraries/WiFi/src/WiFiScan.cpp libraries/WiFi/src/WiFiScan.cpp
libraries/WiFi/src/WiFiServer.cpp libraries/WiFi/src/WiFiServer.cpp
libraries/WiFi/src/WiFiSTA.cpp libraries/WiFi/src/WiFiSTA.cpp
@ -78,66 +83,6 @@ set(LIBRARY_SRCS
libraries/Wire/src/Wire.cpp libraries/Wire/src/Wire.cpp
) )
set(AZURE_SRCS
libraries/AzureIoT/src/az_iot/azureiotcerts.c
libraries/AzureIoT/src/az_iot/c-utility/pal/agenttime.c
libraries/AzureIoT/src/az_iot/c-utility/pal/dns_async.c
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/lock.c
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/threadapi.c
libraries/AzureIoT/src/az_iot/c-utility/pal/freertos/tickcounter.c
libraries/AzureIoT/src/az_iot/c-utility/pal/lwip/sntp_lwip.c
libraries/AzureIoT/src/az_iot/c-utility/pal/socket_async.c
libraries/AzureIoT/src/az_iot/c-utility/pal/src/platform_openssl_compact.c
libraries/AzureIoT/src/az_iot/c-utility/pal/src/tlsio_openssl_compact.c
libraries/AzureIoT/src/az_iot/c-utility/pal/tlsio_options.c
libraries/AzureIoT/src/az_iot/c-utility/src/base64.c
libraries/AzureIoT/src/az_iot/c-utility/src/buffer.c
libraries/AzureIoT/src/az_iot/c-utility/src/connection_string_parser.c
libraries/AzureIoT/src/az_iot/c-utility/src/consolelogger.c
libraries/AzureIoT/src/az_iot/c-utility/src/constbuffer.c
libraries/AzureIoT/src/az_iot/c-utility/src/constmap.c
libraries/AzureIoT/src/az_iot/c-utility/src/crt_abstractions.c
libraries/AzureIoT/src/az_iot/c-utility/src/doublylinkedlist.c
libraries/AzureIoT/src/az_iot/c-utility/src/gballoc.c
libraries/AzureIoT/src/az_iot/c-utility/src/gb_stdio.c
libraries/AzureIoT/src/az_iot/c-utility/src/gb_time.c
libraries/AzureIoT/src/az_iot/c-utility/src/hmac.c
libraries/AzureIoT/src/az_iot/c-utility/src/hmacsha256.c
libraries/AzureIoT/src/az_iot/c-utility/src/httpapiex.c
libraries/AzureIoT/src/az_iot/c-utility/src/httpapiexsas.c
libraries/AzureIoT/src/az_iot/c-utility/src/httpheaders.c
libraries/AzureIoT/src/az_iot/c-utility/src/http_proxy_io.c
libraries/AzureIoT/src/az_iot/c-utility/src/map.c
libraries/AzureIoT/src/az_iot/c-utility/src/optionhandler.c
libraries/AzureIoT/src/az_iot/c-utility/src/sastoken.c
libraries/AzureIoT/src/az_iot/c-utility/src/sha1.c
libraries/AzureIoT/src/az_iot/c-utility/src/sha224.c
libraries/AzureIoT/src/az_iot/c-utility/src/sha384-512.c
libraries/AzureIoT/src/az_iot/c-utility/src/singlylinkedlist.c
libraries/AzureIoT/src/az_iot/c-utility/src/strings.c
libraries/AzureIoT/src/az_iot/c-utility/src/string_tokenizer.c
libraries/AzureIoT/src/az_iot/c-utility/src/urlencode.c
libraries/AzureIoT/src/az_iot/c-utility/src/usha.c
libraries/AzureIoT/src/az_iot/c-utility/src/vector.c
libraries/AzureIoT/src/az_iot/c-utility/src/xio.c
libraries/AzureIoT/src/az_iot/c-utility/src/xlogging.c
libraries/AzureIoT/src/az_iot/iothub_client/src/blob.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_authorization.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_ll.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_client_retry_control.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothub_message.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransport.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransportmqtt.c
libraries/AzureIoT/src/az_iot/iothub_client/src/iothubtransport_mqtt_common.c
libraries/AzureIoT/src/az_iot/iothub_client/src/version.c
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_client.c
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_codec.c
libraries/AzureIoT/src/az_iot/umqtt/src/mqtt_message.c
libraries/AzureIoT/src/AzureIotHub.cpp
libraries/AzureIoT/src/Esp32MQTTClient.cpp
)
set(BLE_SRCS set(BLE_SRCS
libraries/BLE/src/BLE2902.cpp libraries/BLE/src/BLE2902.cpp
libraries/BLE/src/BLE2904.cpp libraries/BLE/src/BLE2904.cpp
@ -170,14 +115,12 @@ set(BLE_SRCS
libraries/BLE/src/GeneralUtils.cpp libraries/BLE/src/GeneralUtils.cpp
) )
set(COMPONENT_SRCS ${CORE_SRCS} ${LIBRARY_SRCS} ${AZURE_SRCS} ${BLE_SRCS})
set(COMPONENT_ADD_INCLUDEDIRS set(includedirs
variants/esp32/ variants/esp32/
cores/esp32/ cores/esp32/
libraries/ArduinoOTA/src libraries/ArduinoOTA/src
libraries/AsyncUDP/src libraries/AsyncUDP/src
libraries/AzureIoT/src
libraries/BLE/src libraries/BLE/src
libraries/BluetoothSerial/src libraries/BluetoothSerial/src
libraries/DNSServer/src libraries/DNSServer/src
@ -188,6 +131,7 @@ set(COMPONENT_ADD_INCLUDEDIRS
libraries/FS/src libraries/FS/src
libraries/HTTPClient/src libraries/HTTPClient/src
libraries/HTTPUpdate/src libraries/HTTPUpdate/src
libraries/LITTLEFS/src
libraries/NetBIOS/src libraries/NetBIOS/src
libraries/Preferences/src libraries/Preferences/src
libraries/SD_MMC/src libraries/SD_MMC/src
@ -203,9 +147,16 @@ set(COMPONENT_ADD_INCLUDEDIRS
libraries/Wire/src libraries/Wire/src
) )
set(COMPONENT_PRIV_INCLUDEDIRS cores/esp32/libb64) set(srcs ${CORE_SRCS} ${LIBRARY_SRCS} ${BLE_SRCS})
set(priv_includes cores/esp32/libb64)
set(requires spi_flash mbedtls mdns esp_adc_cal)
set(priv_requires fatfs nvs_flash app_update spiffs bootloader_support openssl bt tinyusb main)
set(COMPONENT_REQUIRES spi_flash mbedtls mdns ethernet) idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})
set(COMPONENT_PRIV_REQUIRES fatfs nvs_flash app_update spiffs bootloader_support openssl bt)
register_component() if(IDF_TARGET STREQUAL "esp32")
target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO=10812 -DARDUINO_ESP32_DEV -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="ESP32_DEV" -DARDUINO_VARIANT="esp32" -DESP32)
endif()
if(IDF_TARGET STREQUAL "esp32s2")
target_compile_options(${COMPONENT_TARGET} PUBLIC -DARDUINO=10812 -DARDUINO_ESP32S2_DEV -DARDUINO_ARCH_ESP32 -DARDUINO_BOARD="ESP32S2_DEV" -DARDUINO_VARIANT="esp32s2" -DESP32)
endif()

View File

@ -5,7 +5,7 @@ config ENABLE_ARDUINO_DEPENDS
select LWIP_SO_RCVBUF select LWIP_SO_RCVBUF
select ETHERNET select ETHERNET
select WIFI_ENABLED select WIFI_ENABLED
select ESP32_PHY_CALIBRATION_AND_DATA_STORAGE select ESP32_PHY_CALIBRATION_AND_DATA_STORAGE if IDF_TARGET_ESP32
select MEMMAP_SMP select MEMMAP_SMP
default "y" default "y"
@ -19,6 +19,79 @@ config AUTOSTART_ARDUINO
If disabled, you can call initArduino() to run any preparations If disabled, you can call initArduino() to run any preparations
required by the framework required by the framework
choice ARDUINO_RUNNING_CORE
bool "Core on which Arduino's setup() and loop() are running"
default ARDUINO_RUN_CORE1
help
Select on which core Arduino's setup() and loop() functions run
config ARDUINO_RUN_CORE0
bool "CORE 0"
config ARDUINO_RUN_CORE1
bool "CORE 1"
config ARDUINO_RUN_NO_AFFINITY
bool "BOTH"
endchoice
config ARDUINO_RUNNING_CORE
int
default 0 if ARDUINO_RUN_CORE0
default 1 if ARDUINO_RUN_CORE1
default -1 if ARDUINO_RUN_NO_AFFINITY
choice ARDUINO_EVENT_RUNNING_CORE
bool "Core on which Arduino's event handler is running"
default ARDUINO_EVENT_RUN_CORE1
help
Select on which core Arduino's WiFi.onEvent() run
config ARDUINO_EVENT_RUN_CORE0
bool "CORE 0"
config ARDUINO_EVENT_RUN_CORE1
bool "CORE 1"
config ARDUINO_EVENT_RUN_NO_AFFINITY
bool "BOTH"
endchoice
config ARDUINO_EVENT_RUNNING_CORE
int
default 0 if ARDUINO_EVENT_RUN_CORE0
default 1 if ARDUINO_EVENT_RUN_CORE1
default -1 if ARDUINO_EVENT_RUN_NO_AFFINITY
choice ARDUINO_UDP_RUNNING_CORE
bool "Core on which Arduino's UDP is running"
default ARDUINO_UDP_RUN_CORE1
help
Select on which core Arduino's UDP run
config ARDUINO_UDP_RUN_CORE0
bool "CORE 0"
config ARDUINO_UDP_RUN_CORE1
bool "CORE 1"
config ARDUINO_UDP_RUN_NO_AFFINITY
bool "BOTH"
endchoice
config ARDUINO_UDP_RUNNING_CORE
int
default 0 if ARDUINO_UDP_RUN_CORE0
default 1 if ARDUINO_UDP_RUN_CORE1
default -1 if ARDUINO_UDP_RUN_NO_AFFINITY
config ARDUINO_ISR_IRAM
bool "Run interrupts in IRAM"
default "n"
help
Enabling this option will Attach all interrupts with the IRAm flag.
It will also make some HAL function, like, digitalRead/Write and more
be loaded into IRAM for access inside ISRs.
Beware that this is a very dangerous setting. Enable it only if you
are fully aware of the consequences.
config DISABLE_HAL_LOCKS config DISABLE_HAL_LOCKS
bool "Disable mutex locks for HAL" bool "Disable mutex locks for HAL"
default "n" default "n"
@ -168,6 +241,12 @@ config ARDUINO_SELECTIVE_ESPmDNS
select ARDUINO_SELECTIVE_WiFi select ARDUINO_SELECTIVE_WiFi
default y default y
config ARDUINO_SELECTIVE_FFat
bool "Enable FFat"
depends on ARDUINO_SELECTIVE_COMPILATION
select ARDUINO_SELECTIVE_FS
default y
config ARDUINO_SELECTIVE_FS config ARDUINO_SELECTIVE_FS
bool "Enable FS" bool "Enable FS"
depends on ARDUINO_SELECTIVE_COMPILATION depends on ARDUINO_SELECTIVE_COMPILATION

503
LICENSE.md Normal file
View File

@ -0,0 +1,503 @@
### GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
### Preamble
The licenses for most software are designed to take away your freedom
to share and change it. By contrast, the GNU General Public Licenses
are intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there
is no warranty for the free library. Also, if the library is modified
by someone else and passed on, the recipients should know that what
they have is not the original version, so that the original author's
reputation will not be affected by problems that might be introduced
by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using a
shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
**0.** This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License"). Each
licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does and
what the program that uses the Library does.
**1.** You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a
fee.
**2.** You may modify your copy or copies of the Library or any
portion of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
- **a)** The modified work must itself be a software library.
- **b)** You must cause the files modified to carry prominent
notices stating that you changed the files and the date of
any change.
- **c)** You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
- **d)** If a facility in the modified Library refers to a function
or a table of data to be supplied by an application program that
uses the facility, other than as an argument passed when the
facility is invoked, then you must make a good faith effort to
ensure that, in the event an application does not supply such
function or table, the facility still operates, and performs
whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of
the application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
**3.** You may opt to apply the terms of the ordinary GNU General
Public License instead of this License to a given copy of the Library.
To do this, you must alter all the notices that refer to this License,
so that they refer to the ordinary GNU General Public License, version
2, instead of to this License. (If a newer version than version 2 of
the ordinary GNU General Public License has appeared, then you can
specify that version instead if you wish.) Do not make any other
change in these notices.
Once this change is made in a given copy, it is irreversible for that
copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the
Library into a program that is not a library.
**4.** You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from
a designated place, then offering equivalent access to copy the source
code from the same place satisfies the requirement to distribute the
source code, even though third parties are not compelled to copy the
source along with the object code.
**5.** A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a work,
in isolation, is not a derivative work of the Library, and therefore
falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License. Section
6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure
layouts and accessors, and small macros and small inline functions
(ten lines or less in length), then the use of the object file is
unrestricted, regardless of whether it is legally a derivative work.
(Executables containing this object code plus portions of the Library
will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
**6.** As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a work
containing portions of the Library, and distribute that work under
terms of your choice, provided that the terms permit modification of
the work for the customer's own use and reverse engineering for
debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
- **a)** Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood that
the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
- **b)** Use a suitable shared library mechanism for linking with
the Library. A suitable mechanism is one that (1) uses at run time
a copy of the library already present on the user's computer
system, rather than copying library functions into the executable,
and (2) will operate properly with a modified version of the
library, if the user installs one, as long as the modified version
is interface-compatible with the version that the work was
made with.
- **c)** Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
- **d)** If distribution of the work is made by offering access to
copy from a designated place, offer equivalent access to copy the
above specified materials from the same place.
- **e)** Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
**7.** You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
- **a)** Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other
library facilities. This must be distributed under the terms of
the Sections above.
- **b)** Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
**8.** You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
**9.** You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
**10.** Each time you redistribute the Library (or any work based on
the Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
**11.** If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to patent
issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this License.
If you cannot distribute so as to satisfy simultaneously your
obligations under this License and any other pertinent obligations,
then as a consequence you may not distribute the Library at all. For
example, if a patent license would not permit royalty-free
redistribution of the Library by all those who receive copies directly
or indirectly through you, then the only way you could satisfy both it
and this License would be to refrain entirely from distribution of the
Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
**12.** If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
**13.** The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time. Such
new versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
**14.** If you wish to incorporate parts of the Library into other
free programs whose distribution conditions are incompatible with
these, write to the author to ask for permission. For software which
is copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
**NO WARRANTY**
**15.** BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
**16.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
### END OF TERMS AND CONDITIONS
### How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It
is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
one line to give the library's name and an idea of what it does.
Copyright (C) year name of author
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper
mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.
signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -1,4 +1,5 @@
# Arduino core for ESP32 WiFi chip [![Build Status](https://travis-ci.org/espressif/arduino-esp32.svg?branch=master)](https://travis-ci.org/espressif/arduino-esp32) # Arduino core for the ESP32
[![Build Status](https://travis-ci.org/espressif/arduino-esp32.svg?branch=master)](https://travis-ci.org/espressif/arduino-esp32) ![](https://github.com/espressif/arduino-esp32/workflows/ESP32%20Arduino%20CI/badge.svg)
### Need help or have a question? Join the chat at [![https://gitter.im/espressif/arduino-esp32](https://badges.gitter.im/espressif/arduino-esp32.svg)](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Need help or have a question? Join the chat at [![https://gitter.im/espressif/arduino-esp32](https://badges.gitter.im/espressif/arduino-esp32.svg)](https://gitter.im/espressif/arduino-esp32?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@ -9,17 +10,12 @@
- [Issue/Bug report template](#issuebug-report-template) - [Issue/Bug report template](#issuebug-report-template)
- [ESP32Dev Board PINMAP](#esp32dev-board-pinmap) - [ESP32Dev Board PINMAP](#esp32dev-board-pinmap)
## Development Status ### Development Status
[Latest stable release ![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic) [Latest stable release ![Release Version](https://img.shields.io/github/release/espressif/arduino-esp32.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads/espressif/arduino-esp32/latest/total.svg?style=plastic)
[Latest development release ![Development Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic) ![Development Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic) [Latest development release ![Development Version](https://img.shields.io/github/release/espressif/arduino-esp32/all.svg?style=plastic) ![Development Date](https://img.shields.io/github/release-date-pre/espressif/arduino-esp32.svg?style=plastic)](https://github.com/espressif/arduino-esp32/releases/latest/) ![Downloads](https://img.shields.io/github/downloads-pre/espressif/arduino-esp32/latest/total.svg?style=plastic)
Most of the framework is implemented. Most noticable is the missing analogWrite. While analogWrite is on it's way, there are a few other options that you can use: ### Installation Instructions
- 16 channels [LEDC](cores/esp32/esp32-hal-ledc.h) which is PWM
- 8 channels [SigmaDelta](cores/esp32/esp32-hal-sigmadelta.h) which uses SigmaDelta modulation
- 2 channels [DAC](cores/esp32/esp32-hal-dac.h) which gives real analog output
## Installation Instructions
- Using Arduino IDE Boards Manager (preferred) - Using Arduino IDE Boards Manager (preferred)
+ [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md) + [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md)
- Using Arduino IDE with the development repository - Using Arduino IDE with the development repository
@ -33,20 +29,19 @@ Most of the framework is implemented. Most noticable is the missing analogWrite.
- [Using as ESP-IDF component](docs/esp-idf_component.md) - [Using as ESP-IDF component](docs/esp-idf_component.md)
- [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md) - [Using OTAWebUpdater](docs/OTAWebUpdate/OTAWebUpdate.md)
#### Decoding exceptions ### Decoding exceptions
You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace. You can use [EspExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) to get meaningful call trace.
#### Issue/Bug report template ### 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 [for reference](https://github.com/espressif/arduino-esp32/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3A%22for%20reference%22%20).
Finally, if you're sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue. Finally, if you are sure no one else had the issue, follow the [ISSUE_TEMPLATE](docs/ISSUE_TEMPLATE.md) while reporting any issue.
### ESP32Dev Board PINMAP
## ESP32Dev Board PINMAP
![Pin Functions](docs/esp32_pinmap.png) ![Pin Functions](docs/esp32_pinmap.png)
## Hint ### Tip
Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process Sometimes to program ESP32 via serial you must keep GPIO0 LOW during the programming process

View File

@ -1,19 +0,0 @@
build: off
environment:
matrix:
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClient"
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientBasic"
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiClientEvents"
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiIPv6"
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiScan"
- PLATFORMIO_CI_SRC: "libraries/WiFi/examples/WiFiSmartConfig"
install:
- cmd: git submodule update --init --recursive
- cmd: SET PATH=%PATH%;C:\Python27\Scripts
- cmd: pip install -U https://github.com/platformio/platformio/archive/develop.zip
- cmd: platformio platform install https://github.com/platformio/platform-espressif32.git#feature/stage
test_script:
- cmd: platformio ci -b esp32dev -b nano32 -b node32s

2509
boards.txt

File diff suppressed because it is too large Load Diff

View File

@ -68,12 +68,6 @@
#define __STRINGIFY(a) #a #define __STRINGIFY(a) #a
#endif #endif
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define radians(deg) ((deg)*DEG_TO_RAD) #define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG) #define degrees(rad) ((rad)*RAD_TO_DEG)
@ -121,10 +115,12 @@ typedef bool boolean;
typedef uint8_t byte; typedef uint8_t byte;
typedef unsigned int word; typedef unsigned int word;
#ifdef __cplusplus
void setup(void); void setup(void);
void loop(void); void loop(void);
long random(long, long); long random(long, long);
#endif
void randomSeed(unsigned long); void randomSeed(unsigned long);
long map(long, long, long, long, long); long map(long, long, long, long, long);
@ -160,6 +156,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
#include "HardwareSerial.h" #include "HardwareSerial.h"
#include "Esp.h" #include "Esp.h"
using std::abs;
using std::isinf; using std::isinf;
using std::isnan; using std::isnan;
using std::max; using std::max;

View File

@ -19,7 +19,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "Esp.h" #include "Esp.h"
#include "rom/spi_flash.h"
#include "esp_sleep.h" #include "esp_sleep.h"
#include "esp_spi_flash.h" #include "esp_spi_flash.h"
#include <memory> #include <memory>
@ -32,6 +31,19 @@ extern "C" {
} }
#include <MD5Builder.h> #include <MD5Builder.h>
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/spi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/spi_flash.h"
#endif
/** /**
* User-defined Literals * User-defined Literals
* usage: * usage:
@ -92,13 +104,6 @@ void EspClass::deepSleep(uint32_t time_us)
esp_deep_sleep(time_us); esp_deep_sleep(time_us);
} }
uint32_t EspClass::getCycleCount()
{
uint32_t ccount;
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
return ccount;
}
void EspClass::restart(void) void EspClass::restart(void)
{ {
esp_restart(); esp_restart();
@ -128,24 +133,36 @@ uint32_t EspClass::getMaxAllocHeap(void)
uint32_t EspClass::getPsramSize(void) uint32_t EspClass::getPsramSize(void)
{ {
multi_heap_info_t info; if(psramFound()){
heap_caps_get_info(&info, MALLOC_CAP_SPIRAM); multi_heap_info_t info;
return info.total_free_bytes + info.total_allocated_bytes; heap_caps_get_info(&info, MALLOC_CAP_SPIRAM);
return info.total_free_bytes + info.total_allocated_bytes;
}
return 0;
} }
uint32_t EspClass::getFreePsram(void) uint32_t EspClass::getFreePsram(void)
{ {
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM); if(psramFound()){
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
}
return 0;
} }
uint32_t EspClass::getMinFreePsram(void) uint32_t EspClass::getMinFreePsram(void)
{ {
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); if(psramFound()){
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
}
return 0;
} }
uint32_t EspClass::getMaxAllocPsram(void) uint32_t EspClass::getMaxAllocPsram(void)
{ {
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); if(psramFound()){
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
}
return 0;
} }
static uint32_t sketchSize(sketchSize_t response) { static uint32_t sketchSize(sketchSize_t response) {

View File

@ -75,8 +75,8 @@ public:
uint32_t getMaxAllocPsram(); uint32_t getMaxAllocPsram();
uint8_t getChipRevision(); uint8_t getChipRevision();
uint8_t getCpuFreqMHz(){ return CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; } uint32_t getCpuFreqMHz(){ return getCpuFrequencyMhz(); }
uint32_t getCycleCount(); inline uint32_t getCycleCount() __attribute__((always_inline));
const char * getSdkVersion(); const char * getSdkVersion();
void deepSleep(uint32_t time_us); void deepSleep(uint32_t time_us);
@ -101,6 +101,13 @@ public:
}; };
uint32_t ARDUINO_ISR_ATTR EspClass::getCycleCount()
{
uint32_t ccount;
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
return ccount;
}
extern EspClass ESP; extern EspClass ESP;
#endif //ESP_H #endif //ESP_H

View File

@ -16,7 +16,7 @@ extern "C"
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional); extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
} }
void IRAM_ATTR interruptFunctional(void* arg) void ARDUINO_ISR_ATTR interruptFunctional(void* arg)
{ {
InterruptArgStructure* localArg = (InterruptArgStructure*)arg; InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
if (localArg->interruptFunction) if (localArg->interruptFunction)

View File

@ -6,6 +6,8 @@
#include "pins_arduino.h" #include "pins_arduino.h"
#include "HardwareSerial.h" #include "HardwareSerial.h"
#if CONFIG_IDF_TARGET_ESP32
#ifndef RX1 #ifndef RX1
#define RX1 9 #define RX1 9
#endif #endif
@ -22,11 +24,29 @@
#define TX2 17 #define TX2 17
#endif #endif
#else
#ifndef RX1
#define RX1 18
#endif
#ifndef TX1
#define TX1 17
#endif
#endif
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
HardwareSerial Serial0(0);
#else
HardwareSerial Serial(0); HardwareSerial Serial(0);
#endif
HardwareSerial Serial1(1); HardwareSerial Serial1(1);
#if CONFIG_IDF_TARGET_ESP32
HardwareSerial Serial2(2); HardwareSerial Serial2(2);
#endif #endif
#endif
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {} HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
@ -40,21 +60,28 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
end(); end();
} }
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) { if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
#if CONFIG_IDF_TARGET_ESP32
rxPin = 3; rxPin = 3;
txPin = 1; txPin = 1;
#elif CONFIG_IDF_TARGET_ESP32S2
rxPin = 44;
txPin = 43;
#endif
} }
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) { if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
rxPin = RX1; rxPin = RX1;
txPin = TX1; txPin = TX1;
} }
#if CONFIG_IDF_TARGET_ESP32
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) { if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
rxPin = RX2; rxPin = RX2;
txPin = TX2; txPin = TX2;
} }
#endif
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert); _uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert);
if(!baud) { if(!baud) {
uartStartDetectBaudrate(_uart);
time_t startMillis = millis(); time_t startMillis = millis();
unsigned long detectedBaudRate = 0; unsigned long detectedBaudRate = 0;
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) { while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
@ -100,7 +127,7 @@ void HardwareSerial::setDebugOutput(bool en)
uartSetDebug(_uart); uartSetDebug(_uart);
} else { } else {
if(uartGetDebug() == _uart_nr) { if(uartGetDebug() == _uart_nr) {
uartSetDebug(0); uartSetDebug(NULL);
} }
} }
} }
@ -130,11 +157,34 @@ int HardwareSerial::read(void)
return -1; return -1;
} }
void HardwareSerial::flush() // read characters into buffer
// terminates if size characters have been read, or no further are pending
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
size_t HardwareSerial::read(uint8_t *buffer, size_t size)
{
size_t avail = available();
if (size < avail) {
avail = size;
}
size_t count = 0;
while(count < avail) {
*buffer++ = uartRead(_uart);
count++;
}
return count;
}
void HardwareSerial::flush(void)
{ {
uartFlush(_uart); uartFlush(_uart);
} }
void HardwareSerial::flush(bool txOnly)
{
uartFlushTxOnly(_uart, txOnly);
}
size_t HardwareSerial::write(uint8_t c) size_t HardwareSerial::write(uint8_t c)
{ {
uartWrite(_uart, c); uartWrite(_uart, c);

View File

@ -62,10 +62,19 @@ public:
int availableForWrite(void); int availableForWrite(void);
int peek(void); int peek(void);
int read(void); int read(void);
size_t read(uint8_t *buffer, size_t size);
inline size_t read(char * buffer, size_t size)
{
return read((uint8_t*) buffer, size);
}
void flush(void); void flush(void);
void flush( bool txOnly);
size_t write(uint8_t); size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size); size_t write(const uint8_t *buffer, size_t size);
inline size_t write(const char * buffer, size_t size)
{
return write((uint8_t*) buffer, size);
}
inline size_t write(const char * s) inline size_t write(const char * s)
{ {
return write((uint8_t*) s, strlen(s)); return write((uint8_t*) s, strlen(s));
@ -97,10 +106,23 @@ protected:
uart_t* _uart; uart_t* _uart;
}; };
extern void serialEventRun(void) __attribute__((weak));
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
#ifndef ARDUINO_SERIAL_PORT
#define ARDUINO_SERIAL_PORT 0
#endif
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
#include "USB.h"
#include "USBCDC.h"
extern HardwareSerial Serial0;
#else
extern HardwareSerial Serial; extern HardwareSerial Serial;
#endif
extern HardwareSerial Serial1; extern HardwareSerial Serial1;
#if CONFIG_IDF_TARGET_ESP32
extern HardwareSerial Serial2; extern HardwareSerial Serial2;
#endif #endif
#endif #endif
#endif // HardwareSerial_h

View File

@ -21,7 +21,19 @@
#include <WString.h> #include <WString.h>
#include <Stream.h> #include <Stream.h>
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/md5_hash.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/md5_hash.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/md5_hash.h" #include "rom/md5_hash.h"
#endif
class MD5Builder class MD5Builder
{ {

View File

@ -52,19 +52,24 @@ size_t Print::printf(const char *format, ...)
va_list copy; va_list copy;
va_start(arg, format); va_start(arg, format);
va_copy(copy, arg); va_copy(copy, arg);
size_t len = vsnprintf(NULL, 0, format, arg); int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
va_end(copy); va_end(copy);
if(len < 0) {
va_end(arg);
return 0;
};
if(len >= sizeof(loc_buf)){ if(len >= sizeof(loc_buf)){
temp = new char[len+1]; temp = (char*) malloc(len+1);
if(temp == NULL) { if(temp == NULL) {
va_end(arg);
return 0; return 0;
} }
len = vsnprintf(temp, len+1, format, arg);
} }
len = vsnprintf(temp, len+1, format, arg);
write((uint8_t*)temp, len);
va_end(arg); va_end(arg);
if(len >= sizeof(loc_buf)){ len = write((uint8_t*)temp, len);
delete[] temp; if(temp != loc_buf){
free(temp);
} }
return len; return len;
} }
@ -154,8 +159,10 @@ size_t Print::print(struct tm * timeinfo, const char * format)
} }
char buf[64]; char buf[64];
size_t written = strftime(buf, 64, f, timeinfo); size_t written = strftime(buf, 64, f, timeinfo);
print(buf); if(written == 0){
return written; return written;
}
return print(buf);
} }
size_t Print::println(void) size_t Print::println(void)

View File

@ -82,6 +82,9 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
{ {
_timeout = timeout; _timeout = timeout;
} }
unsigned long Stream::getTimeout(void) {
return _timeout;
}
// find returns true if the target string is found // find returns true if the target string is found
bool Stream::find(const char *target) bool Stream::find(const char *target)

View File

@ -59,7 +59,7 @@ public:
// parsing methods // parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void);
bool find(const char *target); // reads data from the stream until the target string is found bool find(const char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target) bool find(uint8_t *target)
{ {
@ -97,8 +97,8 @@ public:
float parseFloat(); // float version of parseInt float parseFloat(); // float version of parseInt
size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
size_t readBytes(uint8_t *buffer, size_t length) virtual size_t readBytes(uint8_t *buffer, size_t length)
{ {
return readBytes((char *) buffer, length); return readBytes((char *) buffer, length);
} }
@ -114,7 +114,7 @@ public:
// returns the number of characters placed in the buffer (0 means no valid data found) // returns the number of characters placed in the buffer (0 means no valid data found)
// Arduino String functions to be added here // Arduino String functions to be added here
String readString(); virtual String readString();
String readStringUntil(char terminator); String readStringUntil(char terminator);
protected: protected:

View File

@ -2,6 +2,7 @@
StreamString.cpp StreamString.cpp
Copyright (c) 2015 Markus Sattler. All rights reserved. Copyright (c) 2015 Markus Sattler. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -22,31 +23,28 @@
#include <Arduino.h> #include <Arduino.h>
#include "StreamString.h" #include "StreamString.h"
size_t StreamString::write(const uint8_t *data, size_t size) size_t StreamString::write(const uint8_t *data, size_t size) {
{
if(size && data) { if(size && data) {
if(reserve(length() + size + 1)) { const unsigned int newlen = length() + size;
memcpy((void *) (buffer + len), (const void *) data, size); if(reserve(newlen + 1)) {
len += size; memcpy((void *) (wbuffer() + len()), (const void *) data, size);
*(buffer + len) = 0x00; // add null for string end setLen(newlen);
*(wbuffer() + newlen) = 0x00; // add null for string end
return size; return size;
} }
} }
return 0; return 0;
} }
size_t StreamString::write(uint8_t data) size_t StreamString::write(uint8_t data) {
{
return concat((char) data); return concat((char) data);
} }
int StreamString::available() int StreamString::available() {
{
return length(); return length();
} }
int StreamString::read() int StreamString::read() {
{
if(length()) { if(length()) {
char c = charAt(0); char c = charAt(0);
remove(0, 1); remove(0, 1);
@ -56,8 +54,7 @@ int StreamString::read()
return -1; return -1;
} }
int StreamString::peek() int StreamString::peek() {
{
if(length()) { if(length()) {
char c = charAt(0); char c = charAt(0);
return c; return c;
@ -65,7 +62,6 @@ int StreamString::peek()
return -1; return -1;
} }
void StreamString::flush() void StreamString::flush() {
{
} }

338
cores/esp32/USB.cpp Normal file
View File

@ -0,0 +1,338 @@
// Copyright 2015-2020 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 "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#if CONFIG_USB_ENABLED
#ifndef USB_VID
#define USB_VID USB_ESPRESSIF_VID
#endif
#ifndef USB_PID
#define USB_PID 0x0002
#endif
#ifndef USB_MANUFACTURER
#define USB_MANUFACTURER "Espressif Systems"
#endif
#ifndef USB_PRODUCT
#define USB_PRODUCT ARDUINO_BOARD
#endif
#ifndef USB_SERIAL
#define USB_SERIAL "0"
#endif
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_DFU_RT
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
{
#define DFU_ATTR_CAN_DOWNLOAD 1
#define DFU_ATTR_CAN_UPLOAD 2
#define DFU_ATTR_MANIFESTATION_TOLERANT 4
#define DFU_ATTR_WILL_DETACH 8
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT");
uint8_t descriptor[TUD_DFU_RT_DESC_LEN] = {
// Interface number, string index, attributes, detach timeout, transfer size */
TUD_DFU_RT_DESCRIPTOR(*itf, str_index, DFU_ATTRS, 700, 64)
};
*itf+=1;
memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN);
return TUD_DFU_RT_DESC_LEN;
}
// Invoked on DFU_DETACH request to reboot to the bootloader
void tud_dfu_rt_reboot_to_dfu(void)
{
usb_persist_restart(RESTART_BOOTLOADER_DFU);
}
#endif /* CFG_TUD_DFU_RT */
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS);
static esp_event_loop_handle_t arduino_usb_event_loop_handle = NULL;
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait){
if(arduino_usb_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_post_to(arduino_usb_event_loop_handle, event_base, event_id, event_data, event_data_size, ticks_to_wait);
}
esp_err_t arduino_usb_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_usb_event_loop_handle == NULL){
return ESP_FAIL;
}
return esp_event_handler_register_with(arduino_usb_event_loop_handle, event_base, event_id, event_handler, event_handler_arg);
}
static bool tinyusb_device_mounted = false;
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_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_post(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
// Invoked when usb bus is suspended
// 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};
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);
}
// 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_post(ARDUINO_USB_EVENTS, ARDUINO_USB_RESUME_EVENT, &p, sizeof(arduino_usb_event_data_t), portMAX_DELAY);
}
ESPUSB::ESPUSB(size_t task_stack_size, uint8_t event_task_priority)
:vid(USB_VID)
,pid(USB_PID)
,product_name(USB_PRODUCT)
,manufacturer_name(USB_MANUFACTURER)
,serial_number(USB_SERIAL)
,fw_version(0x0100)
,usb_version(0x0200)// at least 2.1 or 3.x for BOS & webUSB
,usb_class(TUSB_CLASS_MISC)
,usb_subclass(MISC_SUBCLASS_COMMON)
,usb_protocol(MISC_PROTOCOL_IAD)
,usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
,usb_power_ma(500)
,webusb_enabled(false)
,webusb_url("espressif.github.io/arduino-esp32/webusb.html")
,_started(false)
,_task_stack_size(task_stack_size)
,_event_task_priority(event_task_priority)
{
if (!arduino_usb_event_loop_handle) {
esp_event_loop_args_t event_task_args = {
.queue_size = 5,
.task_name = "arduino_usb_events",
.task_priority = _event_task_priority,
.task_stack_size = _task_stack_size,
.task_core_id = tskNO_AFFINITY
};
if (esp_event_loop_create(&event_task_args, &arduino_usb_event_loop_handle) != ESP_OK) {
log_e("esp_event_loop_create failed");
}
}
}
ESPUSB::~ESPUSB(){
if (arduino_usb_event_loop_handle) {
esp_event_loop_delete(arduino_usb_event_loop_handle);
arduino_usb_event_loop_handle = NULL;
}
}
bool ESPUSB::begin(){
if(!_started){
tinyusb_device_config_t tinyusb_device_config = {
.vid = vid,
.pid = pid,
.product_name = product_name.c_str(),
.manufacturer_name = manufacturer_name.c_str(),
.serial_number = serial_number.c_str(),
.fw_version = fw_version,
.usb_version = usb_version,
.usb_class = usb_class,
.usb_subclass = usb_subclass,
.usb_protocol = usb_protocol,
.usb_attributes = usb_attributes,
.usb_power_ma = usb_power_ma,
.webusb_enabled = webusb_enabled,
.webusb_url = webusb_url.c_str()
};
_started = tinyusb_init(&tinyusb_device_config) == ESP_OK;
}
return _started;
}
void ESPUSB::onEvent(esp_event_handler_t callback){
onEvent(ARDUINO_USB_ANY_EVENT, callback);
}
void ESPUSB::onEvent(arduino_usb_event_t event, esp_event_handler_t callback){
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, event, callback, this);
}
ESPUSB::operator bool() const
{
return _started && tinyusb_device_mounted;
}
bool ESPUSB::enableDFU(){
#if CFG_TUD_DFU_RT
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
#endif /* CFG_TUD_DFU_RT */
return false;
}
bool ESPUSB::VID(uint16_t v){
if(!_started){
vid = v;
}
return !_started;
}
uint16_t ESPUSB::VID(void){
return vid;
}
bool ESPUSB::PID(uint16_t p){
if(!_started){
pid = p;
}
return !_started;
}
uint16_t ESPUSB::PID(void){
return pid;
}
bool ESPUSB::firmwareVersion(uint16_t version){
if(!_started){
fw_version = version;
}
return !_started;
}
uint16_t ESPUSB::firmwareVersion(void){
return fw_version;
}
bool ESPUSB::usbVersion(uint16_t version){
if(!_started){
usb_version = version;
}
return !_started;
}
uint16_t ESPUSB::usbVersion(void){
return usb_version;
}
bool ESPUSB::usbPower(uint16_t mA){
if(!_started){
usb_power_ma = mA;
}
return !_started;
}
uint16_t ESPUSB::usbPower(void){
return usb_power_ma;
}
bool ESPUSB::usbClass(uint8_t _class){
if(!_started){
usb_class = _class;
}
return !_started;
}
uint8_t ESPUSB::usbClass(void){
return usb_class;
}
bool ESPUSB::usbSubClass(uint8_t subClass){
if(!_started){
usb_subclass = subClass;
}
return !_started;
}
uint8_t ESPUSB::usbSubClass(void){
return usb_subclass;
}
bool ESPUSB::usbProtocol(uint8_t protocol){
if(!_started){
usb_protocol = protocol;
}
return !_started;
}
uint8_t ESPUSB::usbProtocol(void){
return usb_protocol;
}
bool ESPUSB::usbAttributes(uint8_t attr){
if(!_started){
usb_attributes = attr;
}
return !_started;
}
uint8_t ESPUSB::usbAttributes(void){
return usb_attributes;
}
bool ESPUSB::webUSB(bool enabled){
if(!_started){
webusb_enabled = enabled;
}
return !_started;
}
bool ESPUSB::webUSB(void){
return webusb_enabled;
}
bool ESPUSB::productName(const char * name){
if(!_started){
product_name = name;
}
return !_started;
}
const char * ESPUSB::productName(void){
return product_name.c_str();
}
bool ESPUSB::manufacturerName(const char * name){
if(!_started){
manufacturer_name = name;
}
return !_started;
}
const char * ESPUSB::manufacturerName(void){
return manufacturer_name.c_str();
}
bool ESPUSB::serialNumber(const char * name){
if(!_started){
serial_number = name;
}
return !_started;
}
const char * ESPUSB::serialNumber(void){
return serial_number.c_str();
}
bool ESPUSB::webUSBURL(const char * name){
if(!_started){
webusb_url = name;
}
return !_started;
}
const char * ESPUSB::webUSBURL(void){
return webusb_url.c_str();
}
ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */

118
cores/esp32/USB.h Normal file
View File

@ -0,0 +1,118 @@
// Copyright 2015-2020 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
#include "sdkconfig.h"
#if CONFIG_USB_ENABLED
#include "Arduino.h"
#include "USBCDC.h"
#include "esp_event.h"
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_EVENTS);
typedef enum {
ARDUINO_USB_ANY_EVENT = ESP_EVENT_ANY_ID,
ARDUINO_USB_STARTED_EVENT = 0,
ARDUINO_USB_STOPPED_EVENT,
ARDUINO_USB_SUSPEND_EVENT,
ARDUINO_USB_RESUME_EVENT,
ARDUINO_USB_MAX_EVENT,
} arduino_usb_event_t;
typedef union {
struct {
bool remote_wakeup_en;
} suspend;
} arduino_usb_event_data_t;
class ESPUSB {
public:
ESPUSB(size_t event_task_stack_size=2048, uint8_t event_task_priority=5);
~ESPUSB();
void onEvent(esp_event_handler_t callback);
void onEvent(arduino_usb_event_t event, esp_event_handler_t callback);
bool VID(uint16_t v);
uint16_t VID(void);
bool PID(uint16_t p);
uint16_t PID(void);
bool firmwareVersion(uint16_t version);
uint16_t firmwareVersion(void);
bool usbVersion(uint16_t version);
uint16_t usbVersion(void);
bool usbPower(uint16_t mA);
uint16_t usbPower(void);
bool usbClass(uint8_t _class);
uint8_t usbClass(void);
bool usbSubClass(uint8_t subClass);
uint8_t usbSubClass(void);
bool usbProtocol(uint8_t protocol);
uint8_t usbProtocol(void);
bool usbAttributes(uint8_t attr);
uint8_t usbAttributes(void);
bool webUSB(bool enabled);
bool webUSB(void);
bool productName(const char * name);
const char * productName(void);
bool manufacturerName(const char * name);
const char * manufacturerName(void);
bool serialNumber(const char * name);
const char * serialNumber(void);
bool webUSBURL(const char * name);
const char * webUSBURL(void);
bool enableDFU();
bool begin();
operator bool() const;
private:
uint16_t vid;
uint16_t pid;
String product_name;
String manufacturer_name;
String serial_number;
uint16_t fw_version;
uint16_t usb_version;
uint8_t usb_class;
uint8_t usb_subclass;
uint8_t usb_protocol;
uint8_t usb_attributes;
uint16_t usb_power_ma;
bool webusb_enabled;
String webusb_url;
bool _started;
size_t _task_stack_size;
uint8_t _event_task_priority;
};
extern ESPUSB USB;
#endif /* CONFIG_USB_ENABLED */

338
cores/esp32/USBCDC.cpp Normal file
View File

@ -0,0 +1,338 @@
// Copyright 2015-2020 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 "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "USB.h"
#include "USBCDC.h"
#if CONFIG_USB_ENABLED
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS);
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
extern "C" {
#include "tinyusb.h"
}
#if CFG_TUD_CDC
#define MAX_USB_CDC_DEVICES 2
USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL};
static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf)
{
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC");
// Interface number, string index, attributes, detach timeout, transfer size */
uint8_t descriptor[TUD_CDC_DESC_LEN] = {
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64)
};
*itf+=2;
memcpy(dst, descriptor, TUD_CDC_DESC_LEN);
return TUD_CDC_DESC_LEN;
}
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
devices[itf]->_onLineState(dtr, rts);
}
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding)
{
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits);
}
}
void tud_cdc_rx_cb(uint8_t itf)
{
if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){
devices[itf]->_onRX();
}
}
static size_t tinyusb_cdc_write(uint8_t itf, const uint8_t *buffer, size_t size){
if(itf >= MAX_USB_CDC_DEVICES){
return 0;
}
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){
delay(1);
continue;
}
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);
}
return sofar;
}
static void ARDUINO_ISR_ATTR cdc0_write_char(char c)
{
tinyusb_cdc_write(0, (const uint8_t *)&c, 1);
}
//void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
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) {
tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor);
if(itf < MAX_USB_CDC_DEVICES){
devices[itf] = this;
arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this);
}
}
void USBCDC::onEvent(esp_event_handler_t callback){
onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback);
}
void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback){
arduino_usb_event_handler_register_with(ARDUINO_USB_CDC_EVENTS, event, callback, this);
}
size_t USBCDC::setRxBufferSize(size_t rx_queue_len){
if(rx_queue){
return 0;
}
rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t));
if(!rx_queue){
return 0;
}
return rx_queue_len;
}
void USBCDC::begin(unsigned long baud)
{
setRxBufferSize(256);//default if not preset
}
void USBCDC::end()
{
}
void USBCDC::_onUnplugged(void){
if(connected){
connected = false;
dtr = false;
rts = false;
arduino_usb_cdc_event_data_t p = {0};
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
}
enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 };
void USBCDC::_onLineState(bool _dtr, bool _rts){
static uint8_t lineState = CDC_LINE_IDLE;
dtr = _dtr;
rts = _rts;
if(reboot_enable){
if(!dtr && rts){
if(lineState == CDC_LINE_IDLE){
lineState++;
} else {
lineState = CDC_LINE_IDLE;
}
} else if(dtr && rts){
if(lineState == CDC_LINE_1){
lineState++;
} else {
lineState = CDC_LINE_IDLE;
}
} else if(dtr && !rts){
if(lineState == CDC_LINE_2){
lineState++;
} else {
lineState = CDC_LINE_IDLE;
}
} else if(!dtr && !rts){
if(lineState == CDC_LINE_3){
usb_persist_restart(RESTART_BOOTLOADER);
} else {
lineState = CDC_LINE_IDLE;
}
}
}
if(lineState == CDC_LINE_IDLE){
if(dtr && rts && !connected){
connected = true;
arduino_usb_cdc_event_data_t p = {0};
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 && !rts && connected){
connected = false;
arduino_usb_cdc_event_data_t p = {0};
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};
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);
}
}
void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){
if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){
bit_rate = _bit_rate;
data_bits = _data_bits;
stop_bits = _stop_bits;
parity = _parity;
arduino_usb_cdc_event_data_t p = {0};
p.line_coding.bit_rate = bit_rate;
p.line_coding.data_bits = data_bits;
p.line_coding.stop_bits = stop_bits;
p.line_coding.parity = parity;
arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY);
}
}
void USBCDC::_onRX(){
uint8_t buf[CONFIG_USB_CDC_RX_BUFSIZE+1];
uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_USB_CDC_RX_BUFSIZE);
for(uint32_t i=0; i<count; i++){
if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){
return;
}
}
arduino_usb_cdc_event_data_t p = {0};
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::enableReboot(bool enable){
reboot_enable = enable;
}
bool USBCDC::rebootEnabled(void){
return reboot_enable;
}
int USBCDC::available(void)
{
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
return -1;
}
return uxQueueMessagesWaiting(rx_queue);
}
int USBCDC::peek(void)
{
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
return -1;
}
uint8_t c;
if(xQueuePeek(rx_queue, &c, 0)) {
return c;
}
return -1;
}
int USBCDC::read(void)
{
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
return -1;
}
uint8_t c = 0;
if(xQueueReceive(rx_queue, &c, 0)) {
return c;
}
return -1;
}
size_t USBCDC::read(uint8_t *buffer, size_t size)
{
if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){
return -1;
}
uint8_t c = 0;
size_t count = 0;
while(count < size && xQueueReceive(rx_queue, &c, 0)){
buffer[count++] = c;
}
return count;
}
void USBCDC::flush(void)
{
if(itf >= MAX_USB_CDC_DEVICES){
return;
}
tud_cdc_n_write_flush(itf);
}
int USBCDC::availableForWrite(void)
{
if(itf >= MAX_USB_CDC_DEVICES){
return -1;
}
return tud_cdc_n_write_available(itf);
}
size_t USBCDC::write(const uint8_t *buffer, size_t size)
{
return tinyusb_cdc_write(itf, buffer, size);
}
size_t USBCDC::write(uint8_t c)
{
return write(&c, 1);
}
uint32_t USBCDC::baudRate()
{
return bit_rate;
}
void USBCDC::setDebugOutput(bool en)
{
if(en) {
uartSetDebug(NULL);
ets_install_putc1((void (*)(char)) &cdc0_write_char);
} else {
ets_install_putc1(NULL);
}
}
USBCDC::operator bool() const
{
if(itf >= MAX_USB_CDC_DEVICES){
return false;
}
return connected;
}
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
USBCDC Serial(0);
#endif
#endif /* CONFIG_USB_CDC_ENABLED */
#endif /* CONFIG_USB_ENABLED */

133
cores/esp32/USBCDC.h Normal file
View File

@ -0,0 +1,133 @@
// Copyright 2015-2020 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
#include <inttypes.h>
#include "Stream.h"
#include "esp32-hal.h"
#if CONFIG_USB_CDC_ENABLED
#include "esp_event.h"
ESP_EVENT_DECLARE_BASE(ARDUINO_USB_CDC_EVENTS);
typedef enum {
ARDUINO_USB_CDC_ANY_EVENT = ESP_EVENT_ANY_ID,
ARDUINO_USB_CDC_CONNECTED_EVENT = 0,
ARDUINO_USB_CDC_DISCONNECTED_EVENT,
ARDUINO_USB_CDC_LINE_STATE_EVENT,
ARDUINO_USB_CDC_LINE_CODING_EVENT,
ARDUINO_USB_CDC_RX_EVENT,
ARDUINO_USB_CDC_MAX_EVENT,
} arduino_usb_cdc_event_t;
typedef union {
struct {
bool dtr;
bool rts;
} line_state;
struct {
uint32_t bit_rate;
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
} line_coding;
struct {
size_t len;
} rx;
} arduino_usb_cdc_event_data_t;
class USBCDC: public Stream
{
public:
USBCDC(uint8_t itf=0);
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);
void begin(unsigned long baud=0);
void end();
int available(void);
int availableForWrite(void);
int peek(void);
int read(void);
size_t read(uint8_t *buffer, size_t size);
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
void flush(void);
inline size_t read(char * buffer, size_t size)
{
return read((uint8_t*) buffer, size);
}
inline size_t write(const char * buffer, size_t size)
{
return write((uint8_t*) buffer, size);
}
inline size_t write(const char * s)
{
return write((uint8_t*) s, strlen(s));
}
inline size_t write(unsigned long n)
{
return write((uint8_t) n);
}
inline size_t write(long n)
{
return write((uint8_t) n);
}
inline size_t write(unsigned int n)
{
return write((uint8_t) n);
}
inline size_t write(int n)
{
return write((uint8_t) n);
}
uint32_t baudRate();
void setDebugOutput(bool);
operator bool() const;
void enableReboot(bool enable);
bool rebootEnabled(void);
//internal methods
void _onDFU(void);
void _onLineState(bool _dtr, bool _rts);
void _onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits);
void _onRX(void);
void _onUnplugged(void);
protected:
uint8_t itf;
uint32_t bit_rate;
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16
bool dtr;
bool rts;
bool connected;
bool reboot_enable;
xQueueHandle rx_queue;
};
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
extern USBCDC Serial;
#endif
#endif /* CONFIG_USB_CDC_ENABLED */

View File

@ -65,9 +65,12 @@ long random(long howsmall, long howbig)
return random(diff) + howsmall; return random(diff) + howsmall;
} }
long map(long x, long in_min, long in_max, long out_min, long out_max) long map(long x, long in_min, long in_max, long out_min, long out_max) {
{ long divisor = (in_max - in_min);
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; if(divisor == 0){
return -1; //AVR returns -1, SAM returns 0
}
return (x - in_min) * (out_max - out_min) / divisor + out_min;
} }
unsigned int makeWord(unsigned int w) unsigned int makeWord(unsigned int w)

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <pgmspace.h> #include <pgmspace.h>
#include <stdint.h>
// An inherited class for holding the result of a concatenation. These // An inherited class for holding the result of a concatenation. These
// result objects are assumed to be writable by subsequent concatenations. // result objects are assumed to be writable by subsequent concatenations.
@ -35,295 +36,327 @@ class StringSumHelper;
// an abstract class used as a means to proide a unique pointer type // an abstract class used as a means to proide a unique pointer type
// but really has no body // but really has no body
class __FlashStringHelper; class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal))) #define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
#define F(string_literal) (FPSTR(PSTR(string_literal)))
// The string class // The string class
class String class String {
{ // use a function pointer to allow for "if (s)" without the
// use a function pointer to allow for "if (s)" without the // complications of an operator bool(). for more information, see:
// complications of an operator bool(). for more information, see: // http://www.artima.com/cppsource/safebool.html
// http://www.artima.com/cppsource/safebool.html typedef void (String::*StringIfHelperType)() const;
typedef void (String::*StringIfHelperType)() const; void StringIfHelper() const {
void StringIfHelper() const
{
}
public:
// constructors
// creates a copy of the initial value.
// if the initial value is null or invalid, or if memory allocation
// fails, the string will be marked as invalid (i.e. "if (s)" will
// be false).
String(const char *cstr = "");
String(const String &str);
String(const __FlashStringHelper *str) : String(reinterpret_cast<const char *>(str)) {};
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String(String &&rval);
String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base = 10);
explicit String(int, unsigned char base = 10);
explicit String(unsigned int, unsigned char base = 10);
explicit String(long, unsigned char base = 10);
explicit String(unsigned long, unsigned char base = 10);
explicit String(float, unsigned char decimalPlaces = 2);
explicit String(double, unsigned char decimalPlaces = 2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const
{
if(buffer) {
return len;
} else {
return 0;
} }
}
// creates a copy of the assigned value. if the value is null or public:
// invalid, or if the memory allocation fails, the string will be // constructors
// marked as invalid ("if (s)" will be false). // creates a copy of the initial value.
String & operator =(const String &rhs); // if the initial value is null or invalid, or if memory allocation
String & operator =(const char *cstr); // fails, the string will be marked as invalid (i.e. "if (s)" will
String & operator = (const __FlashStringHelper *str); // be false).
String(const char *cstr = "");
String(const String &str);
String(const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
String & operator =(String &&rval); String(String &&rval);
String & operator =(StringSumHelper &&rval); String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base = 10);
explicit String(int, unsigned char base = 10);
explicit String(unsigned int, unsigned char base = 10);
explicit String(long, unsigned char base = 10);
explicit String(unsigned long, unsigned char base = 10);
explicit String(float, unsigned char decimalPlaces = 2);
explicit String(double, unsigned char decimalPlaces = 2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const {
if(buffer()) {
return len();
} else {
return 0;
}
}
inline void clear(void) {
setLen(0);
}
inline bool isEmpty(void) const {
return length() == 0;
}
// creates a copy of the assigned value. if the value is null or
// invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator =(const String &rhs);
String & operator =(const char *cstr);
String & operator = (const __FlashStringHelper *str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
String & operator =(String &&rval);
String & operator =(StringSumHelper &&rval);
#endif #endif
// concatenate (works w/ built-in types) // concatenate (works w/ built-in types)
// returns true on success, false on failure (in which case, the string // returns true on success, false on failure (in which case, the string
// is left unchanged). if the argument is null or invalid, the // is left unchanged). if the argument is null or invalid, the
// concatenation is considered unsucessful. // concatenation is considered unsuccessful.
unsigned char concat(const String &str); unsigned char concat(const String &str);
unsigned char concat(const char *cstr); unsigned char concat(const char *cstr);
unsigned char concat(char c); unsigned char concat(char c);
unsigned char concat(unsigned char c); unsigned char concat(unsigned char c);
unsigned char concat(int num); unsigned char concat(int num);
unsigned char concat(unsigned int num); unsigned char concat(unsigned int num);
unsigned char concat(long num); unsigned char concat(long num);
unsigned char concat(unsigned long num); unsigned char concat(unsigned long num);
unsigned char concat(float num); unsigned char concat(float num);
unsigned char concat(double num); unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str); unsigned char concat(const __FlashStringHelper * str);
// if there's not enough memory for the concatenated value, the string // if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way) // will be left unchanged (but this isn't signalled in any way)
String & operator +=(const String &rhs) String & operator +=(const String &rhs) {
{ concat(rhs);
concat(rhs); return (*this);
return (*this); }
} String & operator +=(const char *cstr) {
String & operator +=(const char *cstr) concat(cstr);
{ return (*this);
concat(cstr); }
return (*this); String & operator +=(char c) {
} concat(c);
String & operator +=(char c) return (*this);
{ }
concat(c); String & operator +=(unsigned char num) {
return (*this); concat(num);
} return (*this);
String & operator +=(unsigned char num) }
{ String & operator +=(int num) {
concat(num); concat(num);
return (*this); return (*this);
} }
String & operator +=(int num) String & operator +=(unsigned int num) {
{ concat(num);
concat(num); return (*this);
return (*this); }
} String & operator +=(long num) {
String & operator +=(unsigned int num) concat(num);
{ return (*this);
concat(num); }
return (*this); String & operator +=(unsigned long num) {
} concat(num);
String & operator +=(long num) return (*this);
{ }
concat(num); String & operator +=(float num) {
return (*this); concat(num);
} return (*this);
String & operator +=(unsigned long num) }
{ String & operator +=(double num) {
concat(num); concat(num);
return (*this); return (*this);
} }
String & operator +=(float num) String & operator += (const __FlashStringHelper *str){
{ concat(str);
concat(num); return (*this);
return (*this); }
}
String & operator +=(double num)
{
concat(num);
return (*this);
}
String & operator += (const __FlashStringHelper *str)
{
concat(str);
return (*this);
}
friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs); friend StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr); friend StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator +(const StringSumHelper &lhs, char c); friend StringSumHelper & operator +(const StringSumHelper &lhs, char c);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num); friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, int num); friend StringSumHelper & operator +(const StringSumHelper &lhs, int num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num); friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, long num); friend StringSumHelper & operator +(const StringSumHelper &lhs, long num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num); friend StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, float num); friend StringSumHelper & operator +(const StringSumHelper &lhs, float num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, double num); friend StringSumHelper & operator +(const StringSumHelper &lhs, double num);
friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs); friend StringSumHelper & operator +(const StringSumHelper &lhs, const __FlashStringHelper *rhs);
// comparison (only works w/ Strings and "strings") // comparison (only works w/ Strings and "strings")
operator StringIfHelperType() const operator StringIfHelperType() const {
{ return buffer() ? &String::StringIfHelper : 0;
return buffer ? &String::StringIfHelper : 0; }
} int compareTo(const String &s) const;
int compareTo(const String &s) const; unsigned char equals(const String &s) const;
unsigned char equals(const String &s) const; unsigned char equals(const char *cstr) const;
unsigned char equals(const char *cstr) const; unsigned char operator ==(const String &rhs) const {
unsigned char operator ==(const String &rhs) const return equals(rhs);
{ }
return equals(rhs); unsigned char operator ==(const char *cstr) const {
} return equals(cstr);
unsigned char operator ==(const char *cstr) const }
{ unsigned char operator !=(const String &rhs) const {
return equals(cstr); return !equals(rhs);
} }
unsigned char operator !=(const String &rhs) const unsigned char operator !=(const char *cstr) const {
{ return !equals(cstr);
return !equals(rhs); }
} unsigned char operator <(const String &rhs) const;
unsigned char operator !=(const char *cstr) const unsigned char operator >(const String &rhs) const;
{ unsigned char operator <=(const String &rhs) const;
return !equals(cstr); unsigned char operator >=(const String &rhs) const;
} unsigned char equalsIgnoreCase(const String &s) const;
unsigned char operator <(const String &rhs) const; unsigned char equalsConstantTime(const String &s) const;
unsigned char operator >(const String &rhs) const; unsigned char startsWith(const String &prefix) const;
unsigned char operator <=(const String &rhs) const; unsigned char startsWith(const char *prefix) const {
unsigned char operator >=(const String &rhs) const; return this->startsWith(String(prefix));
unsigned char equalsIgnoreCase(const String &s) const; }
unsigned char equalsConstantTime(const String &s) const; unsigned char startsWith(const __FlashStringHelper *prefix) const {
unsigned char startsWith(const String &prefix) const; return this->startsWith(String(prefix));
unsigned char startsWith(const String &prefix, unsigned int offset) const; }
unsigned char endsWith(const String &suffix) const; unsigned char startsWith(const String &prefix, unsigned int offset) const;
unsigned char endsWith(const String &suffix) const;
unsigned char endsWith(const char *suffix) const {
return this->endsWith(String(suffix));
}
unsigned char endsWith(const __FlashStringHelper * suffix) const {
return this->endsWith(String(suffix));
}
// character acccess // character access
char charAt(unsigned int index) const; char charAt(unsigned int index) const;
void setCharAt(unsigned int index, char c); void setCharAt(unsigned int index, char c);
char operator [](unsigned int index) const; char operator [](unsigned int index) const;
char& operator [](unsigned int index); char& operator [](unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const; void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const {
{ getBytes((unsigned char *) buf, bufsize, index);
getBytes((unsigned char *) buf, bufsize, index); }
} const char* c_str() const { return buffer(); }
const char * c_str() const char* begin() { return wbuffer(); }
{ char* end() { return wbuffer() + length(); }
return buffer; const char* begin() const { return c_str(); }
} const char* end() const { return c_str() + length(); }
// search // search
int indexOf(char ch) const; int indexOf(char ch) const;
int indexOf(char ch, unsigned int fromIndex) const; int indexOf(char ch, unsigned int fromIndex) const;
int indexOf(const String &str) const; int indexOf(const String &str) const;
int indexOf(const String &str, unsigned int fromIndex) const; int indexOf(const String &str, unsigned int fromIndex) const;
int lastIndexOf(char ch) const; int lastIndexOf(char ch) const;
int lastIndexOf(char ch, unsigned int fromIndex) const; int lastIndexOf(char ch, unsigned int fromIndex) const;
int lastIndexOf(const String &str) const; int lastIndexOf(const String &str) const;
int lastIndexOf(const String &str, unsigned int fromIndex) const; int lastIndexOf(const String &str, unsigned int fromIndex) const;
String substring(unsigned int beginIndex) const String substring(unsigned int beginIndex) const {
{ return substring(beginIndex, len());
return substring(beginIndex, len); }
} ;
; String substring(unsigned int beginIndex, unsigned int endIndex) const;
String substring(unsigned int beginIndex, unsigned int endIndex) const;
// modification // modification
void replace(char find, char replace); void replace(char find, char replace);
void replace(const String& find, const String& replace); void replace(const String &find, const String &replace);
void remove(unsigned int index); void replace(const char *find, const String &replace) {
void remove(unsigned int index, unsigned int count); this->replace(String(find), replace);
void toLowerCase(void); }
void toUpperCase(void); void replace(const __FlashStringHelper *find, const String &replace) {
void trim(void); this->replace(String(find), replace);
}
void replace(const char *find, const char *replace) {
this->replace(String(find), String(replace));
}
void replace(const __FlashStringHelper *find, const char *replace) {
this->replace(String(find), String(replace));
}
void replace(const __FlashStringHelper *find, const __FlashStringHelper *replace) {
this->replace(String(find), String(replace));
}
void remove(unsigned int index);
void remove(unsigned int index, unsigned int count);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
// parsing/conversion // parsing/conversion
long toInt(void) const; long toInt(void) const;
float toFloat(void) const; float toFloat(void) const;
double toDouble(void) const; double toDouble(void) const;
protected: protected:
char *buffer; // the actual char array // Contains the string info when we're not in SSO mode
unsigned int capacity; // the array length minus one (for the '\0') struct _ptr {
unsigned int len; // the String length (not counting the '\0') char * buff;
protected: uint16_t cap;
void init(void); uint16_t len;
void invalidate(void); };
unsigned char changeBuffer(unsigned int maxStrLen); // This allows strings up up to 11 (10 + \0 termination) without any extra space.
unsigned char concat(const char *cstr, unsigned int length); enum { SSOSIZE = sizeof(struct _ptr) + 4 - 1 }; // Characters to allocate space for SSO, must be 12 or more
struct _sso {
char buff[SSOSIZE];
unsigned char len : 7; // Ensure only one byte is allocated by GCC for the bitfields
unsigned char isSSO : 1;
} __attribute__((packed)); // Ensure that GCC doesn't expand the flag byte to a 32-bit word for alignment issues
enum { CAPACITY_MAX = 65535 }; // If typeof(cap) changed from uint16_t, be sure to update this enum to the max value storable in the type
union {
struct _ptr ptr;
struct _sso sso;
};
// Accessor functions
inline bool isSSO() const { return sso.isSSO; }
inline unsigned int len() const { return isSSO() ? sso.len : ptr.len; }
inline unsigned int capacity() const { return isSSO() ? (unsigned int)SSOSIZE - 1 : ptr.cap; } // Size of max string not including terminal NUL
inline void setSSO(bool set) { sso.isSSO = set; }
inline void setLen(int len) { if (isSSO()) sso.len = len; else ptr.len = len; }
inline void setCapacity(int cap) { if (!isSSO()) ptr.cap = cap; }
inline void setBuffer(char *buff) { if (!isSSO()) ptr.buff = buff; }
// Buffer accessor functions
inline const char *buffer() const { return (const char *)(isSSO() ? sso.buff : ptr.buff); }
inline char *wbuffer() const { return isSSO() ? const_cast<char *>(sso.buff) : ptr.buff; } // Writable version of buffer
// copy and move protected:
String & copy(const char *cstr, unsigned int length); void init(void);
String & copy(const __FlashStringHelper *pstr, unsigned int length); void invalidate(void);
unsigned char changeBuffer(unsigned int maxStrLen);
unsigned char concat(const char *cstr, unsigned int length);
// copy and move
String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length);
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
void move(String &rhs); void move(String &rhs);
#endif #endif
}; };
class StringSumHelper: public String class StringSumHelper: public String {
{ public:
public: StringSumHelper(const String &s) :
StringSumHelper(const String &s) : String(s) {
String(s) }
{ StringSumHelper(const char *p) :
} String(p) {
StringSumHelper(const char *p) : }
String(p) StringSumHelper(char c) :
{ String(c) {
} }
StringSumHelper(char c) : StringSumHelper(unsigned char num) :
String(c) String(num) {
{ }
} StringSumHelper(int num) :
StringSumHelper(unsigned char num) : String(num) {
String(num) }
{ StringSumHelper(unsigned int num) :
} String(num) {
StringSumHelper(int num) : }
String(num) StringSumHelper(long num) :
{ String(num) {
} }
StringSumHelper(unsigned int num) : StringSumHelper(unsigned long num) :
String(num) String(num) {
{ }
} StringSumHelper(float num) :
StringSumHelper(long num) : String(num) {
String(num) }
{ StringSumHelper(double num) :
} String(num) {
StringSumHelper(unsigned long num) : }
String(num)
{
}
StringSumHelper(float num) :
String(num)
{
}
StringSumHelper(double num) :
String(num)
{
}
}; };
extern const String emptyString;
#endif // __cplusplus #endif // __cplusplus
#endif // String_class_h #endif // String_class_h

View File

@ -31,11 +31,11 @@ extern "C" {
/** /**
* convert input data to base64 * convert input data to base64
* @param data uint8_t * * @param data const uint8_t *
* @param length size_t * @param length size_t
* @return String * @return String
*/ */
String base64::encode(uint8_t * data, size_t length) String base64::encode(const uint8_t * data, size_t length)
{ {
size_t size = base64_encode_expected_len(length) + 1; size_t size = base64_encode_expected_len(length) + 1;
char * buffer = (char *) malloc(size); char * buffer = (char *) malloc(size);
@ -54,10 +54,10 @@ String base64::encode(uint8_t * data, size_t length)
/** /**
* convert input data to base64 * convert input data to base64
* @param text String * @param text const String&
* @return String * @return String
*/ */
String base64::encode(String text) String base64::encode(const String& text)
{ {
return base64::encode((uint8_t *) text.c_str(), text.length()); return base64::encode((uint8_t *) text.c_str(), text.length());
} }

View File

@ -4,8 +4,8 @@
class base64 class base64
{ {
public: public:
static String encode(uint8_t * data, size_t length); static String encode(const uint8_t * data, size_t length);
static String encode(String text); static String encode(const String& text);
private: private:
}; };

View File

@ -15,103 +15,72 @@
#include "esp32-hal-adc.h" #include "esp32-hal-adc.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "soc/rtc_io_reg.h" #include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h" #include "soc/sens_reg.h"
#include "driver/adc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp_adc_cal.h"
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#define DEFAULT_VREF 1100
static esp_adc_cal_characteristics_t *__analogCharacteristics[2] = {NULL, NULL};
static uint16_t __analogVRef = 0;
static uint8_t __analogVRefPin = 0;
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "esp_intr.h"
#endif
static uint8_t __analogAttenuation = 3;//11db static uint8_t __analogAttenuation = 3;//11db
static uint8_t __analogWidth = 3;//12 bits static uint8_t __analogWidth = 3;//12 bits
static uint8_t __analogCycles = 8;
static uint8_t __analogSamples = 0;//1 sample
static uint8_t __analogClockDiv = 1; static uint8_t __analogClockDiv = 1;
// Width of returned answer () void __analogSetClockDiv(uint8_t clockDiv){
static uint8_t __analogReturnedWidth = 12; if(!clockDiv){
clockDiv = 1;
}
__analogClockDiv = clockDiv;
adc_set_clk_div(__analogClockDiv);
}
void __analogSetAttenuation(adc_attenuation_t attenuation)
{
__analogAttenuation = attenuation & 3;
}
#if CONFIG_IDF_TARGET_ESP32
void __analogSetWidth(uint8_t bits){ void __analogSetWidth(uint8_t bits){
if(bits < 9){ if(bits < 9){
bits = 9; bits = 9;
} else if(bits > 12){ } else if(bits > 12){
bits = 12; bits = 12;
} }
__analogReturnedWidth = bits;
__analogWidth = bits - 9; __analogWidth = bits - 9;
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S); adc1_config_width(__analogWidth);
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S);
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, __analogWidth, SENS_SAR2_BIT_WIDTH_S);
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT, __analogWidth, SENS_SAR2_SAMPLE_BIT_S);
} }
#endif
void __analogSetCycles(uint8_t cycles){ void __analogInit(){
__analogCycles = cycles;
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_CYCLE, __analogCycles, SENS_SAR1_SAMPLE_CYCLE_S);
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_CYCLE, __analogCycles, SENS_SAR2_SAMPLE_CYCLE_S);
}
void __analogSetSamples(uint8_t samples){
if(!samples){
return;
}
__analogSamples = samples - 1;
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_NUM, __analogSamples, SENS_SAR1_SAMPLE_NUM_S);
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_NUM, __analogSamples, SENS_SAR2_SAMPLE_NUM_S);
}
void __analogSetClockDiv(uint8_t clockDiv){
if(!clockDiv){
return;
}
__analogClockDiv = clockDiv;
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_CLK_DIV, __analogClockDiv, SENS_SAR1_CLK_DIV_S);
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_CLK_DIV, __analogClockDiv, SENS_SAR2_CLK_DIV_S);
}
void __analogSetAttenuation(adc_attenuation_t attenuation)
{
__analogAttenuation = attenuation & 3;
uint32_t att_data = 0;
int i = 10;
while(i--){
att_data |= __analogAttenuation << (i * 2);
}
WRITE_PERI_REG(SENS_SAR_ATTEN1_REG, att_data & 0xFFFF);//ADC1 has 8 channels
WRITE_PERI_REG(SENS_SAR_ATTEN2_REG, att_data);
}
void IRAM_ATTR __analogInit(){
static bool initialized = false; static bool initialized = false;
if(initialized){ if(initialized){
return; return;
} }
__analogSetAttenuation(__analogAttenuation);
__analogSetCycles(__analogCycles);
__analogSetSamples(__analogSamples + 1);//in samples
__analogSetClockDiv(__analogClockDiv);
__analogSetWidth(__analogWidth + 9);//in bits
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE_M); //SAR ADC1 controller (in RTC) is started by SW
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M); //SAR ADC1 pad enable bitmap is controlled by SW
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_FORCE_M); //SAR ADC2 controller (in RTC) is started by SW
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //SAR ADC2 pad enable bitmap is controlled by SW
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M); //force XPD_SAR=0, use XPD_FSM
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_CTRL_REG, 0xfff << SENS_AMP_RST_FB_FSM_S); //clear FSM
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==
initialized = true; initialized = true;
__analogSetClockDiv(__analogClockDiv);
#if CONFIG_IDF_TARGET_ESP32
__analogSetWidth(__analogWidth + 9);//in bits
#endif
} }
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
@ -120,23 +89,23 @@ void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
if(channel < 0 || attenuation > 3){ if(channel < 0 || attenuation > 3){
return ; return ;
} }
__analogInit(); if(channel > 9){
if(channel > 7){ adc2_config_channel_atten(channel - 10, attenuation);
SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, attenuation, ((channel - 10) * 2));
} else { } else {
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, attenuation, (channel * 2)); adc1_config_channel_atten(channel, attenuation);
} }
__analogInit();
} }
bool IRAM_ATTR __adcAttachPin(uint8_t pin){ bool __adcAttachPin(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin); int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){ if(channel < 0){
return false;//not adc pin log_e("Pin %u is not ADC pin!", pin);
return false;
} }
int8_t pad = digitalPinToTouchChannel(pin); int8_t pad = digitalPinToTouchChannel(pin);
if(pad >= 0){ if(pad >= 0){
#if CONFIG_IDF_TARGET_ESP32
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG); uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
if(touch & (1 << pad)){ if(touch & (1 << pad)){
touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S))
@ -144,6 +113,7 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S))); | (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch); WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
} }
#endif
} else if(pin == 25){ } else if(pin == 25){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1 CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
} else if(pin == 26){ } else if(pin == 26){
@ -151,86 +121,120 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){
} }
pinMode(pin, ANALOG); pinMode(pin, ANALOG);
__analogSetPinAttenuation(pin, __analogAttenuation);
__analogInit();
return true; return true;
} }
bool IRAM_ATTR __adcStart(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
return false;//not adc pin
}
if(channel > 9){
channel -= 10;
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
} else {
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
}
return true;
}
bool IRAM_ATTR __adcBusy(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
return false;//not adc pin
}
if(channel > 7){
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0);
}
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0);
}
uint16_t IRAM_ATTR __adcEnd(uint8_t pin)
{
uint16_t value = 0;
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
return 0;//not adc pin
}
if(channel > 7){
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
} else {
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
}
// Shift result if necessary
uint8_t from = __analogWidth + 9;
if (from == __analogReturnedWidth) {
return value;
}
if (from > __analogReturnedWidth) {
return value >> (from - __analogReturnedWidth);
}
return value << (__analogReturnedWidth - from);
}
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
{
if(!__adcAttachPin(pin) || !__adcStart(pin)){
return 0;
}
return __adcEnd(pin);
}
void __analogReadResolution(uint8_t bits) void __analogReadResolution(uint8_t bits)
{ {
if(!bits || bits > 16){ if(!bits || bits > 16){
return; return;
} }
#if CONFIG_IDF_TARGET_ESP32
__analogSetWidth(bits); // hadware from 9 to 12 __analogSetWidth(bits); // hadware from 9 to 12
__analogReturnedWidth = bits; // software from 1 to 16 #endif
}
uint16_t __analogRead(uint8_t pin)
{
int8_t channel = digitalPinToAnalogChannel(pin);
int value = 0;
esp_err_t r = ESP_OK;
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return value;
}
__adcAttachPin(pin);
if(channel > 9){
channel -= 10;
r = adc2_get_raw( channel, __analogWidth, &value);
if ( r == ESP_OK ) {
return 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 ) {
log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi.", pin, esp_err_to_name(r));
} else {
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
}
} else {
return adc1_get_raw(channel);
}
return value;
}
uint32_t __analogReadMilliVolts(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return 0;
}
#if CONFIG_IDF_TARGET_ESP32
if(!__analogVRef){
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
log_d("eFuse Two Point: Supported");
__analogVRef = DEFAULT_VREF;
}
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
log_d("eFuse Vref: Supported");
__analogVRef = DEFAULT_VREF;
}
if(!__analogVRef){
__analogVRef = DEFAULT_VREF;
if(__analogVRefPin){
esp_adc_cal_characteristics_t chars;
if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){
__analogVRef = __analogRead(__analogVRefPin);
esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, &chars);
__analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, &chars);
log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef);
}
}
}
}
uint8_t unit = 1;
if(channel > 9){
unit = 2;
}
uint16_t adc_reading = __analogRead(pin);
if(__analogCharacteristics[unit - 1] == NULL){
__analogCharacteristics[unit - 1] = calloc(1, sizeof(esp_adc_cal_characteristics_t));
if(__analogCharacteristics[unit - 1] == NULL){
return 0;
}
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, __analogAttenuation, __analogWidth, __analogVRef, __analogCharacteristics[unit - 1]);
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
log_i("ADC%u: Characterized using Two Point Value: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
log_i("ADC%u: Characterized using eFuse Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
} else if(__analogVRef != DEFAULT_VREF){
log_i("ADC%u: Characterized using Vref to GPIO%u: %u\n", unit, __analogVRefPin, __analogCharacteristics[unit - 1]->vref);
} else {
log_i("ADC%u: Characterized using Default Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
}
}
return esp_adc_cal_raw_to_voltage(adc_reading, __analogCharacteristics[unit - 1]);
#else
uint16_t adc_reading = __analogRead(pin);
uint16_t max_reading = 8191;
uint16_t max_mv = 1100;
switch(__analogAttenuation){
case 3: max_mv = 3900; break;
case 2: max_mv = 2200; break;
case 1: max_mv = 1500; break;
default: break;
}
return (adc_reading * max_mv) / max_reading;
#endif
}
#if CONFIG_IDF_TARGET_ESP32
void __analogSetVRefPin(uint8_t pin){
if(pin <25 || pin > 27){
pin = 0;
}
__analogVRefPin = pin;
} }
int __hallRead() //hall sensor without LNA int __hallRead() //hall sensor without LNA
@ -256,18 +260,20 @@ int __hallRead() //hall sensor without LNA
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE); CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);
return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0); return (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
} }
#endif
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead"))); extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
extern uint32_t analogReadMilliVolts(uint8_t pin) __attribute__ ((weak, alias("__analogReadMilliVolts")));
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution"))); extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles")));
extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples")));
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv"))); extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation"))); extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation"))); extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin"))); extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart")));
extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy"))); #if CONFIG_IDF_TARGET_ESP32
extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd"))); extern void analogSetVRefPin(uint8_t pin) __attribute__ ((weak, alias("__analogSetVRefPin")));
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
#endif

View File

@ -38,6 +38,11 @@ typedef enum {
* */ * */
uint16_t analogRead(uint8_t pin); uint16_t analogRead(uint8_t pin);
/*
* Get MilliVolts value for pin
* */
uint32_t analogReadMilliVolts(uint8_t pin);
/* /*
* Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096). * Set the resolution of analogRead return values. Default is 12 bits (range from 0 to 4096).
* If between 9 and 12, it will equal the set hardware resolution, else value will be shifted. * If between 9 and 12, it will equal the set hardware resolution, else value will be shifted.
@ -47,31 +52,6 @@ uint16_t analogRead(uint8_t pin);
*/ */
void analogReadResolution(uint8_t bits); void analogReadResolution(uint8_t bits);
/*
* Sets the sample bits and read resolution
* Default is 12bit (0 - 4095)
* Range is 9 - 12
* */
void analogSetWidth(uint8_t bits);
/*
* Set number of cycles per sample
* Default is 8 and seems to do well
* Range is 1 - 255
* */
void analogSetCycles(uint8_t cycles);
/*
* Set number of samples in the range.
* Default is 1
* Range is 1 - 255
* This setting splits the range into
* "samples" pieces, which could look
* like the sensitivity has been multiplied
* that many times
* */
void analogSetSamples(uint8_t samples);
/* /*
* Set the divider for the ADC clock. * Set the divider for the ADC clock.
* Default is 1 * Default is 1
@ -91,40 +71,30 @@ void analogSetAttenuation(adc_attenuation_t attenuation);
* */ * */
void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation); void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
/*
* Get value for HALL sensor (without LNA)
* connected to pins 36(SVP) and 39(SVN)
* */
int hallRead();
/*
* Non-Blocking API (almost)
*
* Note: ADC conversion can run only for single pin at a time.
* That means that if you want to run ADC on two pins on the same bus,
* you need to run them one after another. Probably the best use would be
* to start conversion on both buses in parallel.
* */
/* /*
* Attach pin to ADC (will also clear any other analog mode that could be on) * Attach pin to ADC (will also clear any other analog mode that could be on)
* */ * */
bool adcAttachPin(uint8_t pin); bool adcAttachPin(uint8_t pin);
#if CONFIG_IDF_TARGET_ESP32
/* /*
* Start ADC conversion on attached pin's bus * Sets the sample bits and read resolution
* Default is 12bit (0 - 4095)
* Range is 9 - 12
* */ * */
bool adcStart(uint8_t pin); void analogSetWidth(uint8_t bits);
/* /*
* Check if conversion on the pin's ADC bus is currently running * Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27)
* */ * */
bool adcBusy(uint8_t pin); void analogSetVRefPin(uint8_t pin);
/* /*
* Get the result of the conversion (will wait if it have not finished) * Get value for HALL sensor (without LNA)
* connected to pins 36(SVP) and 39(SVN)
* */ * */
uint16_t adcEnd(uint8_t pin); int hallRead();
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -65,6 +65,14 @@ bool btStop(){
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED); while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED);
} }
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){ if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
if (esp_bt_controller_deinit()) {
log_e("BT deint failed");
return false;
}
vTaskDelay(1);
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_IDLE) {
return false;
}
return true; return true;
} }
log_e("BT Stop failed"); log_e("BT Stop failed");

View File

@ -21,18 +21,31 @@
#include "esp_log.h" #include "esp_log.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "rom/rtc.h"
#include "soc/apb_ctrl_reg.h" #include "soc/apb_ctrl_reg.h"
#include "soc/efuse_reg.h"
#include "esp32-hal.h" #include "esp32-hal.h"
#include "esp32-hal-cpu.h" #include "esp32-hal-cpu.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/rtc.h"
#endif
typedef struct apb_change_cb_s { typedef struct apb_change_cb_s {
struct apb_change_cb_s * prev;
struct apb_change_cb_s * next; struct apb_change_cb_s * next;
void * arg; void * arg;
apb_change_cb_t cb; apb_change_cb_t cb;
} apb_change_t; } apb_change_t;
const uint32_t MHZ = 1000000;
static apb_change_t * apb_change_callbacks = NULL; static apb_change_t * apb_change_callbacks = NULL;
static xSemaphoreHandle apb_change_lock = NULL; static xSemaphoreHandle apb_change_lock = NULL;
@ -52,9 +65,19 @@ static void triggerApbChangeCallback(apb_change_ev_t ev_type, uint32_t old_apb,
initApbChangeCallback(); initApbChangeCallback();
xSemaphoreTake(apb_change_lock, portMAX_DELAY); xSemaphoreTake(apb_change_lock, portMAX_DELAY);
apb_change_t * r = apb_change_callbacks; apb_change_t * r = apb_change_callbacks;
while(r != NULL){ if( r != NULL ){
r->cb(r->arg, ev_type, old_apb, new_apb); if(ev_type == APB_BEFORE_CHANGE )
r=r->next; while(r != NULL){
r->cb(r->arg, ev_type, old_apb, new_apb);
r=r->next;
}
else { // run backwards through chain
while(r->next != NULL) r = r->next; // find first added
while( r != NULL){
r->cb(r->arg, ev_type, old_apb, new_apb);
r=r->prev;
}
}
} }
xSemaphoreGive(apb_change_lock); xSemaphoreGive(apb_change_lock);
} }
@ -67,6 +90,7 @@ bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
return false; return false;
} }
c->next = NULL; c->next = NULL;
c->prev = NULL;
c->arg = arg; c->arg = arg;
c->cb = cb; c->cb = cb;
xSemaphoreTake(apb_change_lock, portMAX_DELAY); xSemaphoreTake(apb_change_lock, portMAX_DELAY);
@ -74,18 +98,20 @@ bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
apb_change_callbacks = c; apb_change_callbacks = c;
} else { } else {
apb_change_t * r = apb_change_callbacks; apb_change_t * r = apb_change_callbacks;
if(r->cb != cb || r->arg != arg){ // look for duplicate callbacks
while(r->next){ while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
r = r->next; if (r) {
if(r->cb == cb && r->arg == arg){ log_e("duplicate func=%08X arg=%08X",c->cb,c->arg);
free(c); free(c);
goto unlock_and_exit; xSemaphoreGive(apb_change_lock);
} return false;
} }
r->next = c; else {
c->next = apb_change_callbacks;
apb_change_callbacks-> prev = c;
apb_change_callbacks = c;
} }
} }
unlock_and_exit:
xSemaphoreGive(apb_change_lock); xSemaphoreGive(apb_change_lock);
return true; return true;
} }
@ -94,24 +120,21 @@ bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
initApbChangeCallback(); initApbChangeCallback();
xSemaphoreTake(apb_change_lock, portMAX_DELAY); xSemaphoreTake(apb_change_lock, portMAX_DELAY);
apb_change_t * r = apb_change_callbacks; apb_change_t * r = apb_change_callbacks;
if(r == NULL){ // look for matching callback
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
if ( r == NULL ) {
log_e("not found func=%08X arg=%08X",cb,arg);
xSemaphoreGive(apb_change_lock); xSemaphoreGive(apb_change_lock);
return false; return false;
} }
if(r->cb == cb && r->arg == arg){ else {
apb_change_callbacks = r->next; // patch links
if(r->prev) r->prev->next = r->next;
else { // this is first link
apb_change_callbacks = r->next;
}
if(r->next) r->next->prev = r->prev;
free(r); free(r);
} else {
while(r->next && (r->next->cb != cb || r->next->arg != arg)){
r = r->next;
}
if(r->next == NULL || r->next->cb != cb || r->next->arg != arg){
xSemaphoreGive(apb_change_lock);
return false;
}
apb_change_t * c = r->next;
r->next = c->next;
free(c);
} }
xSemaphoreGive(apb_change_lock); xSemaphoreGive(apb_change_lock);
return true; return true;
@ -131,6 +154,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
uint32_t capb, apb; uint32_t capb, apb;
//Get XTAL Frequency and calculate min CPU MHz //Get XTAL Frequency and calculate min CPU MHz
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get(); rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
#if CONFIG_IDF_TARGET_ESP32
if(xtal > RTC_XTAL_FREQ_AUTO){ if(xtal > RTC_XTAL_FREQ_AUTO){
if(xtal < RTC_XTAL_FREQ_40M) { if(xtal < RTC_XTAL_FREQ_40M) {
if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2)){ if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2)){
@ -142,6 +166,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
return false; return false;
} }
} }
#endif
if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){ if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){
if(xtal >= RTC_XTAL_FREQ_40M){ if(xtal >= RTC_XTAL_FREQ_40M){
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4); log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
@ -150,6 +175,17 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
} }
return false; return false;
} }
#if CONFIG_IDF_TARGET_ESP32
//check if cpu supports the frequency
if(cpu_freq_mhz == 240){
//Check if ESP32 is rated for a CPU frequency of 160MHz only
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
log_e("Can not switch to 240 MHz! Chip CPU frequency rated for 160MHz.");
cpu_freq_mhz = 160;
}
}
#endif
//Get current CPU clock configuration //Get current CPU clock configuration
rtc_clk_cpu_freq_get_config(&cconf); rtc_clk_cpu_freq_get_config(&cconf);
//return if frequency has not changed //return if frequency has not changed
@ -176,7 +212,7 @@ bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz) //Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
//if(conf.freq_mhz < 80){ //if(conf.freq_mhz < 80){
// ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1; // ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1;
//} // }
//Update APB Freq REG //Update APB Freq REG
rtc_clk_apb_freq_update(apb); rtc_clk_apb_freq_update(apb);
//Update esp_timer divisor //Update esp_timer divisor

View File

@ -12,43 +12,45 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "esp32-hal-dac.h" #include "esp32-hal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "soc/rtc_io_reg.h" #include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_periph.h"
#include "soc/sens_reg.h" #include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/dac.h"
void IRAM_ATTR __dacWrite(uint8_t pin, uint8_t value) #if CONFIG_IDF_TARGET_ESP32
#define DAC1 25
#define DAC2 26
#elif CONFIG_IDF_TARGET_ESP32S2
#define DAC1 17
#define DAC2 18
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
void ARDUINO_ISR_ATTR __dacWrite(uint8_t pin, uint8_t value)
{ {
if(pin < 25 || pin > 26){ if(pin < DAC1 || pin > DAC2){
return;//not dac pin return;//not dac pin
} }
pinMode(pin, ANALOG); pinMode(pin, ANALOG);
uint8_t channel = pin - 25; uint8_t channel = pin - DAC1;
#if CONFIG_IDF_TARGET_ESP32
//Disable Tone
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN); CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
#elif CONFIG_IDF_TARGET_ESP32S2
if (channel) { SENS.sar_dac_ctrl1.dac_clkgate_en = 1;
//Disable Channel Tone #endif
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M); RTCIO.pad_dac[channel].dac_xpd_force = 1;
//Set the Dac value RTCIO.pad_dac[channel].xpd_dac = 1;
SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, value, RTC_IO_PDAC2_DAC_S); //dac_output if (channel == 0) {
//Channel output enable SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE); } else if (channel == 1) {
} else { SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
//Disable Channel Tone
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
//Set the Dac value
SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, value, RTC_IO_PDAC1_DAC_S); //dac_output
//Channel output enable
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
} }
RTCIO.pad_dac[channel].dac = value;
} }
extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite"))); extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));

View File

@ -13,20 +13,45 @@
// limitations under the License. // limitations under the License.
#include "esp32-hal-gpio.h" #include "esp32-hal-gpio.h"
#include "pins_arduino.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "rom/gpio.h"
#include "soc/gpio_reg.h" #include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/gpio_struct.h" #include "soc/gpio_struct.h"
#include "soc/rtc_io_reg.h" #include "soc/rtc_io_reg.h"
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; #include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/gpio.h"
#include "esp_intr_alloc.h"
#define GPIO_FUNC 2
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/gpio.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#define GPIO_FUNC 1
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "rom/gpio.h"
#include "esp_intr.h"
#endif
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={ #if CONFIG_IDF_TARGET_ESP32
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26};
#elif CONFIG_IDF_TARGET_ESP32S2
const int8_t esp32_adc2gpio[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
#endif
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT]={
#if CONFIG_IDF_TARGET_ESP32
{0x44, 11, 11, 1}, {0x44, 11, 11, 1},
{0x88, -1, -1, -1}, {0x88, -1, -1, -1},
{0x40, 12, 12, 2}, {0x40, 12, 12, 2},
@ -59,14 +84,64 @@ const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={
{0, -1, -1, -1}, {0, -1, -1, -1},
{0, -1, -1, -1}, {0, -1, -1, -1},
{0, -1, -1, -1}, {0, -1, -1, -1},
{0x1c, 9, 4, 9}, {0x1c, 9, 4, 8},
{0x20, 8, 5, 8}, {0x20, 8, 5, 9},
{0x14, 4, 6, -1}, {0x14, 4, 6, -1},
{0x18, 5, 7, -1}, {0x18, 5, 7, -1},
{0x04, 0, 0, -1}, {0x04, 0, 0, -1},
{0x08, 1, 1, -1}, {0x08, 1, 1, -1},
{0x0c, 2, 2, -1}, {0x0c, 2, 2, -1},
{0x10, 3, 3, -1} {0x10, 3, 3, -1}
#elif CONFIG_IDF_TARGET_ESP32S2
{0x04, 0, -1, -1},
{0x08, 1, 0, 1},
{0x0c, 2, 1, 2},
{0x10, 3, 2, 3},
{0x14, 4, 3, 4},
{0x18, 5, 4, 5},
{0x1c, 6, 5, 6},
{0x20, 7, 6, 7},
{0x24, 8, 7, 8},
{0x28, 9, 8, 9},//FSPI_HD
{0x2c, 10, 9, 10},//FSPI_CS0 / FSPI_D4
{0x30, 11, 10, 11},//FSPI_D / FSPI_D5
{0x34, 12, 11, 12},//FSPI_CLK / FSPI_D6
{0x38, 13, 12, 13},//FSPI_Q / FSPI_D7
{0x3c, 14, 13, 14},//FSPI_WP / FSPI_DQS
{0x40, 15, 14, -1},//32K+ / RTS0
{0x44, 16, 15, -1},//32K- / CTS0
{0x48, 17, 16, -1},//DAC1 / TXD1
{0x4c, 18, 17, -1},//DAC2 / RXD1
{0x50, 19, 18, -1},//USB D- / RTS1
{0x54, 20, 19, -1},//USB D+ / CTS1
{0x58, 21, -1, -1},//SDA?
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{ 0, -1, -1, -1},//UNAVAILABLE
{0x6c, -1, -1, -1},//RESERVED SPI_CS1
{0x70, -1, -1, -1},//RESERVED SPI_HD
{0x74, -1, -1, -1},//RESERVED SPI_WP
{0x78, -1, -1, -1},//RESERVED SPI_CS0
{0x7c, -1, -1, -1},//RESERVED SPI_CLK
{0x80, -1, -1, -1},//RESERVED SPI_Q
{0x84, -1, -1, -1},//RESERVED SPI_D
{0x88, -1, -1, -1},//FSPI_HD
{0x8c, -1, -1, -1},//FSPI_CS0
{0x90, -1, -1, -1},//FSPI_D
{0x94, -1, -1, -1},//FSPI_CLK
{0x98, -1, -1, -1},//FSPI_Q
{0x9c, -1, -1, -1},//FSPI_WP
{0xa0, -1, -1, -1},//MTCK
{0xa4, -1, -1, -1},//MTDO
{0xa8, -1, -1, -1},//MTDI
{0xac, -1, -1, -1},//MTMS
{0xb0, -1, -1, -1},//TXD0
{0xb4, -1, -1, -1},//RXD0
{0xb8, -1, -1, -1},//SCL?
{0xbc, -1, -1, -1},//INPUT ONLY
{0, -1, -1, -1}
#endif
}; };
typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtr)(void);
@ -76,56 +151,57 @@ typedef struct {
void* arg; void* arg;
bool functional; bool functional;
} InterruptHandle_t; } InterruptHandle_t;
static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,}; static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,};
#include "driver/rtc_io.h" #include "driver/rtc_io.h"
extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode) extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
{ {
if(!digitalPinIsValid(pin)) { if(!digitalPinIsValid(pin)) {
return; return;
} }
uint32_t rtc_reg = rtc_gpio_desc[pin].reg; int8_t rtc_io = esp32_gpioMux[pin].rtc;
uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
if(mode == ANALOG) { if(mode == ANALOG) {
if(!rtc_reg) { if(!rtc_reg) {
return;//not rtc pin return;//not rtc pin
} }
//lock rtc #if CONFIG_IDF_TARGET_ESP32S2
uint32_t reg_val = ESP_REG(rtc_reg); SENS.sar_io_mux_conf.iomux_clk_gate_en = 1;
if(reg_val & rtc_gpio_desc[pin].mux){ #endif
return;//already in adc mode SET_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, (rtc_io_desc[rtc_io].mux));
SET_PERI_REG_BITS(rtc_io_desc[rtc_io].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, 0, rtc_io_desc[rtc_io].func);
RTCIO.pin[rtc_io].pad_driver = 0;//OD = 1
RTCIO.enable_w1tc.w1tc = (1U << rtc_io);
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].ie);
if (rtc_io_desc[rtc_io].pullup) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pullup);
} }
reg_val &= ~( if (rtc_io_desc[rtc_io].pulldown) {
(RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func) CLEAR_PERI_REG_MASK(rtc_io_desc[rtc_io].reg, rtc_io_desc[rtc_io].pulldown);
|rtc_gpio_desc[pin].ie }
|rtc_gpio_desc[pin].pullup ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)GPIO_FUNC << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
|rtc_gpio_desc[pin].pulldown);
ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S));
ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux;
//unlock rtc
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
return; return;
} }
//RTC pins PULL settings //RTC pins PULL settings
if(rtc_reg) { if(rtc_reg) {
//lock rtc ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
if(mode & PULLUP) { if(mode & PULLUP) {
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown); ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pullup) & ~(rtc_io_desc[rtc_io].pulldown);
} else if(mode & PULLDOWN) { } else if(mode & PULLDOWN) {
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup); ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_io_desc[rtc_io].pulldown) & ~(rtc_io_desc[rtc_io].pullup);
} else { } else {
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
} }
//unlock rtc
} }
uint32_t pinFunction = 0, pinControl = 0; uint32_t pinFunction = 0, pinControl = 0;
//lock gpio
if(mode & INPUT) { if(mode & INPUT) {
if(pin < 32) { if(pin < 32) {
GPIO.enable_w1tc = ((uint32_t)1 << pin); GPIO.enable_w1tc = ((uint32_t)1 << pin);
@ -133,9 +209,8 @@ extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
} }
} else if(mode & OUTPUT) { } else if(mode & OUTPUT) {
if(pin > 33){ if(pin >= NUM_OUPUT_PINS){
//unlock gpio return;
return;//pins above 33 can be only inputs
} else if(pin < 32) { } else if(pin < 32) {
GPIO.enable_w1ts = ((uint32_t)1 << pin); GPIO.enable_w1ts = ((uint32_t)1 << pin);
} else { } else {
@ -153,9 +228,17 @@ extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
pinFunction |= FUN_IE;//input enable but required for output as well? pinFunction |= FUN_IE;//input enable but required for output as well?
if(mode & (INPUT | OUTPUT)) { if(mode & (INPUT | OUTPUT)) {
#if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)2 << MCU_SEL_S); pinFunction |= ((uint32_t)2 << MCU_SEL_S);
#elif CONFIG_IDF_TARGET_ESP32S2
pinFunction |= ((uint32_t)1 << MCU_SEL_S);
#endif
} else if(mode == SPECIAL) { } else if(mode == SPECIAL) {
pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S); #if CONFIG_IDF_TARGET_ESP32
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:1) << MCU_SEL_S);
#elif CONFIG_IDF_TARGET_ESP32S2
pinFunction |= ((uint32_t)(((pin)==RX||(pin)==TX)?0:2) << MCU_SEL_S);
#endif
} else { } else {
pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S); pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
} }
@ -167,31 +250,30 @@ extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
} }
GPIO.pin[pin].val = pinControl; GPIO.pin[pin].val = pinControl;
//unlock gpio
} }
extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
{ {
if(val) { if(val) {
if(pin < 32) { if(pin < 32) {
GPIO.out_w1ts = ((uint32_t)1 << pin); GPIO.out_w1ts = ((uint32_t)1 << pin);
} else if(pin < 34) { } else if(pin < NUM_OUPUT_PINS) {
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
} }
} else { } else {
if(pin < 32) { if(pin < 32) {
GPIO.out_w1tc = ((uint32_t)1 << pin); GPIO.out_w1tc = ((uint32_t)1 << pin);
} else if(pin < 34) { } else if(pin < NUM_OUPUT_PINS) {
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
} }
} }
} }
extern int IRAM_ATTR __digitalRead(uint8_t pin) extern int ARDUINO_ISR_ATTR __digitalRead(uint8_t pin)
{ {
if(pin < 32) { if(pin < 32) {
return (GPIO.in >> pin) & 0x1; return (GPIO.in >> pin) & 0x1;
} else if(pin < 40) { } else if(pin < GPIO_PIN_COUNT) {
return (GPIO.in1.val >> (pin - 32)) & 0x1; return (GPIO.in1.val >> (pin - 32)) & 0x1;
} }
return 0; return 0;
@ -199,7 +281,7 @@ extern int IRAM_ATTR __digitalRead(uint8_t pin)
static intr_handle_t gpio_intr_handle = NULL; static intr_handle_t gpio_intr_handle = NULL;
static void IRAM_ATTR __onPinInterrupt() static void ARDUINO_ISR_ATTR __onPinInterrupt()
{ {
uint32_t gpio_intr_status_l=0; uint32_t gpio_intr_status_l=0;
uint32_t gpio_intr_status_h=0; uint32_t gpio_intr_status_h=0;
@ -247,7 +329,7 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
if(!interrupt_initialized) { if(!interrupt_initialized) {
interrupt_initialized = true; interrupt_initialized = true;
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle); esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __onPinInterrupt, NULL, &gpio_intr_handle);
} }
// if new attach without detach remove old info // if new attach without detach remove old info
@ -260,11 +342,15 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc,
__pinInterruptHandlers[pin].functional = functional; __pinInterruptHandlers[pin].functional = functional;
esp_intr_disable(gpio_intr_handle); esp_intr_disable(gpio_intr_handle);
#if CONFIG_IDF_TARGET_ESP32
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
#endif
GPIO.pin[pin].int_ena = 1; GPIO.pin[pin].int_ena = 1;
#if CONFIG_IDF_TARGET_ESP32
} else { //PRO_CPU } else { //PRO_CPU
GPIO.pin[pin].int_ena = 4; GPIO.pin[pin].int_ena = 4;
} }
#endif
GPIO.pin[pin].int_type = intr_type; GPIO.pin[pin].int_type = intr_type;
esp_intr_enable(gpio_intr_handle); esp_intr_enable(gpio_intr_handle);
} }

View File

@ -25,6 +25,17 @@ extern "C" {
#endif #endif
#include "esp32-hal.h" #include "esp32-hal.h"
#include "soc/soc_caps.h"
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define NUM_OUPUT_PINS 45
#define PIN_DAC1 17
#define PIN_DAC2 18
#else
#define NUM_OUPUT_PINS 34
#define PIN_DAC1 25
#define PIN_DAC2 26
#endif
#define LOW 0x0 #define LOW 0x0
#define HIGH 0x1 #define HIGH 0x1
@ -64,15 +75,15 @@ typedef struct {
int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */ int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */
} esp32_gpioMux_t; } esp32_gpioMux_t;
extern const esp32_gpioMux_t esp32_gpioMux[40]; extern const esp32_gpioMux_t esp32_gpioMux[SOC_GPIO_PIN_COUNT];
extern const int8_t esp32_adc2gpio[20]; extern const int8_t esp32_adc2gpio[20];
#define digitalPinIsValid(pin) ((pin) < 40 && esp32_gpioMux[(pin)].reg) #define digitalPinIsValid(pin) ((pin) < SOC_GPIO_PIN_COUNT && esp32_gpioMux[(pin)].reg)
#define digitalPinCanOutput(pin) ((pin) < 34 && esp32_gpioMux[(pin)].reg) #define digitalPinCanOutput(pin) ((pin) < NUM_OUPUT_PINS && esp32_gpioMux[(pin)].reg)
#define digitalPinToRtcPin(pin) (((pin) < 40)?esp32_gpioMux[(pin)].rtc:-1) #define digitalPinToRtcPin(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].rtc:-1)
#define digitalPinToAnalogChannel(pin) (((pin) < 40)?esp32_gpioMux[(pin)].adc:-1) #define digitalPinToAnalogChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].adc:-1)
#define digitalPinToTouchChannel(pin) (((pin) < 40)?esp32_gpioMux[(pin)].touch:-1) #define digitalPinToTouchChannel(pin) (((pin) < SOC_GPIO_PIN_COUNT)?esp32_gpioMux[(pin)].touch:-1)
#define digitalPinToDacChannel(pin) (((pin) == 25)?0:((pin) == 26)?1:-1) #define digitalPinToDacChannel(pin) (((pin) == PIN_DAC1)?0:((pin) == PIN_DAC2)?1:-1)
void pinMode(uint8_t pin, uint8_t mode); void pinMode(uint8_t pin, uint8_t mode);
void digitalWrite(uint8_t pin, uint8_t val); void digitalWrite(uint8_t pin, uint8_t val);

View File

@ -18,13 +18,28 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "rom/ets_sys.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "soc/i2c_reg.h" #include "soc/i2c_reg.h"
#include "soc/i2c_struct.h" #include "soc/i2c_struct.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018 #include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif
#if CONFIG_IDF_TARGET_ESP32
//#define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE) //#define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i))) //#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0)) #define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
@ -227,7 +242,7 @@ static i2c_t _i2c_bus_array[2] = {
/* Stickbreaker ISR mode debug support /* Stickbreaker ISR mode debug support
*/ */
static void IRAM_ATTR i2cDumpCmdQueue(i2c_t *i2c) static void ARDUINO_ISR_ATTR i2cDumpCmdQueue(i2c_t *i2c)
{ {
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR)&&(defined ENABLE_I2C_DEBUG_BUFFER) #if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR)&&(defined ENABLE_I2C_DEBUG_BUFFER)
static const char * const cmdName[] ={"RSTART","WRITE","READ","STOP","END"}; static const char * const cmdName[] ={"RSTART","WRITE","READ","STOP","END"};
@ -357,7 +372,7 @@ static void i2cDumpInts(uint8_t num)
#endif #endif
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER) #if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){ static void ARDUINO_ISR_ATTR i2cDumpStatus(i2c_t * i2c){
typedef union { typedef union {
struct { struct {
uint32_t ack_rec: 1; /*This register stores the value of ACK bit.*/ uint32_t ack_rec: 1; /*This register stores the value of ACK bit.*/
@ -431,7 +446,7 @@ if(i != fifoPos){// actual data
} }
#endif #endif
static void IRAM_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){ static void ARDUINO_ISR_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER) #if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
if( trigger ){ if( trigger ){
log_i("%s",locus); log_i("%s",locus);
@ -478,7 +493,7 @@ static void i2cApbChangeCallback(void * arg, apb_change_ev_t ev_type, uint32_t o
} }
/* End of CPU Clock change Support /* End of CPU Clock change Support
*/ */
static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check) static void ARDUINO_ISR_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
{ {
I2C_COMMAND_t cmd; I2C_COMMAND_t cmd;
cmd.val=0; cmd.val=0;
@ -491,7 +506,7 @@ static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uin
} }
static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS) static void ARDUINO_ISR_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
{ {
/* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs /* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs
*/ */
@ -649,7 +664,7 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
} }
} }
static void IRAM_ATTR fillTxFifo(i2c_t * i2c) static void ARDUINO_ISR_ATTR fillTxFifo(i2c_t * i2c)
{ {
/* /*
12/01/2017 The Fifo's are independent, 32 bytes of tx and 32 bytes of Rx. 12/01/2017 The Fifo's are independent, 32 bytes of tx and 32 bytes of Rx.
@ -741,7 +756,7 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
} }
static void IRAM_ATTR emptyRxFifo(i2c_t * i2c) static void ARDUINO_ISR_ATTR emptyRxFifo(i2c_t * i2c)
{ {
uint32_t d, cnt=0, moveCnt; uint32_t d, cnt=0, moveCnt;
@ -800,7 +815,7 @@ static void IRAM_ATTR emptyRxFifo(i2c_t * i2c)
#endif #endif
} }
static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal) static void ARDUINO_ISR_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal)
{ {
switch(eventCode) { switch(eventCode) {
@ -845,7 +860,7 @@ static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal
} }
static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c) static void ARDUINO_ISR_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
{ {
/* i2c_update_error_byte_cnt 07/18/2018 /* i2c_update_error_byte_cnt 07/18/2018
Only called after an error has occurred, so, most of the time this function is never used. Only called after an error has occurred, so, most of the time this function is never used.
@ -892,7 +907,7 @@ static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
i2c->errorByteCnt = bc; i2c->errorByteCnt = bc;
} }
static void IRAM_ATTR i2c_isr_handler_default(void* arg) static void ARDUINO_ISR_ATTR i2c_isr_handler_default(void* arg)
{ {
i2c_t* p_i2c = (i2c_t*) arg; // recover data i2c_t* p_i2c = (i2c_t*) arg; // recover data
uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF; uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
@ -1239,7 +1254,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
if(!i2c->intr_handle) { // create ISR for either peripheral if(!i2c->intr_handle) { // create ISR for either peripheral
// log_i("create ISR %d",i2c->num); // log_i("create ISR %d",i2c->num);
uint32_t ret = 0; uint32_t ret = 0;
uint32_t flags = ESP_INTR_FLAG_IRAM | //< ISR can be called if cache is disabled uint32_t flags = ARDUINO_ISR_FLAG | //< ISR can be called if cache is disabled
ESP_INTR_FLAG_LOWMED | //< Low and medium prio interrupts. These can be handled in C. ESP_INTR_FLAG_LOWMED | //< Low and medium prio interrupts. These can be handled in C.
ESP_INTR_FLAG_SHARED; //< Reduce resource requirements, Share interrupts ESP_INTR_FLAG_SHARED; //< Reduce resource requirements, Share interrupts
@ -1270,7 +1285,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
i2c->dev->ctr.trans_start=1; // go for it i2c->dev->ctr.trans_start=1; // go for it
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
portTickType tBefore=xTaskGetTickCount(); portTickType tBefore=xTaskGetTickCount();
#endif #endif
@ -1278,7 +1293,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ticksTimeOut); uint32_t eBits = xEventGroupWaitBits(i2c->i2c_event,EVENT_DONE,pdFALSE,pdTRUE,ticksTimeOut);
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
portTickType tAfter=xTaskGetTickCount(); portTickType tAfter=xTaskGetTickCount();
#endif #endif
@ -1480,7 +1495,9 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda)
* */ * */
// 24Nov17 only supports Master Mode // 24Nov17 only supports Master Mode
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) { i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
#ifdef ENABLE_I2C_DEBUG_BUFFER
log_v("num=%d sda=%d scl=%d freq=%d",i2c_num, sda, scl, frequency); log_v("num=%d sda=%d scl=%d freq=%d",i2c_num, sda, scl, frequency);
#endif
if(i2c_num > 1) { if(i2c_num > 1) {
return NULL; return NULL;
} }
@ -1674,8 +1691,9 @@ i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
clk_speed = apb/(period*2); clk_speed = apb/(period*2);
log_d("APB Freq too fast, Increasing i2c Freq to %d Hz",clk_speed); log_d("APB Freq too fast, Increasing i2c Freq to %d Hz",clk_speed);
} }
#ifdef ENABLE_I2C_DEBUG_BUFFER
log_v("freq=%dHz",clk_speed); log_v("freq=%dHz",clk_speed);
#endif
uint32_t halfPeriod = period/2; uint32_t halfPeriod = period/2;
uint32_t quarterPeriod = period/4; uint32_t quarterPeriod = period/4;
@ -1689,14 +1707,17 @@ i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
available when a Fifo interrupt is triggered. This allows enough room in the Fifo so that available when a Fifo interrupt is triggered. This allows enough room in the Fifo so that
interrupt latency does not cause a Fifo overflow/underflow event. interrupt latency does not cause a Fifo overflow/underflow event.
*/ */
#ifdef ENABLE_I2C_DEBUG_BUFFER
log_v("cpu Freq=%dMhz, i2c Freq=%dHz",getCpuFrequencyMhz(),clk_speed); log_v("cpu Freq=%dMhz, i2c Freq=%dHz",getCpuFrequencyMhz(),clk_speed);
#endif
uint32_t fifo_delta = (INTERRUPT_CYCLE_OVERHEAD/((getCpuFrequencyMhz()*1000000 / clk_speed)*10))+1; uint32_t fifo_delta = (INTERRUPT_CYCLE_OVERHEAD/((getCpuFrequencyMhz()*1000000 / clk_speed)*10))+1;
if (fifo_delta > 24) fifo_delta=24; if (fifo_delta > 24) fifo_delta=24;
f.rx_fifo_full_thrhd = 32 - fifo_delta; f.rx_fifo_full_thrhd = 32 - fifo_delta;
f.tx_fifo_empty_thrhd = fifo_delta; f.tx_fifo_empty_thrhd = fifo_delta;
i2c->dev->fifo_conf.val = f.val; // set thresholds i2c->dev->fifo_conf.val = f.val; // set thresholds
#ifdef ENABLE_I2C_DEBUG_BUFFER
log_v("Fifo delta=%d",fifo_delta); log_v("Fifo delta=%d",fifo_delta);
#endif
//the clock num during SCL is low level //the clock num during SCL is low level
i2c->dev->scl_low_period.period = period; i2c->dev->scl_low_period.period = period;
//the clock num during SCL is high level //the clock num during SCL is high level
@ -1751,7 +1772,133 @@ uint32_t i2cGetStatus(i2c_t * i2c){
} }
else return 0; else return 0;
} }
#else
#include "driver/i2c.h"
#define ACK_CHECK_EN 1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0 /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
struct i2c_struct_t {
i2c_port_t num;
};
static i2c_t * i2c_ports[2] = {NULL, NULL};
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t clk_speed){
if(i2c_num >= 2){
return NULL;
}
i2c_t * out = NULL;
if(i2c_ports[i2c_num] == NULL){
out = (i2c_t*)malloc(sizeof(i2c_t));
if(out == NULL){
log_e("malloc failed");
return NULL;
}
out->num = (i2c_port_t)i2c_num;
i2c_ports[i2c_num] = out;
} else {
out = i2c_ports[i2c_num];
i2c_driver_delete((i2c_port_t)i2c_num);
}
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.scl_io_num = (gpio_num_t)scl;
conf.sda_io_num = (gpio_num_t)sda;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = clk_speed;
esp_err_t ret = i2c_param_config(out->num, &conf);
if (ret != ESP_OK) {
log_e("i2c_param_config failed");
free(out);
i2c_ports[i2c_num] = NULL;
return NULL;
}
ret = i2c_driver_install(out->num, conf.mode, 0, 0, 0);
if (ret != ESP_OK) {
log_e("i2c_driver_install failed");
free(out);
i2c_ports[i2c_num] = NULL;
return NULL;
}
return out;
}
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis){
esp_err_t ret = ESP_OK;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write(cmd, buff, size, ACK_CHECK_EN);
//if send stop?
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c->num, cmd, timeOutMillis / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis, uint32_t *readCount){
esp_err_t ret = ESP_OK;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
if (size > 1) {
i2c_master_read(cmd, buff, size - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, buff + size - 1, NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(i2c->num, cmd, timeOutMillis / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret == ESP_OK){
*readCount = size;
}
return ret;
}
void i2cRelease(i2c_t *i2c){
log_w("");
return;
}
i2c_err_t i2cFlush(i2c_t *i2c){
esp_err_t ret = i2c_reset_tx_fifo(i2c->num);
if(ret != ESP_OK){
return ret;
}
return i2c_reset_rx_fifo(i2c->num);
}
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed){
log_w("");
return ESP_OK;
}
uint32_t i2cGetFrequency(i2c_t * i2c){
log_w("");
return 0;
}
uint32_t i2cGetStatus(i2c_t * i2c){
log_w("");
return 0;
}
//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){
return ESP_FAIL;
}
i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl){
return ESP_FAIL;
}
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda){
return ESP_FAIL;
}
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda){
return ESP_FAIL;
}
#endif /* CONFIG_IDF_TARGET_ESP32 */
/* todo /* todo
22JUL18 22JUL18

View File

@ -16,19 +16,34 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "esp32-hal-matrix.h" #include "esp32-hal-matrix.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/ledc_reg.h" #include "soc/ledc_reg.h"
#include "soc/ledc_struct.h" #include "soc/ledc_struct.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#define LAST_CHAN (15)
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#define LAST_CHAN (7)
#define LEDC_DIV_NUM_HSTIMER0_V LEDC_CLK_DIV_LSTIMER0_V
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif
#if CONFIG_DISABLE_HAL_LOCKS #if CONFIG_DISABLE_HAL_LOCKS
#define LEDC_MUTEX_LOCK() #define LEDC_MUTEX_LOCK()
#define LEDC_MUTEX_UNLOCK() #define LEDC_MUTEX_UNLOCK()
#else #else
#define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS) #define LEDC_MUTEX_LOCK() do {} while (xSemaphoreTake(_ledc_sys_lock, portMAX_DELAY) != pdPASS)
#define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock) #define LEDC_MUTEX_UNLOCK() xSemaphoreGive(_ledc_sys_lock)
xSemaphoreHandle _ledc_sys_lock; xSemaphoreHandle _ledc_sys_lock = NULL;
#endif #endif
/* /*
@ -55,27 +70,35 @@ xSemaphoreHandle _ledc_sys_lock;
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){ if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){
uint32_t iarg = (uint32_t)arg; uint16_t iarg = *(uint16_t*)arg;
uint8_t chan = iarg; uint8_t chan = 0;
uint8_t group=(chan/8), timer=((chan/2)%4);
old_apb /= 1000000; old_apb /= 1000000;
new_apb /= 1000000; new_apb /= 1000000;
if(LEDC_TIMER(group, timer).conf.tick_sel){ while(iarg){ // run though all active channels, adjusting timing configurations
LEDC_MUTEX_LOCK(); if(iarg & 1) {// this channel is active
uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider; uint8_t group=(chan/8), timer=((chan/2)%4);
uint32_t div_num = (new_apb * old_div) / old_apb; if(LEDC_TIMER(group, timer).conf.tick_sel){
if(div_num > LEDC_DIV_NUM_HSTIMER0_V){ LEDC_MUTEX_LOCK();
new_apb = REF_CLK_FREQ / 1000000; uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider;
div_num = (new_apb * old_div) / old_apb; uint32_t div_num = (new_apb * old_div) / old_apb;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) { if(div_num > LEDC_DIV_NUM_HSTIMER0_V){
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible div_num = ((REF_CLK_FREQ /1000000) * old_div) / old_apb;
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
}
LEDC_TIMER(group, timer).conf.tick_sel = 0;
} else if(div_num < 256) {
div_num = 256;//highest clock possible
}
LEDC_TIMER(group, timer).conf.clock_divider = div_num;
LEDC_MUTEX_UNLOCK();
}
else {
log_d("using REF_CLK chan=%d",chan);
} }
LEDC_TIMER(group, timer).conf.tick_sel = 0;
} else if(div_num < 256) {
div_num = 256;//highest clock possible
} }
LEDC_TIMER(group, timer).conf.clock_divider = div_num; iarg = iarg >> 1;
LEDC_MUTEX_UNLOCK(); chan++;
} }
} }
} }
@ -85,11 +108,14 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
{ {
uint8_t group=(chan/8), timer=((chan/2)%4); uint8_t group=(chan/8), timer=((chan/2)%4);
static bool tHasStarted = false; static bool tHasStarted = false;
static uint16_t _activeChannels = 0;
if(!tHasStarted) { if(!tHasStarted) {
tHasStarted = true; tHasStarted = true;
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST);
LEDC.conf.apb_clk_sel = 1;//LS use apb clock LEDC.conf.apb_clk_sel = 1;//LS use apb clock
addApbChangeCallback((void*)&_activeChannels, _on_apb_change);
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
_ledc_sys_lock = xSemaphoreCreateMutex(); _ledc_sys_lock = xSemaphoreCreateMutex();
#endif #endif
@ -98,15 +124,18 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
LEDC_TIMER(group, timer).conf.clock_divider = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part. LEDC_TIMER(group, timer).conf.clock_divider = div_num;//18 bit (10.8) This register is used to configure parameter for divider in timer the least significant eight bits represent the decimal part.
LEDC_TIMER(group, timer).conf.duty_resolution = bit_num;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20. LEDC_TIMER(group, timer).conf.duty_resolution = bit_num;//5 bit This register controls the range of the counter in timer. the counter range is [0 2**bit_num] the max bit width for counter is 20.
LEDC_TIMER(group, timer).conf.tick_sel = apb_clk;//apb clock LEDC_TIMER(group, timer).conf.tick_sel = apb_clk;//apb clock
#if CONFIG_IDF_TARGET_ESP32
if(group) { if(group) {
#endif
LEDC_TIMER(group, timer).conf.low_speed_update = 1;//This bit is only useful for low speed timer channels, reserved for high speed timers LEDC_TIMER(group, timer).conf.low_speed_update = 1;//This bit is only useful for low speed timer channels, reserved for high speed timers
#if CONFIG_IDF_TARGET_ESP32
} }
#endif
LEDC_TIMER(group, timer).conf.pause = 0; LEDC_TIMER(group, timer).conf.pause = 0;
LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset. LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset.
LEDC_TIMER(group, timer).conf.rst = 0; LEDC_TIMER(group, timer).conf.rst = 0;
LEDC_MUTEX_UNLOCK(); LEDC_MUTEX_UNLOCK();
uint32_t iarg = chan; _activeChannels |= (1 << chan); // mark as active for APB callback
addApbChangeCallback((void*)iarg, _on_apb_change);
} }
//max div_num 0x3FFFF (262143) //max div_num 0x3FFFF (262143)
@ -166,17 +195,21 @@ static void _ledcSetupChannel(uint8_t chan, uint8_t idle_level)
LEDC_CHAN(group, channel).duty.duty = 0; LEDC_CHAN(group, channel).duty.duty = 0;
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware. LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) { if(group) {
LEDC_CHAN(group, channel).conf0.val &= ~BIT(4); #endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else { } else {
LEDC_CHAN(group, channel).conf0.clk_en = 0; LEDC_CHAN(group, channel).conf0.clk_en = 0;
} }
#endif
LEDC_MUTEX_UNLOCK(); LEDC_MUTEX_UNLOCK();
} }
double ledcSetup(uint8_t chan, double freq, uint8_t bit_num) double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
{ {
if(chan > 15) { if(chan > LAST_CHAN) {
return 0; return 0;
} }
double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num); double res_freq = _ledcSetupTimerFreq(chan, freq, bit_num);
@ -186,7 +219,7 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)
void ledcWrite(uint8_t chan, uint32_t duty) void ledcWrite(uint8_t chan, uint32_t duty)
{ {
if(chan > 15) { if(chan > LAST_CHAN) {
return; return;
} }
uint8_t group=(chan/8), channel=(chan%8); uint8_t group=(chan/8), channel=(chan%8);
@ -195,26 +228,34 @@ void ledcWrite(uint8_t chan, uint32_t duty)
if(duty) { if(duty) {
LEDC_CHAN(group, channel).conf0.sig_out_en = 1;//This is the output enable control bit for channel LEDC_CHAN(group, channel).conf0.sig_out_en = 1;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 1;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware. LEDC_CHAN(group, channel).conf1.duty_start = 1;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) { if(group) {
LEDC_CHAN(group, channel).conf0.val |= BIT(4); #endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else { } else {
LEDC_CHAN(group, channel).conf0.clk_en = 1; LEDC_CHAN(group, channel).conf0.clk_en = 1;
} }
#endif
} else { } else {
LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel LEDC_CHAN(group, channel).conf0.sig_out_en = 0;//This is the output enable control bit for channel
LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware. LEDC_CHAN(group, channel).conf1.duty_start = 0;//When duty_num duty_cycle and duty_scale has been configured. these register won't take effect until set duty_start. this bit is automatically cleared by hardware.
#if CONFIG_IDF_TARGET_ESP32
if(group) { if(group) {
LEDC_CHAN(group, channel).conf0.val &= ~BIT(4); #endif
LEDC_CHAN(group, channel).conf0.low_speed_update = 1;
#if CONFIG_IDF_TARGET_ESP32
} else { } else {
LEDC_CHAN(group, channel).conf0.clk_en = 0; LEDC_CHAN(group, channel).conf0.clk_en = 0;
} }
#endif
} }
LEDC_MUTEX_UNLOCK(); LEDC_MUTEX_UNLOCK();
} }
uint32_t ledcRead(uint8_t chan) uint32_t ledcRead(uint8_t chan)
{ {
if(chan > 15) { if(chan > LAST_CHAN) {
return 0; return 0;
} }
return LEDC.channel_group[chan/8].channel[chan%8].duty.duty >> 4; return LEDC.channel_group[chan/8].channel[chan%8].duty.duty >> 4;
@ -230,7 +271,7 @@ double ledcReadFreq(uint8_t chan)
double ledcWriteTone(uint8_t chan, double freq) double ledcWriteTone(uint8_t chan, double freq)
{ {
if(chan > 15) { if(chan > LAST_CHAN) {
return 0; return 0;
} }
if(!freq) { if(!freq) {
@ -257,11 +298,15 @@ double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
void ledcAttachPin(uint8_t pin, uint8_t chan) void ledcAttachPin(uint8_t pin, uint8_t chan)
{ {
if(chan > 15) { if(chan > LAST_CHAN) {
return; return;
} }
pinMode(pin, OUTPUT); pinMode(pin, OUTPUT);
#if CONFIG_IDF_TARGET_ESP32S2
pinMatrixOutAttach(pin, LEDC_LS_SIG_OUT0_IDX + chan, false, false);
#else
pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false); pinMatrixOutAttach(pin, ((chan/8)?LEDC_LS_SIG_OUT0_IDX:LEDC_HS_SIG_OUT0_IDX) + (chan%8), false, false);
#endif
} }
void ledcDetachPin(uint8_t pin) void ledcDetachPin(uint8_t pin)

View File

@ -20,6 +20,7 @@ extern "C"
#endif #endif
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_timer.h"
#define ARDUHAL_LOG_LEVEL_NONE (0) #define ARDUHAL_LOG_LEVEL_NONE (0)
#define ARDUHAL_LOG_LEVEL_ERROR (1) #define ARDUHAL_LOG_LEVEL_ERROR (1)
@ -75,7 +76,7 @@ const char * pathToFileName(const char * path);
int log_printf(const char *fmt, ...); int log_printf(const char *fmt, ...);
#define ARDUHAL_SHORT_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter format ARDUHAL_LOG_RESET_COLOR "\r\n" #define ARDUHAL_SHORT_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter format ARDUHAL_LOG_RESET_COLOR "\r\n"
#define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", pathToFileName(__FILE__), __LINE__, __FUNCTION__ #define ARDUHAL_LOG_FORMAT(letter, format) ARDUHAL_LOG_COLOR_ ## letter "[%6u][" #letter "][%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR "\r\n", (unsigned long) (esp_timer_get_time() / 1000ULL), pathToFileName(__FILE__), __LINE__, __FUNCTION__
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
#define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__) #define log_v(format, ...) log_printf(ARDUHAL_LOG_FORMAT(V, format), ##__VA_ARGS__)

View File

@ -14,33 +14,45 @@
#include "esp32-hal-matrix.h" #include "esp32-hal-matrix.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/gpio.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/gpio.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/gpio.h" #include "rom/gpio.h"
#endif
#define MATRIX_DETACH_OUT_SIG 0x100 #define MATRIX_DETACH_OUT_SIG 0x100
#define MATRIX_DETACH_IN_LOW_PIN 0x30 #define MATRIX_DETACH_IN_LOW_PIN 0x30
#define MATRIX_DETACH_IN_LOW_HIGH 0x38 #define MATRIX_DETACH_IN_LOW_HIGH 0x38
void IRAM_ATTR pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable) void ARDUINO_ISR_ATTR pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable)
{ {
gpio_matrix_out(pin, function, invertOut, invertEnable); gpio_matrix_out(pin, function, invertOut, invertEnable);
} }
void IRAM_ATTR pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable) void ARDUINO_ISR_ATTR pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable)
{ {
gpio_matrix_out(pin, MATRIX_DETACH_OUT_SIG, invertOut, invertEnable); gpio_matrix_out(pin, MATRIX_DETACH_OUT_SIG, invertOut, invertEnable);
} }
void IRAM_ATTR pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted) void ARDUINO_ISR_ATTR pinMatrixInAttach(uint8_t pin, uint8_t signal, bool inverted)
{ {
gpio_matrix_in(pin, signal, inverted); gpio_matrix_in(pin, signal, inverted);
} }
void IRAM_ATTR pinMatrixInDetach(uint8_t signal, bool high, bool inverted) void ARDUINO_ISR_ATTR pinMatrixInDetach(uint8_t signal, bool high, bool inverted)
{ {
gpio_matrix_in(high?MATRIX_DETACH_IN_LOW_HIGH:MATRIX_DETACH_IN_LOW_PIN, signal, inverted); gpio_matrix_in(high?MATRIX_DETACH_IN_LOW_HIGH:MATRIX_DETACH_IN_LOW_PIN, signal, inverted);
} }
/* /*
void IRAM_ATTR intrMatrixAttach(uint32_t source, uint32_t inum){ void ARDUINO_ISR_ATTR intrMatrixAttach(uint32_t source, uint32_t inum){
intr_matrix_set(PRO_CPU_NUM, source, inum); intr_matrix_set(PRO_CPU_NUM, source, inum);
} }
*/ */

View File

@ -31,10 +31,22 @@
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/apb_ctrl_reg.h" #include "soc/apb_ctrl_reg.h"
#include "rom/rtc.h"
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "esp32-hal.h" #include "esp32-hal.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/rtc.h"
#endif
//Undocumented!!! Get chip temperature in Farenheit //Undocumented!!! Get chip temperature in Farenheit
//Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino //Source: https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/ESP32_int_temp_sensor/ESP32_int_temp_sensor.ino
uint8_t temprature_sens_read(); uint8_t temprature_sens_read();
@ -44,11 +56,13 @@ float temperatureRead()
return (temprature_sens_read() - 32) / 1.8; return (temprature_sens_read() - 32) / 1.8;
} }
void yield() void __yield()
{ {
vPortYield(); vPortYield();
} }
void yield() __attribute__ ((weak, alias("__yield")));
#if CONFIG_AUTOSTART_ARDUINO #if CONFIG_AUTOSTART_ARDUINO
extern TaskHandle_t loopTaskHandle; extern TaskHandle_t loopTaskHandle;
@ -111,12 +125,30 @@ void disableCore1WDT(){
} }
#endif #endif
unsigned long IRAM_ATTR micros() BaseType_t xTaskCreateUniversal( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask,
const BaseType_t xCoreID ){
#ifndef CONFIG_FREERTOS_UNICORE
if(xCoreID >= 0 && xCoreID < 2) {
return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID);
} else {
#endif
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
#ifndef CONFIG_FREERTOS_UNICORE
}
#endif
}
unsigned long ARDUINO_ISR_ATTR micros()
{ {
return (unsigned long) (esp_timer_get_time()); return (unsigned long) (esp_timer_get_time());
} }
unsigned long IRAM_ATTR millis() unsigned long ARDUINO_ISR_ATTR millis()
{ {
return (unsigned long) (esp_timer_get_time() / 1000ULL); return (unsigned long) (esp_timer_get_time() / 1000ULL);
} }
@ -126,7 +158,7 @@ void delay(uint32_t ms)
vTaskDelay(ms / portTICK_PERIOD_MS); vTaskDelay(ms / portTICK_PERIOD_MS);
} }
void IRAM_ATTR delayMicroseconds(uint32_t us) void ARDUINO_ISR_ATTR delayMicroseconds(uint32_t us)
{ {
uint32_t m = micros(); uint32_t m = micros();
if(us){ if(us){
@ -178,7 +210,7 @@ void initArduino()
#ifdef F_CPU #ifdef F_CPU
setCpuFrequencyMhz(F_CPU/1000000); setCpuFrequencyMhz(F_CPU/1000000);
#endif #endif
#if CONFIG_SPIRAM_SUPPORT #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
psramInit(); psramInit();
#endif #endif
esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL); esp_log_level_set("*", CONFIG_LOG_DEFAULT_LEVEL);
@ -207,7 +239,7 @@ void initArduino()
} }
//used by hal log //used by hal log
const char * IRAM_ATTR pathToFileName(const char * path) const char * ARDUINO_ISR_ATTR pathToFileName(const char * path)
{ {
size_t i = 0; size_t i = 0;
size_t pos = 0; size_t pos = 0;

View File

@ -1,11 +1,37 @@
// Copyright 2015-2016 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 "esp32-hal.h" #include "esp32-hal.h"
#if CONFIG_SPIRAM_SUPPORT #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
#include "esp_spiram.h"
#include "soc/efuse_reg.h" #include "soc/efuse_reg.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/spiram.h"
#include "esp32s2/rom/cache.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "esp_spiram.h"
#endif
static volatile bool spiramDetected = false; static volatile bool spiramDetected = false;
static volatile bool spiramFailed = false; static volatile bool spiramFailed = false;
@ -17,6 +43,7 @@ bool psramInit(){
if (spiramFailed) { if (spiramFailed) {
return false; return false;
} }
#if CONFIG_IDF_TARGET_ESP32
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7; uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
@ -25,13 +52,21 @@ bool psramInit(){
return false; return false;
} }
esp_spiram_init_cache(); esp_spiram_init_cache();
#elif CONFIG_IDF_TARGET_ESP32S2
extern void esp_config_data_cache_mode(void);
esp_config_data_cache_mode();
Cache_Enable_DCache(0);
#endif
if (esp_spiram_init() != ESP_OK) { if (esp_spiram_init() != ESP_OK) {
spiramFailed = true; spiramFailed = true;
log_w("PSRAM init failed!"); log_w("PSRAM init failed!");
#if CONFIG_IDF_TARGET_ESP32
pinMatrixOutDetach(16, false, false); pinMatrixOutDetach(16, false, false);
pinMatrixOutDetach(17, false, false); pinMatrixOutDetach(17, false, false);
#endif
return false; return false;
} }
esp_spiram_init_cache();
if (!esp_spiram_test()) { if (!esp_spiram_test()) {
spiramFailed = true; spiramFailed = true;
log_e("PSRAM test failed!"); log_e("PSRAM test failed!");
@ -42,31 +77,34 @@ bool psramInit(){
log_e("PSRAM could not be added to the heap!"); log_e("PSRAM could not be added to the heap!");
return false; return false;
} }
#if CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL && !CONFIG_ARDUINO_ISR_IRAM
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif
#endif #endif
spiramDetected = true; spiramDetected = true;
log_d("PSRAM enabled"); log_d("PSRAM enabled");
return true; return true;
} }
bool IRAM_ATTR psramFound(){ bool ARDUINO_ISR_ATTR psramFound(){
return spiramDetected; return spiramDetected;
} }
void IRAM_ATTR *ps_malloc(size_t size){ void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
if(!spiramDetected){ if(!spiramDetected){
return NULL; return NULL;
} }
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
} }
void IRAM_ATTR *ps_calloc(size_t n, size_t size){ void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
if(!spiramDetected){ if(!spiramDetected){
return NULL; return NULL;
} }
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
} }
void IRAM_ATTR *ps_realloc(void *ptr, size_t size){ void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
if(!spiramDetected){ if(!spiramDetected){
return NULL; return NULL;
} }
@ -79,19 +117,19 @@ bool psramInit(){
return false; return false;
} }
bool IRAM_ATTR psramFound(){ bool ARDUINO_ISR_ATTR psramFound(){
return false; return false;
} }
void IRAM_ATTR *ps_malloc(size_t size){ void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
return NULL; return NULL;
} }
void IRAM_ATTR *ps_calloc(size_t n, size_t size){ void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){
return NULL; return NULL;
} }
void IRAM_ATTR *ps_realloc(void *ptr, size_t size){ void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){
return NULL; return NULL;
} }

View File

@ -19,6 +19,17 @@
extern "C" { extern "C" {
#endif #endif
#include "sdkconfig.h"
#ifndef BOARD_HAS_PSRAM
#ifdef CONFIG_SPIRAM_SUPPORT
#undef CONFIG_SPIRAM_SUPPORT
#endif
#ifdef CONFIG_SPIRAM
#undef CONFIG_SPIRAM
#endif
#endif
bool psramInit(); bool psramInit();
bool psramFound(); bool psramFound();

View File

@ -19,18 +19,20 @@
#include "esp32-hal.h" #include "esp32-hal.h"
#include "esp8266-compat.h" #include "esp8266-compat.h"
#include "soc/gpio_reg.h" #include "soc/gpio_reg.h"
#include "soc/gpio_reg.h"
#include "esp32-hal-rmt.h"
#include "driver/periph_ctrl.h"
#include "soc/rmt_struct.h" #include "soc/rmt_struct.h"
#include "driver/periph_ctrl.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
/** /**
* Internal macros * Internal macros
*/ */
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#define MAX_CHANNELS 8 #define MAX_CHANNELS 8
#elif CONFIG_IDF_TARGET_ESP32S2
#define MAX_CHANNELS 4
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#define MAX_DATA_PER_CHANNEL 64 #define MAX_DATA_PER_CHANNEL 64
#define MAX_DATA_PER_ITTERATION 62 #define MAX_DATA_PER_ITTERATION 62
#define _ABS(a) (a>0?a:-a) #define _ABS(a) (a>0?a:-a)
@ -100,7 +102,10 @@ struct rmt_obj_s
* Internal variables for channel descriptors * Internal variables for channel descriptors
*/ */
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = { static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL NULL, NULL, NULL, NULL,
#if CONFIG_IDF_TARGET_ESP32
NULL, NULL, NULL, NULL
#endif
}; };
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = { static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
@ -108,10 +113,12 @@ static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
#if CONFIG_IDF_TARGET_ESP32
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
#endif
}; };
/** /**
@ -128,19 +135,19 @@ static xSemaphoreHandle g_rmt_block_lock = NULL;
*/ */
static void _initPin(int pin, int channel, bool tx_not_rx); static void _initPin(int pin, int channel, bool tx_not_rx);
static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size); static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous);
static void IRAM_ATTR _rmt_isr(void* arg); static void ARDUINO_ISR_ATTR _rmt_isr(void* arg);
static rmt_obj_t* _rmtAllocate(int pin, int from, int size); static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
static void _initPin(int pin, int channel, bool tx_not_rx); static void _initPin(int pin, int channel, bool tx_not_rx);
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel); static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel);
static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch); static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch);
static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch); static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch);
/** /**
@ -234,6 +241,20 @@ bool rmtDeinit(rmt_obj_t *rmt)
return true; return true;
} }
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
{
if (!rmt) {
return false;
}
int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers;
if (size > allocated_size) {
return false;
}
return _rmtSendOnce(rmt, data, size, true);
}
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size) bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
{ {
if (!rmt) { if (!rmt) {
@ -249,7 +270,7 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
RMT_MUTEX_LOCK(channel); RMT_MUTEX_LOCK(channel);
// setup interrupt handler if not yet installed for half and full tx // setup interrupt handler if not yet installed for half and full tx
if (!intr_handle) { if (!intr_handle) {
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle); esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
} }
rmt->data_size = size - MAX_DATA_PER_ITTERATION; rmt->data_size = size - MAX_DATA_PER_ITTERATION;
@ -282,10 +303,10 @@ bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
RMT_MUTEX_UNLOCK(channel); RMT_MUTEX_UNLOCK(channel);
// start the transation // start the transation
return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION); return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false);
} else { } else {
// use one-go mode if data fits one buffer // use one-go mode if data fits one buffer
return _rmtSendOnce(rmt, data, size); return _rmtSendOnce(rmt, data, size, false);
} }
} }
@ -483,7 +504,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
break; break;
} }
} }
if (i == MAX_CHANNELS || i+j >= MAX_CHANNELS || j != buffers) { if (i == MAX_CHANNELS || i+j > MAX_CHANNELS || j != buffers) {
xSemaphoreGive(g_rmt_block_lock); xSemaphoreGive(g_rmt_block_lock);
return NULL; return NULL;
} }
@ -518,12 +539,17 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
RMT.conf_ch[channel].conf0.mem_size = buffers; RMT.conf_ch[channel].conf0.mem_size = buffers;
RMT.conf_ch[channel].conf0.carrier_en = 0; RMT.conf_ch[channel].conf0.carrier_en = 0;
RMT.conf_ch[channel].conf0.carrier_out_lv = 0; RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
#if CONFIG_IDF_TARGET_ESP32
RMT.conf_ch[channel].conf0.mem_pd = 0; RMT.conf_ch[channel].conf0.mem_pd = 0;
#endif
RMT.conf_ch[channel].conf0.idle_thres = 0x80; RMT.conf_ch[channel].conf0.idle_thres = 0x80;
RMT.conf_ch[channel].conf1.rx_en = 0; RMT.conf_ch[channel].conf1.rx_en = 0;
RMT.conf_ch[channel].conf1.tx_conti_mode = 0; RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
#if CONFIG_IDF_TARGET_ESP32
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0; RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
#else
RMT.conf_ch[channel].conf1.chk_rx_carrier_en = 0;
#endif
RMT.conf_ch[channel].conf1.rx_filter_en = 0; RMT.conf_ch[channel].conf1.rx_filter_en = 0;
RMT.conf_ch[channel].conf1.rx_filter_thres = 0; RMT.conf_ch[channel].conf1.rx_filter_thres = 0;
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
@ -543,7 +569,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
// install interrupt if at least one channel is active // install interrupt if at least one channel is active
if (!intr_handle) { if (!intr_handle) {
esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle); esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, _rmt_isr, NULL, &intr_handle);
} }
RMT_MUTEX_UNLOCK(channel); RMT_MUTEX_UNLOCK(channel);
@ -553,7 +579,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
/** /**
* Private methods definitions * Private methods definitions
*/ */
bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size) bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous)
{ {
if (!rmt) { if (!rmt) {
return false; return false;
@ -571,6 +597,7 @@ bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
} }
RMT_MUTEX_LOCK(channel); RMT_MUTEX_LOCK(channel);
RMT.conf_ch[channel].conf1.tx_conti_mode = continuous;
RMT.conf_ch[channel].conf1.mem_rd_rst = 1; RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
RMT.conf_ch[channel].conf1.tx_start = 1; RMT.conf_ch[channel].conf1.tx_start = 1;
RMT_MUTEX_UNLOCK(channel); RMT_MUTEX_UNLOCK(channel);
@ -610,7 +637,7 @@ static void _initPin(int pin, int channel, bool tx_not_rx)
} }
static void IRAM_ATTR _rmt_isr(void* arg) static void ARDUINO_ISR_ATTR _rmt_isr(void* arg)
{ {
int intr_val = RMT.int_st.val; int intr_val = RMT.int_st.val;
size_t ch; size_t ch;
@ -665,7 +692,6 @@ static void IRAM_ATTR _rmt_isr(void* arg)
} }
if (intr_val & _INT_ERROR(ch)) { if (intr_val & _INT_ERROR(ch)) {
digitalWrite(2, 1);
// clear the flag // clear the flag
RMT.int_clr.val = _INT_ERROR(ch); RMT.int_clr.val = _INT_ERROR(ch);
RMT.int_ena.val &= ~_INT_ERROR(ch); RMT.int_ena.val &= ~_INT_ERROR(ch);
@ -701,7 +727,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
} }
} }
static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch) static void ARDUINO_ISR_ATTR _rmt_tx_mem_second(uint8_t ch)
{ {
DEBUG_INTERRUPT_START(4) DEBUG_INTERRUPT_START(4)
uint32_t* data = g_rmt_objects[ch].data_ptr; uint32_t* data = g_rmt_objects[ch].data_ptr;
@ -753,7 +779,7 @@ static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch)
DEBUG_INTERRUPT_END(4); DEBUG_INTERRUPT_END(4);
} }
static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch) static void ARDUINO_ISR_ATTR _rmt_tx_mem_first(uint8_t ch)
{ {
DEBUG_INTERRUPT_START(2); DEBUG_INTERRUPT_START(2);
uint32_t* data = g_rmt_objects[ch].data_ptr; uint32_t* data = g_rmt_objects[ch].data_ptr;
@ -804,7 +830,7 @@ static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch)
DEBUG_INTERRUPT_END(2); DEBUG_INTERRUPT_END(2);
} }
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel) static int ARDUINO_ISR_ATTR _rmt_get_mem_len(uint8_t channel)
{ {
int block_num = RMT.conf_ch[channel].conf0.mem_size; int block_num = RMT.conf_ch[channel].conf0.mem_size;
int item_block_len = block_num * 64; int item_block_len = block_num * 64;

View File

@ -73,6 +73,12 @@ float rmtSetTick(rmt_obj_t* rmt, float tick);
*/ */
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size); bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
/**
* Loop data up to the reserved memsize continuously
*
*/
bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
/** /**
* Initiates async receive, event flag indicates data received * Initiates async receive, event flag indicates data received
* *
@ -122,6 +128,10 @@ bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t
*/ */
bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level); bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level);
/**
* Deinitialize the driver
*/
bool rmtDeinit(rmt_obj_t *rmt);
// TODO: // TODO:
// * uninstall interrupt when all channels are deinit // * uninstall interrupt when all channels are deinit

View File

@ -16,11 +16,23 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "esp32-hal-matrix.h" #include "esp32-hal-matrix.h"
#include "soc/gpio_sd_reg.h" #include "soc/gpio_sd_reg.h"
#include "soc/gpio_sd_struct.h" #include "soc/gpio_sd_struct.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif
#if CONFIG_DISABLE_HAL_LOCKS #if CONFIG_DISABLE_HAL_LOCKS
#define SD_MUTEX_LOCK() #define SD_MUTEX_LOCK()
@ -69,6 +81,9 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31
prescale = 0xFF; prescale = 0xFF;
} }
SD_MUTEX_LOCK(); SD_MUTEX_LOCK();
#ifndef CONFIG_IDF_TARGET_ESP32
SIGMADELTA.misc.function_clk_en = 1;
#endif
SIGMADELTA.channel[channel].prescale = prescale; SIGMADELTA.channel[channel].prescale = prescale;
SIGMADELTA.cg.clk_en = 0; SIGMADELTA.cg.clk_en = 0;
SIGMADELTA.cg.clk_en = 1; SIGMADELTA.cg.clk_en = 1;

View File

@ -17,10 +17,7 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "rom/gpio.h"
#include "soc/spi_reg.h" #include "soc/spi_reg.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
@ -28,17 +25,24 @@
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0)))) #include "esp_system.h"
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0)))) #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?SPID_IN_IDX:((p==2)?HSPID_IN_IDX:((p==3)?VSPID_IN_IDX:0)))) #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:((n==2)?SPICS2_OUT_IDX:SPICS0_OUT_IDX))) #include "esp32/rom/gpio.h"
#define SPI_HSPI_SS_IDX(n) ((n==0)?HSPICS0_OUT_IDX:((n==1)?HSPICS1_OUT_IDX:((n==2)?HSPICS2_OUT_IDX:HSPICS0_OUT_IDX))) #include "esp_intr_alloc.h"
#define SPI_VSPI_SS_IDX(n) ((n==0)?VSPICS0_OUT_IDX:((n==1)?VSPICS1_OUT_IDX:((n==2)?VSPICS2_OUT_IDX:VSPICS0_OUT_IDX))) #elif CONFIG_IDF_TARGET_ESP32S2
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):((p==3)?SPI_VSPI_SS_IDX(n):0)))) #include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/gpio.h"
#define SPI_INUM(u) (2) #include "esp_intr_alloc.h"
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI0_INTR_SOURCE:((u==1)?ETS_SPI1_INTR_SOURCE:((u==2)?ETS_SPI2_INTR_SOURCE:((p==3)?ETS_SPI3_INTR_SOURCE:0)))) #else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "rom/gpio.h"
#include "esp_intr.h"
#endif
struct spi_struct_t { struct spi_struct_t {
spi_dev_t * dev; spi_dev_t * dev;
@ -48,25 +52,69 @@ struct spi_struct_t {
uint8_t num; uint8_t num;
}; };
#if CONFIG_IDF_TARGET_ESP32S2
// ESP32S2
#define SPI_COUNT (3)
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_MUX_IDX:((p==1)?FSPICLK_OUT_MUX_IDX:((p==2)?SPI3_CLK_OUT_MUX_IDX:0)))
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?FSPIQ_OUT_IDX:((p==2)?SPI3_Q_OUT_IDX:0)))
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?FSPID_IN_IDX:((p==2)?SPI3_D_IN_IDX:0)))
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:0))
#define SPI_HSPI_SS_IDX(n) ((n==0)?SPI3_CS0_OUT_IDX:((n==1)?SPI3_CS1_OUT_IDX:((n==2)?SPI3_CS2_OUT_IDX:SPI3_CS0_OUT_IDX)))
#define SPI_FSPI_SS_IDX(n) ((n==0)?FSPICS0_OUT_IDX:((n==1)?FSPICS1_OUT_IDX:((n==2)?FSPICS2_OUT_IDX:VSPICS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):0)))
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI1_INTR_SOURCE:((u==1)?ETS_SPI2_INTR_SOURCE:((u==2)?ETS_SPI3_INTR_SOURCE:0)))
#else
// ESP32
#define SPI_COUNT (4)
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0))))
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0))))
#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?SPID_IN_IDX:((p==2)?HSPID_IN_IDX:((p==3)?VSPID_IN_IDX:0))))
#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:((n==2)?SPICS2_OUT_IDX:SPICS0_OUT_IDX)))
#define SPI_HSPI_SS_IDX(n) ((n==0)?HSPICS0_OUT_IDX:((n==1)?HSPICS1_OUT_IDX:((n==2)?HSPICS2_OUT_IDX:HSPICS0_OUT_IDX)))
#define SPI_VSPI_SS_IDX(n) ((n==0)?VSPICS0_OUT_IDX:((n==1)?VSPICS1_OUT_IDX:((n==2)?VSPICS2_OUT_IDX:VSPICS0_OUT_IDX)))
#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):((p==3)?SPI_VSPI_SS_IDX(n):0))))
#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI0_INTR_SOURCE:((u==1)?ETS_SPI1_INTR_SOURCE:((u==2)?ETS_SPI2_INTR_SOURCE:((p==3)?ETS_SPI3_INTR_SOURCE:0))))
#endif
#if CONFIG_DISABLE_HAL_LOCKS #if CONFIG_DISABLE_HAL_LOCKS
#define SPI_MUTEX_LOCK() #define SPI_MUTEX_LOCK()
#define SPI_MUTEX_UNLOCK() #define SPI_MUTEX_UNLOCK()
static spi_t _spi_bus_array[4] = { static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2}
#else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0}, {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1}, {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3} {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3}
#endif
}; };
#else #else
#define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS) #define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS)
#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) #define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock)
static spi_t _spi_bus_array[4] = { static spi_t _spi_bus_array[] = {
#if CONFIG_IDF_TARGET_ESP32S2
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2}
#else
{(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0}, {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0},
{(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1}, {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1},
{(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2}, {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2},
{(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3} {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3}
#endif
}; };
#endif #endif
@ -76,6 +124,14 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
return; return;
} }
if(sck < 0) { if(sck < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
sck = 36;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
sck = 14; sck = 14;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -83,6 +139,7 @@ void spiAttachSCK(spi_t * spi, int8_t sck)
} else { } else {
sck = 6; sck = 6;
} }
#endif
} }
pinMode(sck, OUTPUT); pinMode(sck, OUTPUT);
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false); pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
@ -94,6 +151,14 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
return; return;
} }
if(miso < 0) { if(miso < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
miso = 37;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
miso = 12; miso = 12;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -101,6 +166,7 @@ void spiAttachMISO(spi_t * spi, int8_t miso)
} else { } else {
miso = 7; miso = 7;
} }
#endif
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
pinMode(miso, INPUT); pinMode(miso, INPUT);
@ -114,6 +180,14 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
return; return;
} }
if(mosi < 0) { if(mosi < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
mosi = 35;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
mosi = 13; mosi = 13;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -121,6 +195,7 @@ void spiAttachMOSI(spi_t * spi, int8_t mosi)
} else { } else {
mosi = 8; mosi = 8;
} }
#endif
} }
pinMode(mosi, OUTPUT); pinMode(mosi, OUTPUT);
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false); pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
@ -132,6 +207,14 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
return; return;
} }
if(sck < 0) { if(sck < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
sck = 36;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
sck = 14; sck = 14;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -139,6 +222,7 @@ void spiDetachSCK(spi_t * spi, int8_t sck)
} else { } else {
sck = 6; sck = 6;
} }
#endif
} }
pinMatrixOutDetach(sck, false, false); pinMatrixOutDetach(sck, false, false);
pinMode(sck, INPUT); pinMode(sck, INPUT);
@ -150,6 +234,14 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
return; return;
} }
if(miso < 0) { if(miso < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
miso = 37;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
miso = 12; miso = 12;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -157,6 +249,7 @@ void spiDetachMISO(spi_t * spi, int8_t miso)
} else { } else {
miso = 7; miso = 7;
} }
#endif
} }
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false); pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
pinMode(miso, INPUT); pinMode(miso, INPUT);
@ -168,6 +261,14 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
return; return;
} }
if(mosi < 0) { if(mosi < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
mosi = 35;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
mosi = 13; mosi = 13;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -175,6 +276,7 @@ void spiDetachMOSI(spi_t * spi, int8_t mosi)
} else { } else {
mosi = 8; mosi = 8;
} }
#endif
} }
pinMatrixOutDetach(mosi, false, false); pinMatrixOutDetach(mosi, false, false);
pinMode(mosi, INPUT); pinMode(mosi, INPUT);
@ -190,6 +292,14 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
} }
if(ss < 0) { if(ss < 0) {
cs_num = 0; cs_num = 0;
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
ss = 34;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
ss = 15; ss = 15;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -197,6 +307,7 @@ void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
} else { } else {
ss = 11; ss = 11;
} }
#endif
} }
pinMode(ss, OUTPUT); pinMode(ss, OUTPUT);
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false); pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
@ -209,6 +320,14 @@ void spiDetachSS(spi_t * spi, int8_t ss)
return; return;
} }
if(ss < 0) { if(ss < 0) {
#if CONFIG_IDF_TARGET_ESP32S2
if(spi->num == FSPI) {
ss = 34;
} else {
log_e("HSPI Does not have default pins on ESP32S2!");
return;
}
#else
if(spi->num == HSPI) { if(spi->num == HSPI) {
ss = 15; ss = 15;
} else if(spi->num == VSPI) { } else if(spi->num == VSPI) {
@ -216,6 +335,7 @@ void spiDetachSS(spi_t * spi, int8_t ss)
} else { } else {
ss = 11; ss = 11;
} }
#endif
} }
pinMatrixOutDetach(ss, false, false); pinMatrixOutDetach(ss, false, false);
pinMode(ss, INPUT); pinMode(ss, INPUT);
@ -227,7 +347,11 @@ void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
#else
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL); spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
#endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -237,7 +361,11 @@ void spiDisableSSPins(spi_t * spi, uint8_t cs_mask)
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
#else
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL); spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
#endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -269,7 +397,11 @@ void spiSSSet(spi_t * spi)
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.cs_keep_active = 1;
#else
spi->dev->pin.cs_keep_active = 1; spi->dev->pin.cs_keep_active = 1;
#endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -279,7 +411,11 @@ void spiSSClear(spi_t * spi)
return; return;
} }
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.cs_keep_active = 0;
#else
spi->dev->pin.cs_keep_active = 0; spi->dev->pin.cs_keep_active = 0;
#endif
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
@ -306,7 +442,11 @@ uint8_t spiGetDataMode(spi_t * spi)
if(!spi) { if(!spi) {
return 0; return 0;
} }
#if CONFIG_IDF_TARGET_ESP32S2
bool idleEdge = spi->dev->misc.ck_idle_edge;
#else
bool idleEdge = spi->dev->pin.ck_idle_edge; bool idleEdge = spi->dev->pin.ck_idle_edge;
#endif
bool outEdge = spi->dev->user.ck_out_edge; bool outEdge = spi->dev->user.ck_out_edge;
if(idleEdge) { if(idleEdge) {
if(outEdge) { if(outEdge) {
@ -328,20 +468,36 @@ void spiSetDataMode(spi_t * spi, uint8_t dataMode)
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
switch (dataMode) { switch (dataMode) {
case SPI_MODE1: case SPI_MODE1:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0; spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE2: case SPI_MODE2:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1; spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE3: case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1; spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
case SPI_MODE0: case SPI_MODE0:
default: default:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0; spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 0; spi->dev->user.ck_out_edge = 0;
break; break;
} }
@ -384,28 +540,39 @@ static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb
} }
} }
void spiStopBus(spi_t * spi) static void spiInitBus(spi_t * spi)
{ {
if(!spi) {
return;
}
SPI_MUTEX_LOCK();
spi->dev->slave.trans_done = 0; spi->dev->slave.trans_done = 0;
spi->dev->slave.slave_mode = 0; spi->dev->slave.slave_mode = 0;
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.val = 0;
#else
spi->dev->pin.val = 0; spi->dev->pin.val = 0;
#endif
spi->dev->user.val = 0; spi->dev->user.val = 0;
spi->dev->user1.val = 0; spi->dev->user1.val = 0;
spi->dev->ctrl.val = 0; spi->dev->ctrl.val = 0;
spi->dev->ctrl1.val = 0; spi->dev->ctrl1.val = 0;
spi->dev->ctrl2.val = 0; spi->dev->ctrl2.val = 0;
spi->dev->clock.val = 0; spi->dev->clock.val = 0;
SPI_MUTEX_UNLOCK(); }
void spiStopBus(spi_t * spi)
{
if(!spi) {
return;
}
removeApbChangeCallback(spi, _on_apb_change); removeApbChangeCallback(spi, _on_apb_change);
SPI_MUTEX_LOCK();
spiInitBus(spi);
SPI_MUTEX_UNLOCK();
} }
spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder) spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder)
{ {
if(spi_num > 3){ if(spi_num >= SPI_COUNT){
return NULL; return NULL;
} }
@ -420,23 +587,32 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
} }
#endif #endif
if(spi_num == HSPI) { #if CONFIG_IDF_TARGET_ESP32S2
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN); if(spi_num == FSPI) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
} else if(spi_num == VSPI) { DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); } else if(spi_num == HSPI) {
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
} else { } else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
} }
#else
spiStopBus(spi); if(spi_num == HSPI) {
spiSetDataMode(spi, dataMode); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
spiSetBitOrder(spi, bitOrder); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
spiSetClockDiv(spi, clockDiv); } else if(spi_num == VSPI) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
} else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
}
#endif
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spiInitBus(spi);
spi->dev->user.usr_mosi = 1; spi->dev->user.usr_mosi = 1;
spi->dev->user.usr_miso = 1; spi->dev->user.usr_miso = 1;
spi->dev->user.doutdin = 1; spi->dev->user.doutdin = 1;
@ -447,6 +623,10 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
} }
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
spiSetDataMode(spi, dataMode);
spiSetBitOrder(spi, bitOrder);
spiSetClockDiv(spi, clockDiv);
addApbChangeCallback(spi, _on_apb_change); addApbChangeCallback(spi, _on_apb_change);
return spi; return spi;
} }
@ -459,7 +639,12 @@ void spiWaitReady(spi_t * spi)
while(spi->dev->cmd.usr); while(spi->dev->cmd.usr);
} }
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len) #if CONFIG_IDF_TARGET_ESP32S2
#define usr_mosi_dbitlen usr_mosi_bit_len
#define usr_miso_dbitlen usr_miso_bit_len
#endif
void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len)
{ {
if(!spi) { if(!spi) {
return; return;
@ -532,17 +717,7 @@ uint8_t spiTransferByte(spi_t * spi, uint8_t data)
return data; return data;
} }
uint32_t __spiTranslate24(uint32_t data) static uint32_t __spiTranslate32(uint32_t data)
{
union {
uint32_t l;
uint8_t b[4];
} out;
out.l = data;
return out.b[2] | (out.b[1] << 8) | (out.b[0] << 16);
}
uint32_t __spiTranslate32(uint32_t data)
{ {
union { union {
uint32_t l; uint32_t l;
@ -630,7 +805,7 @@ uint32_t spiTransferLong(spi_t * spi, uint32_t data)
return data; return data;
} }
void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t bytes) static void __spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t bytes)
{ {
if(!spi) { if(!spi) {
return; return;
@ -671,7 +846,7 @@ void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t byt
} }
} }
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size) void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size)
{ {
if(!spi) { if(!spi) {
return; return;
@ -722,23 +897,39 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
SPI_MUTEX_LOCK(); SPI_MUTEX_LOCK();
spi->dev->clock.val = clockDiv; spi->dev->clock.val = clockDiv;
switch (dataMode) { switch (dataMode) {
case SPI_MODE1: case SPI_MODE1:
spi->dev->pin.ck_idle_edge = 0; #if CONFIG_IDF_TARGET_ESP32S2
spi->dev->user.ck_out_edge = 1; spi->dev->misc.ck_idle_edge = 0;
break; #else
case SPI_MODE2: spi->dev->pin.ck_idle_edge = 0;
spi->dev->pin.ck_idle_edge = 1; #endif
spi->dev->user.ck_out_edge = 1; spi->dev->user.ck_out_edge = 1;
break; break;
case SPI_MODE3: case SPI_MODE2:
spi->dev->pin.ck_idle_edge = 1; #if CONFIG_IDF_TARGET_ESP32S2
spi->dev->user.ck_out_edge = 0; spi->dev->misc.ck_idle_edge = 1;
break; #else
case SPI_MODE0: spi->dev->pin.ck_idle_edge = 1;
default: #endif
spi->dev->pin.ck_idle_edge = 0; spi->dev->user.ck_out_edge = 1;
spi->dev->user.ck_out_edge = 0; break;
break; case SPI_MODE3:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 1;
#else
spi->dev->pin.ck_idle_edge = 1;
#endif
spi->dev->user.ck_out_edge = 0;
break;
case SPI_MODE0:
default:
#if CONFIG_IDF_TARGET_ESP32S2
spi->dev->misc.ck_idle_edge = 0;
#else
spi->dev->pin.ck_idle_edge = 0;
#endif
spi->dev->user.ck_out_edge = 0;
break;
} }
if (SPI_MSBFIRST == bitOrder) { if (SPI_MSBFIRST == bitOrder) {
spi->dev->ctrl.wr_bit_order = 0; spi->dev->ctrl.wr_bit_order = 0;
@ -765,7 +956,7 @@ void spiEndTransaction(spi_t * spi)
SPI_MUTEX_UNLOCK(); SPI_MUTEX_UNLOCK();
} }
void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data) void ARDUINO_ISR_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
{ {
if(!spi) { if(!spi) {
return; return;
@ -791,7 +982,7 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
return data; return data;
} }
void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data) void ARDUINO_ISR_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
{ {
if(!spi) { if(!spi) {
return; return;
@ -826,7 +1017,7 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
return data; return data;
} }
void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data) void ARDUINO_ISR_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
{ {
if(!spi) { if(!spi) {
return; return;
@ -861,7 +1052,7 @@ uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
return data; return data;
} }
void spiWriteNL(spi_t * spi, const void * data_in, size_t len){ void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){
size_t longs = len >> 2; size_t longs = len >> 2;
if(len & 3){ if(len & 3){
longs++; longs++;
@ -887,7 +1078,7 @@ void spiWriteNL(spi_t * spi, const void * data_in, size_t len){
} }
} }
void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, size_t len){ void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, uint32_t len){
if(!spi) { if(!spi) {
return; return;
} }
@ -974,7 +1165,7 @@ void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
} }
} }
void IRAM_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){ void ARDUINO_ISR_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len){
size_t longs = len >> 2; size_t longs = len >> 2;
if(len & 3){ if(len & 3){
longs++; longs++;

View File

@ -19,6 +19,7 @@
extern "C" { extern "C" {
#endif #endif
#include "sdkconfig.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -26,7 +27,9 @@ extern "C" {
#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS) #define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins #define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#if CONFIG_IDF_TARGET_ESP32
#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins #define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#endif
// This defines are not representing the real Divider of the ESP32 // This defines are not representing the real Divider of the ESP32
// the Defines match to an AVR Arduino on 16MHz for better compatibility // the Defines match to an AVR Arduino on 16MHz for better compatibility
@ -96,7 +99,7 @@ void spiSetClockDiv(spi_t * spi, uint32_t clockDiv);
void spiSetDataMode(spi_t * spi, uint8_t dataMode); void spiSetDataMode(spi_t * spi, uint8_t dataMode);
void spiSetBitOrder(spi_t * spi, uint8_t bitOrder); void spiSetBitOrder(spi_t * spi, uint8_t bitOrder);
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len); void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len);
void spiWriteByte(spi_t * spi, uint8_t data); void spiWriteByte(spi_t * spi, uint8_t data);
void spiWriteWord(spi_t * spi, uint16_t data); void spiWriteWord(spi_t * spi, uint16_t data);
void spiWriteLong(spi_t * spi, uint32_t data); void spiWriteLong(spi_t * spi, uint32_t data);
@ -105,7 +108,7 @@ void spiTransfer(spi_t * spi, uint32_t *out, uint8_t len);
uint8_t spiTransferByte(spi_t * spi, uint8_t data); uint8_t spiTransferByte(spi_t * spi, uint8_t data);
uint16_t spiTransferWord(spi_t * spi, uint16_t data); uint16_t spiTransferWord(spi_t * spi, uint16_t data);
uint32_t spiTransferLong(spi_t * spi, uint32_t data); uint32_t spiTransferLong(spi_t * spi, uint32_t data);
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size); void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size);
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits); void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits);
/* /*
@ -115,11 +118,11 @@ void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bi
void spiSimpleTransaction(spi_t * spi); void spiSimpleTransaction(spi_t * spi);
void spiEndTransaction(spi_t * spi); void spiEndTransaction(spi_t * spi);
void spiWriteNL(spi_t * spi, const void * data, uint32_t len); void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len);
void spiWriteByteNL(spi_t * spi, uint8_t data); void spiWriteByteNL(spi_t * spi, uint8_t data);
void spiWriteShortNL(spi_t * spi, uint16_t data); void spiWriteShortNL(spi_t * spi, uint16_t data);
void spiWriteLongNL(spi_t * spi, uint32_t data); void spiWriteLongNL(spi_t * spi, uint32_t data);
void spiWritePixelsNL(spi_t * spi, const void * data, uint32_t len); void spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len);
#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len) #define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len)
uint8_t spiTransferByteNL(spi_t * spi, uint8_t data); uint8_t spiTransferByteNL(spi_t * spi, uint8_t data);

View File

@ -14,6 +14,8 @@
#include "esp32-hal.h" #include "esp32-hal.h"
#include "lwip/apps/sntp.h" #include "lwip/apps/sntp.h"
//#include "tcpip_adapter.h"
#include "esp_netif.h"
static void setTimeZone(long offset, int daylight) static void setTimeZone(long offset, int daylight)
{ {
@ -45,6 +47,8 @@ static void setTimeZone(long offset, int daylight)
* */ * */
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
{ {
//tcpip_adapter_init(); // Should not hurt anything if already inited
esp_netif_init();
if(sntp_enabled()){ if(sntp_enabled()){
sntp_stop(); sntp_stop();
} }
@ -62,6 +66,8 @@ void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1,
* */ * */
void configTzTime(const char* tz, const char* server1, const char* server2, const char* server3) void configTzTime(const char* tz, const char* server1, const char* server2, const char* server3)
{ {
//tcpip_adapter_init(); // Should not hurt anything if already inited
esp_netif_init();
if(sntp_enabled()){ if(sntp_enabled()){
sntp_stop(); sntp_stop();
} }
@ -76,23 +82,15 @@ void configTzTime(const char* tz, const char* server1, const char* server2, cons
bool getLocalTime(struct tm * info, uint32_t ms) bool getLocalTime(struct tm * info, uint32_t ms)
{ {
uint32_t count = ms / 10; uint32_t start = millis();
time_t now; time_t now;
while((millis()-start) <= ms) {
time(&now);
localtime_r(&now, info);
if(info->tm_year > (2016 - 1900)){
return true;
}
while(count--) {
delay(10);
time(&now); time(&now);
localtime_r(&now, info); localtime_r(&now, info);
if(info->tm_year > (2016 - 1900)){ if(info->tm_year > (2016 - 1900)){
return true; return true;
} }
delay(10);
} }
return false; return false;
} }

View File

@ -16,11 +16,27 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h" #include "freertos/xtensa_api.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "rom/ets_sys.h"
#include "soc/timer_group_struct.h" #include "soc/timer_group_struct.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "driver/periph_ctrl.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "esp_intr.h" #include "esp_intr.h"
#endif
#define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock) #define HWTIMER_LOCK() portENTER_CRITICAL(timer->lock)
#define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock) #define HWTIMER_UNLOCK() portEXIT_CRITICAL(timer->lock)
@ -67,11 +83,18 @@ static hw_timer_t hw_timer[4] = {
typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtr)(void);
static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0}; static voidFuncPtr __timerInterruptHandlers[4] = {0,0,0,0};
void IRAM_ATTR __timerISR(void * arg){ void ARDUINO_ISR_ATTR __timerISR(void * arg){
#if CONFIG_IDF_TARGET_ESP32
uint32_t s0 = TIMERG0.int_st_timers.val; uint32_t s0 = TIMERG0.int_st_timers.val;
uint32_t s1 = TIMERG1.int_st_timers.val; uint32_t s1 = TIMERG1.int_st_timers.val;
TIMERG0.int_clr_timers.val = s0; TIMERG0.int_clr_timers.val = s0;
TIMERG1.int_clr_timers.val = s1; 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 status = (s1 & 3) << 2 | (s0 & 3);
uint8_t i = 4; uint8_t i = 4;
//restart the timers that should autoreload //restart the timers that should autoreload
@ -165,6 +188,7 @@ void timerStop(hw_timer_t *timer){
void timerRestart(hw_timer_t *timer){ void timerRestart(hw_timer_t *timer){
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
timer->dev->reload = 1;
timer->dev->config.enable = 1; timer->dev->config.enable = 1;
} }
@ -202,15 +226,29 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
} }
hw_timer_t * timer = &hw_timer[num]; hw_timer_t * timer = &hw_timer[num];
if(timer->group) { if(timer->group) {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN); periph_module_enable(PERIPH_TIMG1_MODULE);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST);
TIMERG1.int_ena.val &= ~BIT(timer->timer);
} else { } else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN); periph_module_enable(PERIPH_TIMG0_MODULE);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST);
TIMERG0.int_ena.val &= ~BIT(timer->timer);
} }
timer->dev->config.enable = 0; timer->dev->config.enable = 0;
if(timer->group) {
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);
#endif
} else {
TIMERG0.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
#else
TIMERG0.int_clr.val = BIT(timer->timer);
#endif
}
#ifdef TIMER_GROUP_SUPPORTS_XTAL_CLOCK
timer->dev->config.use_xtal = 0;
#endif
timerSetDivider(timer, divider); timerSetDivider(timer, divider);
timerSetCountUp(timer, countUp); timerSetCountUp(timer, countUp);
timerSetAutoReload(timer, false); timerSetAutoReload(timer, false);
@ -228,6 +266,9 @@ void timerEnd(hw_timer_t *timer){
} }
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
// EDGE DOES NOT WORK CURRENTLY
edge = false;
static bool initialized = false; static bool initialized = false;
static intr_handle_t intr_handle = NULL; static intr_handle_t intr_handle = NULL;
if(intr_handle){ if(intr_handle){
@ -239,8 +280,18 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
timer->dev->config.alarm_en = 0; timer->dev->config.alarm_en = 0;
if(timer->num & 2){ if(timer->num & 2){
TIMERG1.int_ena.val &= ~BIT(timer->timer); 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);
#endif
} else { } else {
TIMERG0.int_ena.val &= ~BIT(timer->timer); TIMERG0.int_ena.val &= ~BIT(timer->timer);
#if CONFIG_IDF_TARGET_ESP32
TIMERG0.int_clr_timers.val |= BIT(timer->timer);
#else
TIMERG0.int_clr.val = BIT(timer->timer);
#endif
} }
__timerInterruptHandlers[timer->num] = NULL; __timerInterruptHandlers[timer->num] = NULL;
} else { } else {
@ -263,7 +314,7 @@ void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
} }
if(!initialized){ if(!initialized){
initialized = true; initialized = true;
esp_intr_alloc(intr_source, (int)(ESP_INTR_FLAG_IRAM|ESP_INTR_FLAG_LOWMED|ESP_INTR_FLAG_EDGE), __timerISR, NULL, &intr_handle); esp_intr_alloc(intr_source, (int)(ARDUINO_ISR_FLAG|ESP_INTR_FLAG_LOWMED), __timerISR, NULL, &intr_handle);
} else { } else {
intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle)); intr_matrix_set(esp_intr_get_cpu(intr_handle), intr_source, esp_intr_get_intno(intr_handle));
} }

View File

@ -0,0 +1,702 @@
#include "sdkconfig.h"
#if CONFIG_USB_ENABLED
#include <stdlib.h>
#include "esp_log.h"
#include "soc/soc.h"
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/usb_struct.h"
#include "soc/usb_reg.h"
#include "soc/usb_wrap_reg.h"
#include "soc/usb_wrap_struct.h"
#include "soc/periph_defs.h"
#include "soc/timer_group_struct.h"
#include "soc/system_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "tinyusb.h"
#include "esp32-hal.h"
#include "esp32-hal-tinyusb.h"
#include "esp32s2/rom/usb/usb_persist.h"
typedef char tusb_str_t[127];
static bool WEBUSB_ENABLED = false;
static tusb_str_t WEBUSB_URL = "";
static tusb_str_t USB_DEVICE_PRODUCT = "";
static tusb_str_t USB_DEVICE_MANUFACTURER = "";
static tusb_str_t USB_DEVICE_SERIAL = "";
static uint8_t USB_DEVICE_ATTRIBUTES = 0;
static uint16_t USB_DEVICE_POWER = 0;
/*
* Device Descriptor
* */
static tusb_desc_device_t tinyusb_device_descriptor = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
.idVendor = 0,
.idProduct = 0,
.bcdDevice = 0,
.iManufacturer = 0x01,
.iProduct = 0x02,
.iSerialNumber = 0x03,
.bNumConfigurations = 0x01
};
/*
* String Descriptors
* */
#define MAX_STRING_DESCRIPTORS 20
static uint32_t tinyusb_string_descriptor_len = 4;
static char * tinyusb_string_descriptor[MAX_STRING_DESCRIPTORS] = {
// array of pointer to string descriptors
"\x09\x04", // 0: is supported language is English (0x0409)
USB_DEVICE_MANUFACTURER,// 1: Manufacturer
USB_DEVICE_PRODUCT, // 2: Product
USB_DEVICE_SERIAL, // 3: Serials, should use chip ID
};
/* Microsoft OS 2.0 registry property descriptor
Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
device should create DeviceInterfaceGUIDs. It can be done by driver and
in case of real PnP solution device should expose MS "Microsoft OS 2.0
registry property descriptor". Such descriptor can insert any record
into Windows registry per device/configuration/interface. In our case it
will insert "DeviceInterfaceGUIDs" multistring property.
GUID is freshly generated and should be OK to use.
https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/
(Section Microsoft OS compatibility descriptors)
*/
#define MS_OS_20_DESC_LEN 0xB2
static uint8_t const tinyusb_ms_os_20_descriptor[] =
{
// Set header: length, type, windows version, total length
U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
// Configuration subset header: length, type, configuration index, reserved, configuration total length
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A),
// Function Subset header: length, type, first interface, reserved, subset length
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
// MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
// MS OS 2.0 Registry property descriptor: length, type
U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY),
U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
U16_TO_U8S_LE(0x0050), // wPropertyDataLength
//bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”.
'{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00,
'0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
'8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
'8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
};
TU_VERIFY_STATIC(sizeof(tinyusb_ms_os_20_descriptor) == MS_OS_20_DESC_LEN, "Incorrect size");
/*
* BOS Descriptor (required for webUSB)
* */
#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
enum {
VENDOR_REQUEST_WEBUSB = 1,
VENDOR_REQUEST_MICROSOFT = 2
};
static uint8_t const tinyusb_bos_descriptor[] = {
// total length, number of device caps
TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2),
// Vendor Code, iLandingPage
TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1),
// Microsoft OS 2.0 descriptor
TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT)
};
/*
* URL Descriptor (required for webUSB)
* */
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bScheme;
char url[127];
} tinyusb_desc_webusb_url_t;
static tinyusb_desc_webusb_url_t tinyusb_url_descriptor = {
.bLength = 3,
.bDescriptorType = 3, // WEBUSB URL type
.bScheme = 1, // URL Scheme Prefix: 0: "http://", 1: "https://", 255: ""
.url = ""
};
/*
* Configuration Descriptor
* */
static tinyusb_descriptor_cb_t tinyusb_loaded_interfaces_callbacks[USB_INTERFACE_MAX];
static uint32_t tinyusb_loaded_interfaces_mask = 0;
static uint8_t tinyusb_loaded_interfaces_num = 0;
static uint16_t tinyusb_config_descriptor_len = 0;
static uint8_t * tinyusb_config_descriptor = NULL;
/*
* Endpoint Usage Tracking
* */
typedef union {
struct {
uint32_t in:16;
uint32_t out:16;
};
uint32_t val;
} tinyusb_endpoints_usage_t;
static tinyusb_endpoints_usage_t tinyusb_endpoints;
/*
* TinyUSB Callbacks
* */
/**
* @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
*/
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
{
//log_d("%u", index);
return tinyusb_config_descriptor;
}
/**
* @brief Invoked when received GET DEVICE DESCRIPTOR.
*/
uint8_t const *tud_descriptor_device_cb(void)
{
//log_d("");
return (uint8_t const *)&tinyusb_device_descriptor;
}
/**
* @brief Invoked when received GET STRING DESCRIPTOR request.
*/
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
//log_d("%u (0x%x)", index, langid);
static uint16_t _desc_str[127];
uint8_t chr_count;
if (index == 0) {
memcpy(&_desc_str[1], tinyusb_string_descriptor[0], 2);
chr_count = 1;
} else {
// Convert ASCII string into UTF-16
if (index >= tinyusb_string_descriptor_len) {
return NULL;
}
const char *str = tinyusb_string_descriptor[index];
// Cap at max char
chr_count = strlen(str);
if (chr_count > 126) {
chr_count = 126;
}
for (uint8_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
}
// first byte is len, second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
return _desc_str;
}
/**
* @brief Invoked when received GET BOS DESCRIPTOR request.
*/
uint8_t const * tud_descriptor_bos_cb(void)
{
//log_d("");
return tinyusb_bos_descriptor;
}
__attribute__ ((weak)) bool tinyusb_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request){ return false; }
__attribute__ ((weak)) bool tinyusb_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request){ return true; }
/**
* @brief Handle WebUSB and Vendor requests.
*/
bool tud_vendor_control_request_cb(uint8_t rhport, tusb_control_request_t const * request)
{
if(WEBUSB_ENABLED && (request->bRequest == VENDOR_REQUEST_WEBUSB
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
if(request->bRequest == VENDOR_REQUEST_WEBUSB){
// match vendor request in BOS descriptor
// Get landing page url
tinyusb_url_descriptor.bLength = 3 + strlen(WEBUSB_URL);
snprintf(tinyusb_url_descriptor.url, 127, "%s", WEBUSB_URL);
return tud_control_xfer(rhport, request, (void*) &tinyusb_url_descriptor, tinyusb_url_descriptor.bLength);
}
// Get Microsoft OS 2.0 compatible descriptor
uint16_t total_len;
memcpy(&total_len, tinyusb_ms_os_20_descriptor + 8, 2);
return tud_control_xfer(rhport, request, (void*) tinyusb_ms_os_20_descriptor, total_len);
}
return tinyusb_vendor_control_request_cb(rhport, request);
}
bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_request_t const * request)
{
if(!WEBUSB_ENABLED || !(request->bRequest == VENDOR_REQUEST_WEBUSB
|| (request->bRequest == VENDOR_REQUEST_MICROSOFT && request->wIndex == 7))){
return tinyusb_vendor_control_complete_cb(rhport, request);
}
return true;
}
/*
* Required Callbacks
* */
#if CFG_TUD_HID
__attribute__ ((weak)) const uint8_t * tud_hid_descriptor_report_cb(void){return NULL;}
__attribute__ ((weak)) uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen){return 0;}
__attribute__ ((weak)) void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, const uint8_t * buffer, uint16_t bufsize){}
#endif
#if CFG_TUD_MSC
__attribute__ ((weak)) bool tud_msc_test_unit_ready_cb(uint8_t lun){return false;}
__attribute__ ((weak)) void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]){}
__attribute__ ((weak)) void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size){}
__attribute__ ((weak)) int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize){return -1;}
__attribute__ ((weak)) int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize){return -1;}
__attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize){return -1;}
#endif
/*
* Private API
* */
static bool usb_persist_enabled = false;
static restart_type_t usb_persist_mode = RESTART_NO_PERSIST;
static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){
if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){
return false;
}
tinyusb_endpoints.in |= BIT(endpoint);
return true;
}
static bool tinyusb_reserve_out_endpoint(uint8_t endpoint){
if(endpoint > 6 || (tinyusb_endpoints.out & BIT(endpoint)) != 0){
return false;
}
tinyusb_endpoints.out |= BIT(endpoint);
return true;
}
static bool tinyusb_has_available_fifos(void){
uint8_t max_endpoints = 4, active_endpoints = 0;
if (tinyusb_loaded_interfaces_mask & BIT(USB_INTERFACE_CDC)) {
max_endpoints = 5; //CDC endpoint 0x85 is actually not linked to FIFO and not used
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) != 0){
active_endpoints++;
}
}
return active_endpoints < max_endpoints;
}
static uint16_t tinyusb_load_descriptor(tinyusb_interface_t interface, uint8_t * dst, uint8_t * itf)
{
if(tinyusb_loaded_interfaces_callbacks[interface]){
return tinyusb_loaded_interfaces_callbacks[interface](dst, itf);
}
return 0;
}
static bool tinyusb_load_enabled_interfaces(){
tinyusb_config_descriptor_len += TUD_CONFIG_DESC_LEN;
tinyusb_config_descriptor = (uint8_t *)malloc(tinyusb_config_descriptor_len);
if (tinyusb_config_descriptor == NULL) {
log_e("Descriptor Malloc Failed");
return false;
}
uint8_t * dst = tinyusb_config_descriptor + TUD_CONFIG_DESC_LEN;
for(int i=0; i<USB_INTERFACE_MAX; i++){
if (tinyusb_loaded_interfaces_mask & (1U << i)) {
uint16_t len = tinyusb_load_descriptor((tinyusb_interface_t)i, dst, &tinyusb_loaded_interfaces_num);
if (!len) {
log_e("Descriptor Load Failed");
return false;
} else {
if(i == USB_INTERFACE_CDC){
if(!tinyusb_reserve_out_endpoint(3) ||!tinyusb_reserve_in_endpoint(4) || !tinyusb_reserve_in_endpoint(5)){
log_e("CDC Reserve Endpoints Failed");
return false;
}
}
dst += len;
}
}
}
uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB Device");
uint8_t descriptor[TUD_CONFIG_DESC_LEN] = {
//num configs, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, tinyusb_loaded_interfaces_num, str_index, tinyusb_config_descriptor_len, USB_DEVICE_ATTRIBUTES, USB_DEVICE_POWER)
};
memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN);
if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) {
usb_persist_enabled = true;
log_d("USB Persist enabled");
}
log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask);
return true;
}
static inline char nibble_to_hex_char(uint8_t b)
{
if (b < 0xa) {
return '0' + b;
} else {
return 'a' + b - 0xa;
}
}
static void set_usb_serial_num(void)
{
/* Get the MAC address */
const uint32_t mac0 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_MAC_0);
const uint32_t mac1 = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_1_REG, EFUSE_MAC_1);
uint8_t mac_bytes[6];
memcpy(mac_bytes, &mac0, 4);
memcpy(mac_bytes + 4, &mac1, 2);
/* Convert to UTF16 string */
uint8_t* srl = (uint8_t*)USB_DEVICE_SERIAL;
for (int i = 0; i < 6; ++i) {
uint8_t b = mac_bytes[5 - i]; /* printing from the MSB */
if (i) {
*srl++ = ':';
}
*srl++ = nibble_to_hex_char(b >> 4);
*srl++ = nibble_to_hex_char(b & 0xf);
}
*srl++ = '\0';
}
static void tinyusb_apply_device_config(tinyusb_device_config_t *config){
if(config->product_name){
snprintf(USB_DEVICE_PRODUCT, 126, "%s", config->product_name);
}
if(config->manufacturer_name){
snprintf(USB_DEVICE_MANUFACTURER, 126, "%s", config->manufacturer_name);
}
if(config->serial_number && config->serial_number[0]){
snprintf(USB_DEVICE_SERIAL, 126, "%s", config->serial_number);
} else {
set_usb_serial_num();
}
if(config->webusb_url){
snprintf(WEBUSB_URL, 126, "%s", config->webusb_url);
}
WEBUSB_ENABLED = config->webusb_enabled;
USB_DEVICE_ATTRIBUTES = config->usb_attributes;
USB_DEVICE_POWER = config->usb_power_ma;
tinyusb_device_descriptor.bcdUSB = config->usb_version;
tinyusb_device_descriptor.idVendor = config->vid;
tinyusb_device_descriptor.idProduct = config->pid;
tinyusb_device_descriptor.bcdDevice = config->fw_version;
tinyusb_device_descriptor.bDeviceClass = config->usb_class;
tinyusb_device_descriptor.bDeviceSubClass = config->usb_subclass;
tinyusb_device_descriptor.bDeviceProtocol = config->usb_protocol;
}
static void IRAM_ATTR usb_persist_shutdown_handler(void)
{
if(usb_persist_mode != RESTART_NO_PERSIST){
if (usb_persist_enabled) {
REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
}
if (usb_persist_mode == RESTART_BOOTLOADER) {
//USB CDC Download
if (usb_persist_enabled) {
USB_WRAP.date.val = USBDC_PERSIST_ENA;
}
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
periph_module_disable(PERIPH_TIMG1_MODULE);
} else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
//DFU Download
USB_WRAP.date.val = USBDC_BOOT_DFU;
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
periph_module_disable(PERIPH_TIMG0_MODULE);
periph_module_disable(PERIPH_TIMG1_MODULE);
} else if (usb_persist_enabled) {
//USB Persist reboot
USB_WRAP.date.val = USBDC_PERSIST_ENA;
}
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST);
}
}
// USB Device Driver task
// This top level thread processes all usb events and invokes callbacks
static void usb_device_task(void *param) {
(void)param;
while(1) tud_task(); // RTOS forever loop
}
/*
* PUBLIC API
* */
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb)
{
if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){
log_e("Interface %u not enabled", interface);
return ESP_FAIL;
}
tinyusb_loaded_interfaces_mask |= (1U << interface);
tinyusb_config_descriptor_len += descriptor_len;
tinyusb_loaded_interfaces_callbacks[interface] = cb;
log_d("Interface %u enabled", interface);
return ESP_OK;
}
esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
static bool initialized = false;
if(initialized){
return ESP_OK;
}
initialized = true;
tinyusb_endpoints.val = 0;
tinyusb_apply_device_config(config);
if (!tinyusb_load_enabled_interfaces()) {
initialized = false;
return ESP_FAIL;
}
bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA);
if(usb_did_persist && usb_persist_enabled){
// Enable USB/IO_MUX peripheral reset, if coming from persistent reboot
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE);
REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE);
} else {
// Reset USB module
periph_module_reset(PERIPH_USB_MODULE);
periph_module_enable(PERIPH_USB_MODULE);
}
if (usb_persist_enabled && esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
initialized = false;
return ESP_FAIL;
}
tinyusb_config_t tusb_cfg = {
.external_phy = false // In the most cases you need to use a `false` value
};
esp_err_t err = tinyusb_driver_install(&tusb_cfg);
if (err != ESP_OK) {
initialized = false;
return err;
}
xTaskCreate(usb_device_task, "usbd", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
return err;
}
void usb_persist_restart(restart_type_t mode)
{
if (usb_persist_enabled && mode < RESTART_TYPE_MAX) {
usb_persist_mode = mode;
esp_restart();
} else {
log_e("Persistence is not enabled");
}
}
uint8_t tinyusb_add_string_descriptor(const char * str){
if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){
return 0;
}
uint8_t index = tinyusb_string_descriptor_len;
tinyusb_string_descriptor[tinyusb_string_descriptor_len++] = (char*)str;
return index;
}
uint8_t tinyusb_get_free_duplex_endpoint(void){
if(!tinyusb_has_available_fifos()){
log_e("No available IN endpoints");
return 0;
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) == 0){
tinyusb_endpoints.in |= BIT(i);
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
log_e("No available duplex endpoints");
return 0;
}
uint8_t tinyusb_get_free_in_endpoint(void){
if(!tinyusb_has_available_fifos()){
log_e("No available IN endpoints");
return 0;
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0 && (tinyusb_endpoints.out & BIT(i)) != 0){
tinyusb_endpoints.in |= BIT(i);
return i;
}
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.in & BIT(i)) == 0){
tinyusb_endpoints.in |= BIT(i);
return i;
}
}
return 0;
}
uint8_t tinyusb_get_free_out_endpoint(void){
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.out & BIT(i)) == 0 && (tinyusb_endpoints.in & BIT(i)) != 0){
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
for(uint8_t i=1; i<7; i++){
if((tinyusb_endpoints.out & BIT(i)) == 0){
tinyusb_endpoints.out |= BIT(i);
return i;
}
}
return 0;
}
/*
void usb_dw_reg_dump(void)
{
#define USB_PRINT_REG(r) printf("USB0." #r " = 0x%x;\n", USB0.r)
#define USB_PRINT_IREG(i, r) printf("USB0.in_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.in_ep_reg[i].r)
#define USB_PRINT_OREG(i, r) printf("USB0.out_ep_reg[%u]." #r " = 0x%x;\n", i, USB0.out_ep_reg[i].r)
uint8_t i;
USB_PRINT_REG(gotgctl);
USB_PRINT_REG(gotgint);
USB_PRINT_REG(gahbcfg);
USB_PRINT_REG(gusbcfg);
USB_PRINT_REG(grstctl);
USB_PRINT_REG(gintsts);
USB_PRINT_REG(gintmsk);
USB_PRINT_REG(grxstsr);
USB_PRINT_REG(grxstsp);
USB_PRINT_REG(grxfsiz);
USB_PRINT_REG(gnptxsts);
USB_PRINT_REG(gpvndctl);
USB_PRINT_REG(ggpio);
USB_PRINT_REG(guid);
USB_PRINT_REG(gsnpsid);
USB_PRINT_REG(ghwcfg1);
USB_PRINT_REG(ghwcfg2);
USB_PRINT_REG(ghwcfg3);
USB_PRINT_REG(ghwcfg4);
USB_PRINT_REG(glpmcfg);
USB_PRINT_REG(gpwrdn);
USB_PRINT_REG(gdfifocfg);
USB_PRINT_REG(gadpctl);
USB_PRINT_REG(hptxfsiz);
USB_PRINT_REG(hcfg);
USB_PRINT_REG(hfir);
USB_PRINT_REG(hfnum);
USB_PRINT_REG(hptxsts);
USB_PRINT_REG(haint);
USB_PRINT_REG(haintmsk);
USB_PRINT_REG(hflbaddr);
USB_PRINT_REG(hprt);
USB_PRINT_REG(dcfg);
USB_PRINT_REG(dctl);
USB_PRINT_REG(dsts);
USB_PRINT_REG(diepmsk);
USB_PRINT_REG(doepmsk);
USB_PRINT_REG(daint);
USB_PRINT_REG(daintmsk);
USB_PRINT_REG(dtknqr1);
USB_PRINT_REG(dtknqr2);
USB_PRINT_REG(dvbusdis);
USB_PRINT_REG(dvbuspulse);
USB_PRINT_REG(dtknqr3_dthrctl);
USB_PRINT_REG(dtknqr4_fifoemptymsk);
USB_PRINT_REG(deachint);
USB_PRINT_REG(deachintmsk);
USB_PRINT_REG(pcgctrl);
USB_PRINT_REG(pcgctrl1);
USB_PRINT_REG(gnptxfsiz);
for (i = 0; i < 4; i++) {
printf("USB0.dieptxf[%u] = 0x%x;\n", i, USB0.dieptxf[i]);
}
// for (i = 0; i < 16; i++) {
// printf("USB0.diepeachintmsk[%u] = 0x%x;\n", i, USB0.diepeachintmsk[i]);
// }
// for (i = 0; i < 16; i++) {
// printf("USB0.doepeachintmsk[%u] = 0x%x;\n", i, USB0.doepeachintmsk[i]);
// }
for (i = 0; i < 7; i++) {
printf("// EP %u:\n", i);
USB_PRINT_IREG(i, diepctl);
USB_PRINT_IREG(i, diepint);
USB_PRINT_IREG(i, dieptsiz);
USB_PRINT_IREG(i, diepdma);
USB_PRINT_IREG(i, dtxfsts);
USB_PRINT_OREG(i, doepctl);
USB_PRINT_OREG(i, doepint);
USB_PRINT_OREG(i, doeptsiz);
USB_PRINT_OREG(i, doepdma);
}
}
*/
#endif /* CONFIG_USB_ENABLED */

View File

@ -0,0 +1,103 @@
// Copyright 2015-2020 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
#include "esp32-hal.h"
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_USB_ENABLED
#ifdef __cplusplus
extern "C" {
#endif
#include "tinyusb.h"
typedef struct {
uint16_t vid;
uint16_t pid;
const char * product_name;
const char * manufacturer_name;
const char * serial_number;
uint16_t fw_version;
uint16_t usb_version;
uint8_t usb_class;
uint8_t usb_subclass;
uint8_t usb_protocol;
uint8_t usb_attributes;
uint16_t usb_power_ma;
bool webusb_enabled;
const char * webusb_url;
} tinyusb_device_config_t;
#define TINYUSB_CONFIG_DEFAULT() { \
.vid = USB_ESPRESSIF_VID, \
.pid = 0x0002, \
.product_name = CONFIG_USB_DESC_PRODUCT_STRING, \
.manufacturer_name = CONFIG_USB_DESC_MANUFACTURER_STRING, \
.serial_number = CONFIG_USB_DESC_SERIAL_STRING, \
.fw_version = CONFIG_USB_DESC_BCDDEVICE, \
.usb_version = 0x0200, \
.usb_class = TUSB_CLASS_MISC, \
.usb_subclass = MISC_SUBCLASS_COMMON, \
.usb_protocol = MISC_PROTOCOL_IAD, \
.usb_attributes = TUSB_DESC_CONFIG_ATT_SELF_POWERED, \
.usb_power_ma = 500, \
.webusb_enabled = false, \
.webusb_url = "espressif.github.io/arduino-esp32/webusb.html" \
}
esp_err_t tinyusb_init(tinyusb_device_config_t *config);
/*
* USB Persistence API
* */
typedef enum {
RESTART_NO_PERSIST,
RESTART_PERSIST,
RESTART_BOOTLOADER,
RESTART_BOOTLOADER_DFU,
RESTART_TYPE_MAX
} restart_type_t;
void usb_persist_restart(restart_type_t mode);
// The following definitions and functions are to be used only by the drivers
typedef enum {
USB_INTERFACE_CDC,
USB_INTERFACE_DFU,
USB_INTERFACE_HID,
USB_INTERFACE_VENDOR,
USB_INTERFACE_MSC,
USB_INTERFACE_MIDI,
USB_INTERFACE_CUSTOM,
USB_INTERFACE_MAX
} tinyusb_interface_t;
typedef uint16_t (*tinyusb_descriptor_cb_t)(uint8_t * dst, uint8_t * itf);
esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb);
uint8_t tinyusb_add_string_descriptor(const char * str);
uint8_t tinyusb_get_free_duplex_endpoint(void);
uint8_t tinyusb_get_free_in_endpoint(void);
uint8_t tinyusb_get_free_out_endpoint(void);
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_USB_ENABLED */
#endif /* CONFIG_IDF_TARGET_ESP32S2 */

View File

@ -15,12 +15,29 @@
#include "esp32-hal-touch.h" #include "esp32-hal-touch.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "soc/rtc_io_reg.h" #include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h" #include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/touch_sensor.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "esp_intr.h"
#endif
static uint16_t __touchSleepCycles = 0x1000; static uint16_t __touchSleepCycles = 0x1000;
static uint16_t __touchMeasureCycles = 0x1000; static uint16_t __touchMeasureCycles = 0x1000;
@ -29,8 +46,9 @@ typedef void (*voidFuncPtr)(void);
static voidFuncPtr __touchInterruptHandlers[10] = {0,}; static voidFuncPtr __touchInterruptHandlers[10] = {0,};
static intr_handle_t touch_intr_handle = NULL; static intr_handle_t touch_intr_handle = NULL;
void IRAM_ATTR __touchISR(void * arg) void ARDUINO_ISR_ATTR __touchISR(void * arg)
{ {
#if CONFIG_IDF_TARGET_ESP32
uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff; uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG); uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
uint8_t i = 0; uint8_t i = 0;
@ -47,16 +65,21 @@ void IRAM_ATTR __touchISR(void * arg)
} }
} }
} }
#endif
} }
void __touchSetCycles(uint16_t measure, uint16_t sleep) void __touchSetCycles(uint16_t measure, uint16_t sleep)
{ {
__touchSleepCycles = sleep; __touchSleepCycles = sleep;
__touchMeasureCycles = measure; __touchMeasureCycles = measure;
#if CONFIG_IDF_TARGET_ESP32
//Touch pad SleepCycle Time //Touch pad SleepCycle Time
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S); SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S);
//Touch Pad Measure Time //Touch Pad Measure Time
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S); SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S);
#else
touch_pad_set_meas_time(sleep, measure);
#endif
} }
void __touchInit() void __touchInit()
@ -66,15 +89,27 @@ void __touchInit()
return; return;
} }
initialized = true; initialized = true;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S); SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR); SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
//clear touch enable //clear touch enable
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0); WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_TOUCH_SLP_TIMER_EN);
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles); __touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __touchISR, NULL, &touch_intr_handle);
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __touchISR, NULL, &touch_intr_handle); #else
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5);
touch_pad_set_idle_channel_connect(TOUCH_PAD_CONN_GND);
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
touch_pad_denoise_t denoise = {
.grade = TOUCH_PAD_DENOISE_BIT4,
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
};
touch_pad_denoise_set_config(&denoise);
touch_pad_denoise_enable();
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
touch_pad_fsm_start();
#endif
} }
uint16_t __touchRead(uint8_t pin) uint16_t __touchRead(uint8_t pin)
@ -88,6 +123,7 @@ uint16_t __touchRead(uint8_t pin)
__touchInit(); __touchInit();
#if CONFIG_IDF_TARGET_ESP32
uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG); uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
//Disable Intr & enable touch pad //Disable Intr & enable touch pad
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG,
@ -119,6 +155,25 @@ uint16_t __touchRead(uint8_t pin)
//restore previous value //restore previous value
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0); WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
return touch_value; return touch_value;
#else
static uint32_t chan_mask = 0;
uint32_t value = 0;
if((chan_mask & (1 << pad)) == 0){
if(touch_pad_set_thresh((touch_pad_t)pad, TOUCH_PAD_THRESHOLD_MAX) != ESP_OK){
log_e("touch_pad_set_thresh failed");
} else if(touch_pad_config((touch_pad_t)pad) != ESP_OK){
log_e("touch_pad_config failed");
} else {
chan_mask |= (1 << pad);
}
}
if((chan_mask & (1 << pad)) != 0) {
if(touch_pad_read_raw_data((touch_pad_t)pad, &value) != ESP_OK){
log_e("touch_pad_read_raw_data failed");
}
}
return value;
#endif
} }
void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold)
@ -134,6 +189,7 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
__touchInterruptHandlers[pad] = userFunc; __touchInterruptHandlers[pad] = userFunc;
#if CONFIG_IDF_TARGET_ESP32
//clear touch force ,select the Touch mode is Timer //clear touch force ,select the Touch mode is Timer
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M); CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
@ -161,6 +217,9 @@ void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t thresh
(1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \ (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \
(1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \ (1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \
(1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))); (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)));
#else
#endif
} }
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead"))); extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));

View File

@ -18,10 +18,7 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_intr.h"
#include "rom/uart.h"
#include "soc/uart_reg.h" #include "soc/uart_reg.h"
#include "soc/uart_struct.h" #include "soc/uart_struct.h"
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
@ -30,10 +27,37 @@
#include "soc/rtc.h" #include "soc/rtc.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/uart.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/uart.h"
#include "soc/periph_defs.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#include "rom/uart.h"
#include "esp_intr.h"
#endif
#if CONFIG_IDF_TARGET_ESP32S2
#define UART_PORTS_NUM 2
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:0))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:0))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:0))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:0))
#else
#define UART_PORTS_NUM 3
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0))) #define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0)))
#define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0))) #define UART_RXD_IDX(u) ((u==0)?U0RXD_IN_IDX:( (u==1)?U1RXD_IN_IDX:( (u==2)?U2RXD_IN_IDX:0)))
#define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0))) #define UART_TXD_IDX(u) ((u==0)?U0TXD_OUT_IDX:( (u==1)?U1TXD_OUT_IDX:( (u==2)?U2TXD_OUT_IDX:0)))
#define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0))) #define UART_INTR_SOURCE(u) ((u==0)?ETS_UART0_INTR_SOURCE:( (u==1)?ETS_UART1_INTR_SOURCE:((u==2)?ETS_UART2_INTR_SOURCE:0)))
#endif
static int s_uart_debug_nr = 0; static int s_uart_debug_nr = 0;
@ -51,31 +75,35 @@ struct uart_struct_t {
#define UART_MUTEX_LOCK() #define UART_MUTEX_LOCK()
#define UART_MUTEX_UNLOCK() #define UART_MUTEX_UNLOCK()
static uart_t _uart_bus_array[3] = { static uart_t _uart_bus_array[] = {
{(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL, NULL}, {&UART0, 0, NULL, NULL},
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL, NULL}, {&UART1, 1, NULL, NULL},
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL, NULL} #if CONFIG_IDF_TARGET_ESP32
{&UART2, 2, NULL, NULL}
#endif
}; };
#else #else
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS) #define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock) #define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
static uart_t _uart_bus_array[3] = { static uart_t _uart_bus_array[] = {
{(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL, NULL}, {&UART0, NULL, 0, NULL, NULL},
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL, NULL}, {&UART1, NULL, 1, NULL, NULL},
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL, NULL} #if CONFIG_IDF_TARGET_ESP32
{&UART2, NULL, 2, NULL, NULL}
#endif
}; };
#endif #endif
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb); static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
static void IRAM_ATTR _uart_isr(void *arg) static void ARDUINO_ISR_ATTR _uart_isr(void *arg)
{ {
uint8_t i, c; uint8_t i, c;
BaseType_t xHigherPriorityTaskWoken; BaseType_t xHigherPriorityTaskWoken;
uart_t* uart; uart_t* uart;
for(i=0;i<3;i++){ for(i=0;i<UART_PORTS_NUM;i++){
uart = &_uart_bus_array[i]; uart = &_uart_bus_array[i];
if(uart->intr_handle == NULL){ if(uart->intr_handle == NULL){
continue; continue;
@ -83,9 +111,15 @@ static void IRAM_ATTR _uart_isr(void *arg)
uart->dev->int_clr.rxfifo_full = 1; uart->dev->int_clr.rxfifo_full = 1;
uart->dev->int_clr.frm_err = 1; uart->dev->int_clr.frm_err = 1;
uart->dev->int_clr.rxfifo_tout = 1; uart->dev->int_clr.rxfifo_tout = 1;
#if CONFIG_IDF_TARGET_ESP32
while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) { while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
c = uart->dev->fifo.rw_byte; c = uart->dev->fifo.rw_byte;
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) { #else
uint32_t fifo_reg = UART_FIFO_AHB_REG(i);
while(uart->dev->status.rxfifo_cnt) {
c = ESP_REG(fifo_reg);
#endif
if(uart->queue != NULL) {
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken); xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
} }
} }
@ -100,14 +134,18 @@ void uartEnableInterrupt(uart_t* uart)
{ {
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
uart->dev->conf1.rxfifo_full_thrhd = 112; uart->dev->conf1.rxfifo_full_thrhd = 112;
#if CONFIG_IDF_TARGET_ESP32
uart->dev->conf1.rx_tout_thrhd = 2; uart->dev->conf1.rx_tout_thrhd = 2;
#else
uart->dev->mem_conf.rx_tout_thrhd = 2;
#endif
uart->dev->conf1.rx_tout_en = 1; uart->dev->conf1.rx_tout_en = 1;
uart->dev->int_ena.rxfifo_full = 1; uart->dev->int_ena.rxfifo_full = 1;
uart->dev->int_ena.frm_err = 1; uart->dev->int_ena.frm_err = 1;
uart->dev->int_ena.rxfifo_tout = 1; uart->dev->int_ena.rxfifo_tout = 1;
uart->dev->int_clr.val = 0xffffffff; uart->dev->int_clr.val = 0xffffffff;
esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, NULL, &uart->intr_handle); esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ARDUINO_ISR_FLAG, _uart_isr, NULL, &uart->intr_handle);
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
} }
@ -143,7 +181,7 @@ void uartDetachTx(uart_t* uart)
void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted) void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
{ {
if(uart == NULL || rxPin > 39) { if(uart == NULL || rxPin >= GPIO_PIN_COUNT) {
return; return;
} }
pinMode(rxPin, INPUT); pinMode(rxPin, INPUT);
@ -153,7 +191,7 @@ void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted)
void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted) void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
{ {
if(uart == NULL || txPin > 39) { if(uart == NULL || txPin >= GPIO_PIN_COUNT) {
return; return;
} }
pinMode(txPin, OUTPUT); pinMode(txPin, OUTPUT);
@ -162,7 +200,7 @@ void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted)
uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted) uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rxPin, int8_t txPin, uint16_t queueLen, bool inverted)
{ {
if(uart_nr > 2) { if(uart_nr >= UART_PORTS_NUM) {
return NULL; return NULL;
} }
@ -190,9 +228,11 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
if(uart_nr == 1){ if(uart_nr == 1){
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST);
#if CONFIG_IDF_TARGET_ESP32
} else if(uart_nr == 2){ } else if(uart_nr == 2){
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST);
#endif
} else { } else {
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST);
@ -208,6 +248,11 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF; uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
uart->dev->rs485_conf.dl1_en = 1; uart->dev->rs485_conf.dl1_en = 1;
} }
// tx_idle_num : idle interval after tx FIFO is empty(unit: the time it takes to send one bit under current baudrate)
// Setting it to 0 prevents line idle time/delays when sending messages with small intervals
uart->dev->idle_conf.tx_idle_num = 0; //
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
if(rxPin != -1) { if(rxPin != -1) {
@ -217,7 +262,6 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
if(txPin != -1) { if(txPin != -1) {
uartAttachTx(uart, txPin, inverted); uartAttachTx(uart, txPin, inverted);
} }
addApbChangeCallback(uart, uart_on_apb_change); addApbChangeCallback(uart, uart_on_apb_change);
return uart; return uart;
} }
@ -253,7 +297,7 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
vQueueDelete(uart->queue); vQueueDelete(uart->queue);
uart->queue = xQueueCreate(new_size, sizeof(uint8_t)); uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
if(uart->queue == NULL) { if(uart->queue == NULL) {
return NULL; return 0;
} }
} }
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
@ -266,7 +310,7 @@ uint32_t uartAvailable(uart_t* uart)
if(uart == NULL || uart->queue == NULL) { if(uart == NULL || uart->queue == NULL) {
return 0; return 0;
} }
return uxQueueMessagesWaiting(uart->queue); return (uxQueueMessagesWaiting(uart->queue) + uart->dev->status.rxfifo_cnt) ;
} }
uint32_t uartAvailableForWrite(uart_t* uart) uint32_t uartAvailableForWrite(uart_t* uart)
@ -277,12 +321,41 @@ uint32_t uartAvailableForWrite(uart_t* uart)
return 0x7f - uart->dev->status.txfifo_cnt; return 0x7f - uart->dev->status.txfifo_cnt;
} }
void uartRxFifoToQueue(uart_t* uart)
{
uint8_t c;
UART_MUTEX_LOCK();
//disable interrupts
uart->dev->int_ena.val = 0;
uart->dev->int_clr.val = 0xffffffff;
#if CONFIG_IDF_TARGET_ESP32
while (uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
c = uart->dev->fifo.rw_byte;
#else
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
while (uart->dev->status.rxfifo_cnt) {
c = ESP_REG(fifo_reg);
#endif
xQueueSend(uart->queue, &c, 0);
}
//enable interrupts
uart->dev->int_ena.rxfifo_full = 1;
uart->dev->int_ena.frm_err = 1;
uart->dev->int_ena.rxfifo_tout = 1;
uart->dev->int_clr.val = 0xffffffff;
UART_MUTEX_UNLOCK();
}
uint8_t uartRead(uart_t* uart) uint8_t uartRead(uart_t* uart)
{ {
if(uart == NULL || uart->queue == NULL) { if(uart == NULL || uart->queue == NULL) {
return 0; return 0;
} }
uint8_t c; uint8_t c;
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
{
uartRxFifoToQueue(uart);
}
if(xQueueReceive(uart->queue, &c, 0)) { if(xQueueReceive(uart->queue, &c, 0)) {
return c; return c;
} }
@ -295,6 +368,10 @@ uint8_t uartPeek(uart_t* uart)
return 0; return 0;
} }
uint8_t c; uint8_t c;
if ((uxQueueMessagesWaiting(uart->queue) == 0) && (uart->dev->status.rxfifo_cnt > 0))
{
uartRxFifoToQueue(uart);
}
if(xQueuePeek(uart->queue, &c, 0)) { if(xQueuePeek(uart->queue, &c, 0)) {
return c; return c;
} }
@ -308,7 +385,11 @@ void uartWrite(uart_t* uart, uint8_t c)
} }
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
while(uart->dev->status.txfifo_cnt == 0x7F); while(uart->dev->status.txfifo_cnt == 0x7F);
#if CONFIG_IDF_TARGET_ESP32
uart->dev->fifo.rw_byte = c; uart->dev->fifo.rw_byte = c;
#else
ESP_REG(UART_FIFO_AHB_REG(uart->num)) = c;
#endif
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
} }
@ -318,31 +399,53 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
return; return;
} }
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
#ifndef CONFIG_IDF_TARGET_ESP32
uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
#endif
while(len) { while(len) {
while(uart->dev->status.txfifo_cnt == 0x7F); while(uart->dev->status.txfifo_cnt == 0x7F);
#if CONFIG_IDF_TARGET_ESP32
uart->dev->fifo.rw_byte = *data++; uart->dev->fifo.rw_byte = *data++;
#else
ESP_REG(fifo_reg) = *data++;
#endif
len--; len--;
} }
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
} }
void uartFlush(uart_t* uart) void uartFlush(uart_t* uart)
{
uartFlushTxOnly(uart,false);
}
void uartFlushTxOnly(uart_t* uart, bool txOnly)
{ {
if(uart == NULL) { if(uart == NULL) {
return; return;
} }
UART_MUTEX_LOCK(); UART_MUTEX_LOCK();
#if CONFIG_IDF_TARGET_ESP32
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out); while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
if( !txOnly ){
//Due to hardware issue, we can not use fifo_rst to reset uart fifo.
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
//Due to hardware issue, we can not use fifo_rst to reset uart fifo. // we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later. while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
READ_PERI_REG(UART_FIFO_REG(uart->num));
}
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`. xQueueReset(uart->queue);
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
READ_PERI_REG(UART_FIFO_REG(uart->num));
} }
#else
while(uart->dev->status.txfifo_cnt);
uart->dev->conf0.txfifo_rst = 1;
uart->dev->conf0.txfifo_rst = 0;
#endif
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
} }
@ -368,18 +471,31 @@ static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old
uart->dev->int_clr.val = 0xffffffff; uart->dev->int_clr.val = 0xffffffff;
// read RX fifo // read RX fifo
uint8_t c; uint8_t c;
BaseType_t xHigherPriorityTaskWoken; // BaseType_t xHigherPriorityTaskWoken;
#if CONFIG_IDF_TARGET_ESP32
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) { while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
c = uart->dev->fifo.rw_byte; c = uart->dev->fifo.rw_byte;
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) { #else
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken); uint32_t fifo_reg = UART_FIFO_AHB_REG(uart->num);
while(uart->dev->status.rxfifo_cnt != 0) {
c = ESP_REG(fifo_reg);
#endif
if(uart->queue != NULL ) {
xQueueSend(uart->queue, &c, 1); //&xHigherPriorityTaskWoken);
} }
} }
UART_MUTEX_UNLOCK();
// wait TX empty // wait TX empty
#if CONFIG_IDF_TARGET_ESP32
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out); while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
#else
while(uart->dev->status.txfifo_cnt);
#endif
} else { } else {
//todo: //todo:
// set baudrate // set baudrate
UART_MUTEX_LOCK();
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F); uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
uint32_t baud_rate = ((old_apb<<4)/clk_div); uint32_t baud_rate = ((old_apb<<4)/clk_div);
clk_div = ((new_apb<<4)/baud_rate); clk_div = ((new_apb<<4)/baud_rate);
@ -399,27 +515,44 @@ uint32_t uartGetBaudRate(uart_t* uart)
if(uart == NULL) { if(uart == NULL) {
return 0; return 0;
} }
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F); uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
if(!clk_div) {
return 0;
}
return ((getApbFrequency()<<4)/clk_div); return ((getApbFrequency()<<4)/clk_div);
} }
static void IRAM_ATTR uart0_write_char(char c) static void ARDUINO_ISR_ATTR uart0_write_char(char c)
{ {
#if CONFIG_IDF_TARGET_ESP32
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART_BASE) = c; ESP_REG(DR_REG_UART_BASE) = c;
#else
while(UART0.status.txfifo_cnt == 0x7F);
WRITE_PERI_REG(UART_FIFO_AHB_REG(0), c);
#endif
} }
static void IRAM_ATTR uart1_write_char(char c) static void ARDUINO_ISR_ATTR uart1_write_char(char c)
{ {
#if CONFIG_IDF_TARGET_ESP32
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART1_BASE) = c; ESP_REG(DR_REG_UART1_BASE) = c;
#else
while(UART1.status.txfifo_cnt == 0x7F);
WRITE_PERI_REG(UART_FIFO_AHB_REG(1), c);
#endif
} }
static void IRAM_ATTR uart2_write_char(char c) #if CONFIG_IDF_TARGET_ESP32
static void ARDUINO_ISR_ATTR uart2_write_char(char c)
{ {
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART2_BASE) = c; ESP_REG(DR_REG_UART2_BASE) = c;
} }
#endif
void uart_install_putc() void uart_install_putc()
{ {
@ -430,9 +563,11 @@ void uart_install_putc()
case 1: case 1:
ets_install_putc1((void (*)(char)) &uart1_write_char); ets_install_putc1((void (*)(char)) &uart1_write_char);
break; break;
#if CONFIG_IDF_TARGET_ESP32
case 2: case 2:
ets_install_putc1((void (*)(char)) &uart2_write_char); ets_install_putc1((void (*)(char)) &uart2_write_char);
break; break;
#endif
default: default:
ets_install_putc1(NULL); ets_install_putc1(NULL);
break; break;
@ -441,7 +576,7 @@ void uart_install_putc()
void uartSetDebug(uart_t* uart) void uartSetDebug(uart_t* uart)
{ {
if(uart == NULL || uart->num > 2) { if(uart == NULL || uart->num >= UART_PORTS_NUM) {
s_uart_debug_nr = -1; s_uart_debug_nr = -1;
//ets_install_putc1(NULL); //ets_install_putc1(NULL);
//return; //return;
@ -460,9 +595,6 @@ int uartGetDebug()
int log_printf(const char *format, ...) int log_printf(const char *format, ...)
{ {
if(s_uart_debug_nr < 0){
return 0;
}
static char loc_buf[64]; static char loc_buf[64];
char * temp = loc_buf; char * temp = loc_buf;
int len; int len;
@ -480,7 +612,7 @@ int log_printf(const char *format, ...)
} }
vsnprintf(temp, len+1, format, arg); vsnprintf(temp, len+1, format, arg);
#if !CONFIG_DISABLE_HAL_LOCKS #if !CONFIG_DISABLE_HAL_LOCKS
if(_uart_bus_array[s_uart_debug_nr].lock){ if(s_uart_debug_nr != -1 && _uart_bus_array[s_uart_debug_nr].lock){
xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY); xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY);
ets_printf("%s", temp); ets_printf("%s", temp);
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock); xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
@ -520,6 +652,14 @@ unsigned long uartBaudrateDetect(uart_t *uart, bool flg)
* detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is * detected calling uartBadrateDetect(). The raw baudrate is computed using the UART_CLK_FREQ. The raw baudrate is
* rounded to the closed real baudrate. * rounded to the closed real baudrate.
*/ */
void uartStartDetectBaudrate(uart_t *uart) {
if(!uart) return;
uart->dev->auto_baud.glitch_filt = 0x08;
uart->dev->auto_baud.en = 0;
uart->dev->auto_baud.en = 1;
}
unsigned long unsigned long
uartDetectBaudrate(uart_t *uart) uartDetectBaudrate(uart_t *uart)
{ {
@ -563,5 +703,9 @@ uartDetectBaudrate(uart_t *uart)
* Returns the status of the RX state machine, if the value is non-zero the state machine is active. * Returns the status of the RX state machine, if the value is non-zero the state machine is active.
*/ */
bool uartRxActive(uart_t* uart) { bool uartRxActive(uart_t* uart) {
#if CONFIG_IDF_TARGET_ESP32
return uart->dev->status.st_urx_out != 0; return uart->dev->status.st_urx_out != 0;
#else
return 0;
#endif
} }

View File

@ -63,6 +63,7 @@ void uartWrite(uart_t* uart, uint8_t c);
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len); void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len);
void uartFlush(uart_t* uart); void uartFlush(uart_t* uart);
void uartFlushTxOnly(uart_t* uart, bool txOnly );
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate); void uartSetBaudRate(uart_t* uart, uint32_t baud_rate);
uint32_t uartGetBaudRate(uart_t* uart); uint32_t uartGetBaudRate(uart_t* uart);
@ -72,6 +73,7 @@ size_t uartResizeRxBuffer(uart_t* uart, size_t new_size);
void uartSetDebug(uart_t* uart); void uartSetDebug(uart_t* uart);
int uartGetDebug(); int uartGetDebug();
void uartStartDetectBaudrate(uart_t *uart);
unsigned long uartDetectBaudrate(uart_t *uart); unsigned long uartDetectBaudrate(uart_t *uart);
bool uartRxActive(uart_t* uart); bool uartRxActive(uart_t* uart);

View File

@ -20,10 +20,6 @@
#ifndef HAL_ESP32_HAL_H_ #ifndef HAL_ESP32_HAL_H_
#define HAL_ESP32_HAL_H_ #define HAL_ESP32_HAL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -34,9 +30,34 @@ extern "C" {
#include <math.h> #include <math.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_sleep.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef F_CPU #ifndef F_CPU
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U) #define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U)
#elif CONFIG_IDF_TARGET_ESP32S2
#define F_CPU (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000U)
#endif
#endif
#if CONFIG_ARDUINO_ISR_IRAM
#define ARDUINO_ISR_ATTR IRAM_ATTR
#define ARDUINO_ISR_FLAG ESP_INTR_FLAG_IRAM
#else
#define ARDUINO_ISR_ATTR
#define ARDUINO_ISR_FLAG (0)
#endif
#ifndef ARDUINO_RUNNING_CORE
#define ARDUINO_RUNNING_CORE CONFIG_ARDUINO_RUNNING_CORE
#endif
#ifndef ARDUINO_EVENT_RUNNING_CORE
#define ARDUINO_EVENT_RUNNING_CORE CONFIG_ARDUINO_EVENT_RUNNING_CORE
#endif #endif
//forward declaration from freertos/portmacro.h //forward declaration from freertos/portmacro.h
@ -64,12 +85,6 @@ void yield(void);
#include "esp32-hal-psram.h" #include "esp32-hal-psram.h"
#include "esp32-hal-cpu.h" #include "esp32-hal-cpu.h"
#ifndef BOARD_HAS_PSRAM
#ifdef CONFIG_SPIRAM_SUPPORT
#undef CONFIG_SPIRAM_SUPPORT
#endif
#endif
//returns chip temperature in Celsius //returns chip temperature in Celsius
float temperatureRead(); float temperatureRead();
@ -90,6 +105,16 @@ void enableCore1WDT();
void disableCore1WDT(); void disableCore1WDT();
#endif #endif
//if xCoreID < 0 or CPU is unicore, it will use xTaskCreate, else xTaskCreatePinnedToCore
//allows to easily handle all possible situations without repetitive code
BaseType_t xTaskCreateUniversal( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask,
const BaseType_t xCoreID );
unsigned long micros(); unsigned long micros();
unsigned long millis(); unsigned long millis();
void delay(uint32_t); void delay(uint32_t);

View File

@ -18,7 +18,7 @@
#define _ESP8266_COMPAT_H_ #define _ESP8266_COMPAT_H_
#define ICACHE_FLASH_ATTR #define ICACHE_FLASH_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR #define ICACHE_RAM_ATTR ARDUINO_ISR_ATTR
#endif /* _ESP8266_COMPAT_H_ */ #endif /* _ESP8266_COMPAT_H_ */

View File

@ -2,15 +2,22 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "Arduino.h" #include "Arduino.h"
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
#include "USB.h"
#endif
TaskHandle_t loopTaskHandle = NULL; TaskHandle_t loopTaskHandle = NULL;
#if CONFIG_AUTOSTART_ARDUINO #if CONFIG_AUTOSTART_ARDUINO
#if CONFIG_FREERTOS_UNICORE #if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0 void yieldIfNecessary(void){
#else static uint64_t lastYield = 0;
#define ARDUINO_RUNNING_CORE 1 uint64_t now = millis();
if((now - lastYield) > 2000) {
lastYield = now;
vTaskDelay(5); //delay 1 RTOS tick
}
}
#endif #endif
bool loopTaskWDTEnabled; bool loopTaskWDTEnabled;
@ -19,18 +26,25 @@ void loopTask(void *pvParameters)
{ {
setup(); setup();
for(;;) { for(;;) {
#if CONFIG_FREERTOS_UNICORE
yieldIfNecessary();
#endif
if(loopTaskWDTEnabled){ if(loopTaskWDTEnabled){
esp_task_wdt_reset(); esp_task_wdt_reset();
} }
loop(); loop();
if (serialEventRun) serialEventRun();
} }
} }
extern "C" void app_main() extern "C" void app_main()
{ {
#if ARDUINO_SERIAL_PORT //Serial used for USB CDC
USB.begin();
#endif
loopTaskWDTEnabled = false; loopTaskWDTEnabled = false;
initArduino(); initArduino();
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE); xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
} }
#endif #endif

View File

@ -32,7 +32,6 @@ typedef unsigned long prog_uint32_t;
#define PROGMEM #define PROGMEM
#define PGM_P const char * #define PGM_P const char *
#define PGM_VOID_P const void * #define PGM_VOID_P const void *
#define FPSTR(p) ((const char *)(p))
#define PSTR(s) (s) #define PSTR(s) (s)
#define _SFR_BYTE(n) (n) #define _SFR_BYTE(n) (n)

View File

@ -1,13 +1,12 @@
Installation instructions using Arduino IDE Boards Manager ## Installation instructions using Arduino IDE Boards Manager
========================================================== ### ==========================================================
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32 and 64 bit). - Stable release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
- Development release link: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json`
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32, 64 bit and ARM).
- Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software). - Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the [Arduino website](http://www.arduino.cc/en/main/software).
- Start Arduino and open Preferences window. - Start Arduino and open Preferences window.
- Enter ```https://dl.espressif.com/dl/package_esp32_index.json``` into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas. - Enter one of the release links above into *Additional Board Manager URLs* field. You can add multiple URLs, separating them with commas.
- Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation). - Open Boards Manager from Tools > Board menu and install *esp32* platform (and don't forget to select your ESP32 board from Tools > Board menu after installation).
Stable release link: `https://dl.espressif.com/dl/package_esp32_index.json`
Development release link: `https://dl.espressif.com/dl/package_esp32_dev_index.json`

View File

@ -23,5 +23,7 @@ Installation instructions for Mac OS
- Try `python3` instead of `python` if you get the error: `IOError: [Errno socket error] [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)` when running `python get.py` - Try `python3` instead of `python` if you get the error: `IOError: [Errno socket error] [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)` when running `python get.py`
- If you get the following error when running `python get.py` urllib.error.URLError: <urlopen error SSL: CERTIFICATE_VERIFY_FAILED, go to Macintosh HD > Applications > Python3.6 folder (or any other python version), and run the following scripts: Install Certificates.command and Update Shell Profile.command
- Restart Arduino IDE - Restart Arduino IDE

View File

@ -1,6 +1,10 @@
To use as a component of ESP-IDF To use as a component of ESP-IDF
================================================= =================================================
## esp32-arduino-lib-builder
For a simplified method, see [lib-builder](lib_builder.md)
## Installation ## Installation
- Download and install [esp-idf](https://github.com/espressif/esp-idf) - Download and install [esp-idf](https://github.com/espressif/esp-idf)

14
docs/lib_builder.md Normal file
View File

@ -0,0 +1,14 @@
## Using esp32-arduino-lib-builder to compile custom libraries
Espressif has provided a [tool](https://github.com/espressif/esp32-arduino-lib-builder) to simplify building your own compiled libraries for use in Arduino IDE (or your favorite IDE).
To use it to generate custom libraries, follow these steps:
1. `git clone https://github.com/espressif/esp32-arduino-lib-builder`
2. `cd esp32-arduino-lib-builder`
3. `./tools/update-components.sh`
4. `./tools/install-esp-idf.sh` (if you already have an $IDF_PATH defined, it will use your local copy of the repository)
5. `make menuconfig` or directly edit sdkconfig.
6. `./build.sh`
The script automates the process of building [arduino as an ESP-IDF component](https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md).
Once it is complete, you can cherry pick the needed libraries from `out/tools/sdk/lib`, or run `tools/copy-to-arduino.sh` to copy the entire built system.
`tools/config.sh` contains a number of variables that control the process, particularly the $IDF_BRANCH variable. You can adjust this to try building against newer versions, but there are absolutely no guarantees that any components will work or even successfully compile against a newer IDF.

View File

@ -1,11 +1,11 @@
Installation instructions for using PlatformIO Installation instructions for using PlatformIO
================================================= =================================================
- [What is PlatformIO?](http://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32) - [What is PlatformIO?](https://docs.platformio.org/en/latest/what-is-platformio.html?utm_source=github&utm_medium=arduino-esp32)
- [PlatformIO IDE](http://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32) - [PlatformIO IDE](https://platformio.org/platformio-ide?utm_source=github&utm_medium=arduino-esp32)
- [PlatformIO Core](http://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool) - [PlatformIO Core](https://docs.platformio.org/en/latest/core.html?utm_source=github&utm_medium=arduino-esp32) (command line tool)
- [Advanced usage](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) - - [Advanced usage](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32) -
custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version custom settings, uploading to SPIFFS, Over-the-Air (OTA), staging version
- [Integration with Cloud and Standalone IDEs](http://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) - - [Integration with Cloud and Standalone IDEs](https://docs.platformio.org/en/latest/ide.html?utm_source=github&utm_medium=arduino-esp32) -
Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode Cloud9, Codeanywhere, Eclipse Che (Codenvy), Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, VIM, Visual Studio, and VSCode
- [Project Examples](http://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples) - [Project Examples](https://docs.platformio.org/en/latest/platforms/espressif32.html?utm_source=github&utm_medium=arduino-esp32#examples)

View File

@ -127,9 +127,7 @@ void ArduinoOTAClass::begin() {
} }
_initialized = true; _initialized = true;
_state = OTA_IDLE; _state = OTA_IDLE;
#ifdef OTA_DEBUG log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port);
OTA_DEBUG.printf("OTA server at: %s.local:%u\n", _hostname.c_str(), _port);
#endif
} }
int ArduinoOTAClass::parseInt(){ int ArduinoOTAClass::parseInt(){
@ -173,6 +171,7 @@ void ArduinoOTAClass::_onRx(){
_md5 = readStringUntil('\n'); _md5 = readStringUntil('\n');
_md5.trim(); _md5.trim();
if(_md5.length() != 32){ if(_md5.length() != 32){
log_e("bad md5 length");
return; return;
} }
@ -198,6 +197,7 @@ void ArduinoOTAClass::_onRx(){
} else if (_state == OTA_WAITAUTH) { } else if (_state == OTA_WAITAUTH) {
int cmd = parseInt(); int cmd = parseInt();
if (cmd != U_AUTH) { if (cmd != U_AUTH) {
log_e("%d was expected. got %d instead", U_AUTH, cmd);
_state = OTA_IDLE; _state = OTA_IDLE;
return; return;
} }
@ -205,6 +205,7 @@ void ArduinoOTAClass::_onRx(){
String cnonce = readStringUntil(' '); String cnonce = readStringUntil(' ');
String response = readStringUntil('\n'); String response = readStringUntil('\n');
if (cnonce.length() != 32 || response.length() != 32) { if (cnonce.length() != 32 || response.length() != 32) {
log_e("auth param fail");
_state = OTA_IDLE; _state = OTA_IDLE;
return; return;
} }
@ -225,6 +226,7 @@ void ArduinoOTAClass::_onRx(){
} else { } else {
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort()); _udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
_udp_ota.print("Authentication Failed"); _udp_ota.print("Authentication Failed");
log_w("Authentication Failed");
_udp_ota.endPacket(); _udp_ota.endPacket();
if (_error_callback) _error_callback(OTA_AUTH_ERROR); if (_error_callback) _error_callback(OTA_AUTH_ERROR);
_state = OTA_IDLE; _state = OTA_IDLE;
@ -234,9 +236,9 @@ void ArduinoOTAClass::_onRx(){
void ArduinoOTAClass::_runUpdate() { void ArduinoOTAClass::_runUpdate() {
if (!Update.begin(_size, _cmd)) { if (!Update.begin(_size, _cmd)) {
#ifdef OTA_DEBUG
Update.printError(OTA_DEBUG); log_e("Begin ERROR: %s", Update.errorString());
#endif
if (_error_callback) { if (_error_callback) {
_error_callback(OTA_BEGIN_ERROR); _error_callback(OTA_BEGIN_ERROR);
} }
@ -272,21 +274,15 @@ void ArduinoOTAClass::_runUpdate() {
} }
if (!waited){ if (!waited){
if(written && tried++ < 3){ if(written && tried++ < 3){
#ifdef OTA_DEBUG log_i("Try[%u]: %u", tried, written);
OTA_DEBUG.printf("Try[%u]: %u\n", tried, written);
#endif
if(!client.printf("%u", written)){ if(!client.printf("%u", written)){
#ifdef OTA_DEBUG log_e("failed to respond");
OTA_DEBUG.printf("failed to respond\n");
#endif
_state = OTA_IDLE; _state = OTA_IDLE;
break; break;
} }
continue; continue;
} }
#ifdef OTA_DEBUG log_e("Receive Failed");
OTA_DEBUG.printf("Receive Failed\n");
#endif
if (_error_callback) { if (_error_callback) {
_error_callback(OTA_RECEIVE_ERROR); _error_callback(OTA_RECEIVE_ERROR);
} }
@ -295,9 +291,7 @@ void ArduinoOTAClass::_runUpdate() {
return; return;
} }
if(!available){ if(!available){
#ifdef OTA_DEBUG log_e("No Data: %u", waited);
OTA_DEBUG.printf("No Data: %u\n", waited);
#endif
_state = OTA_IDLE; _state = OTA_IDLE;
break; break;
} }
@ -317,18 +311,14 @@ void ArduinoOTAClass::_runUpdate() {
log_w("didn't write enough! %u != %u", written, r); log_w("didn't write enough! %u != %u", written, r);
} }
if(!client.printf("%u", written)){ if(!client.printf("%u", written)){
#ifdef OTA_DEBUG log_w("failed to respond");
OTA_DEBUG.printf("failed to respond\n");
#endif
} }
total += written; total += written;
if(_progress_callback) { if(_progress_callback) {
_progress_callback(total, _size); _progress_callback(total, _size);
} }
} else { } else {
#ifdef OTA_DEBUG log_e("Write ERROR: %s", Update.errorString());
Update.printError(OTA_DEBUG);
#endif
} }
} }
@ -351,10 +341,7 @@ void ArduinoOTAClass::_runUpdate() {
Update.printError(client); Update.printError(client);
client.stop(); client.stop();
delay(10); delay(10);
#ifdef OTA_DEBUG log_e("Update ERROR: %s", Update.errorString());
OTA_DEBUG.print("Update ERROR: ");
Update.printError(OTA_DEBUG);
#endif
_state = OTA_IDLE; _state = OTA_IDLE;
} }
} }
@ -366,9 +353,7 @@ void ArduinoOTAClass::end() {
MDNS.end(); MDNS.end();
} }
_state = OTA_IDLE; _state = OTA_IDLE;
#ifdef OTA_DEBUG log_i("OTA server stopped.");
OTA_DEBUG.println("OTA server stopped.");
#endif
} }
void ArduinoOTAClass::handle() { void ArduinoOTAClass::handle() {
@ -395,4 +380,4 @@ void ArduinoOTAClass::setTimeout(int timeoutInMillis) {
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
ArduinoOTAClass ArduinoOTA; ArduinoOTAClass ArduinoOTA;
#endif #endif

View File

@ -1,17 +0,0 @@
{
"name":"AsyncUDP",
"description":"Asynchronous UDP Library for ESP32",
"keywords":"async,udp,server,client,multicast,broadcast",
"authors":
{
"name": "Hristo Gochkov",
"maintainer": true
},
"repository":
{
"type": "git",
"url": "https://github.com/me-no-dev/ESPAsyncUDP.git"
},
"frameworks": "arduino",
"platforms":"espressif"
}

View File

@ -150,7 +150,7 @@ static bool _udp_task_start(){
} }
} }
if(!_udp_task_handle){ if(!_udp_task_handle){
xTaskCreate(_udp_task, "async_udp", 4096, NULL, 3, (TaskHandle_t*)&_udp_task_handle); xTaskCreateUniversal(_udp_task, "async_udp", 4096, NULL, 3, (TaskHandle_t*)&_udp_task_handle, CONFIG_ARDUINO_UDP_RUNNING_CORE);
if(!_udp_task_handle){ if(!_udp_task_handle){
return false; return false;
} }

View File

@ -7,7 +7,7 @@
#include <functional> #include <functional>
extern "C" { extern "C" {
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include <tcpip_adapter.h> #include "esp_netif.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
} }

Submodule libraries/BLE deleted from b232e7f5f0

15
libraries/BLE/README.md Normal file
View File

@ -0,0 +1,15 @@
# ESP32 BLE for Arduino
The Arduino IDE provides an excellent library package manager where versions of libraries can be downloaded and installed. This Github project provides the repository for the ESP32 BLE support for Arduino.
The actual source of the project which is being maintained can be found here:
https://github.com/nkolban/esp32-snippets
Issues and questions should be raised here:
https://github.com/nkolban/esp32-snippets/issues
Documentation for using the library can be found here:
https://github.com/nkolban/esp32-snippets/tree/master/Documentation

View File

@ -0,0 +1,161 @@
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println((char*)pData);
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
String newValue = "Time since boot: " + String(millis()/1000);
Serial.println("Setting new characteristic value to \"" + newValue + "\"");
// Set the characteristic's value to be the array of bytes that is actually a string.
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
}else if(doScan){
BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
}
delay(1000); // Delay a second between loops.
} // End of loop

View File

@ -0,0 +1,104 @@
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by pcbreflux
*/
/*
Create a BLE server that will send periodic iBeacon frames.
The design of creating the BLE server is:
1. Create a BLE Server
2. Create advertising data
3. Start advertising.
4. wait
5. Stop advertising.
6. deep sleep
*/
#include "sys/time.h"
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "esp_sleep.h"
#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up
RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory
RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memory
#ifdef __cplusplus
extern "C" {
#endif
uint8_t temprature_sens_read();
//uint8_t g_phyFuns;
#ifdef __cplusplus
}
#endif
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
BLEAdvertising *pAdvertising;
struct timeval now;
#define BEACON_UUID "8ec76ea3-6668-48da-9866-75be8bc86f4d" // UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/)
void setBeacon() {
BLEBeacon oBeacon = BLEBeacon();
oBeacon.setManufacturerId(0x4C00); // fake Apple 0x004C LSB (ENDIAN_CHANGE_U16!)
oBeacon.setProximityUUID(BLEUUID(BEACON_UUID));
oBeacon.setMajor((bootcount & 0xFFFF0000) >> 16);
oBeacon.setMinor(bootcount&0xFFFF);
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
std::string strServiceData = "";
strServiceData += (char)26; // Len
strServiceData += (char)0xFF; // Type
strServiceData += oBeacon.getData();
oAdvertisementData.addData(strServiceData);
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->setScanResponseData(oScanResponseData);
pAdvertising->setAdvertisementType(ADV_TYPE_NONCONN_IND);
}
void setup() {
Serial.begin(115200);
gettimeofday(&now, NULL);
Serial.printf("start ESP32 %d\n",bootcount++);
Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n",now.tv_sec,now.tv_sec-last);
last = now.tv_sec;
// Create the BLE Device
BLEDevice::init("");
// Create the BLE Server
// BLEServer *pServer = BLEDevice::createServer(); // <-- no longer required to instantiate BLEServer, less flash and ram usage
pAdvertising = BLEDevice::getAdvertising();
setBeacon();
// Start advertising
pAdvertising->start();
Serial.println("Advertizing started...");
delay(100);
pAdvertising->stop();
Serial.printf("enter deep sleep\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
}
void loop() {
}

View File

@ -0,0 +1,110 @@
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
A connect hander associated with the server starts a background task that performs notification
every couple of seconds.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
pCharacteristic->setValue((uint8_t*)&value, 4);
pCharacteristic->notify();
value++;
delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}

View File

@ -0,0 +1,40 @@
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 5; //In seconds
BLEScan* pBLEScan;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}

View File

@ -0,0 +1,45 @@
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
updates by chegewara
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("Long name works now");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World says Neil");
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}

View File

@ -0,0 +1,111 @@
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
A connect hander associated with the server starts a background task that performs notification
every couple of seconds.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
BLEDevice::startAdvertising();
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
pCharacteristic->setValue((uint8_t*)&value, 4);
pCharacteristic->notify();
value++;
delay(10); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}

View File

@ -0,0 +1,125 @@
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE"
Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY"
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
In this example rxValue is the data received (only accessible inside that function).
And txValue is the data to be sent, in this example just a byte incremented every second.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("UART Service");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}

View File

@ -0,0 +1,65 @@
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE scanner app in your phone");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to MyESP32");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
Serial.println("5- See the magic =)");
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}

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