From c37ff5c0dc6fd0656e8fef9854d073eb218c2500 Mon Sep 17 00:00:00 2001 From: Valeriy Koval Date: Mon, 24 Oct 2016 20:23:25 +0300 Subject: [PATCH] Initial support for ESP32 --- .travis.yml | 2 + appveyor.yml | 2 + boards/esp32.json | 27 +++ builder/frameworks/arduino.py | 87 ++++++- builder/frameworks/espidf.py | 88 ++++++- builder/main.py | 251 +++++++++++++++++++- examples/arduino-blink/.gitignore | 3 + examples/arduino-blink/.travis.yml | 65 +++++ examples/arduino-blink/README.rst | 38 +++ examples/arduino-blink/lib/readme.txt | 38 +++ examples/arduino-blink/platformio.ini | 13 + examples/arduino-blink/src/Blink.cpp | 27 +++ examples/arduino-wifiscan/.gitignore | 3 + examples/arduino-wifiscan/.travis.yml | 65 +++++ examples/arduino-wifiscan/README.rst | 38 +++ examples/arduino-wifiscan/lib/readme.txt | 38 +++ examples/arduino-wifiscan/platformio.ini | 13 + examples/arduino-wifiscan/src/WiFiScan.ino | 48 ++++ examples/espidf-http-request/.gitignore | 3 + examples/espidf-http-request/.travis.yml | 65 +++++ examples/espidf-http-request/README.rst | 29 +++ examples/espidf-http-request/lib/readme.txt | 38 +++ examples/espidf-http-request/platformio.ini | 14 ++ examples/espidf-http-request/src/main.c | 181 ++++++++++++++ platform.json | 6 +- 25 files changed, 1176 insertions(+), 6 deletions(-) create mode 100644 boards/esp32.json create mode 100644 examples/arduino-blink/.gitignore create mode 100644 examples/arduino-blink/.travis.yml create mode 100644 examples/arduino-blink/README.rst create mode 100644 examples/arduino-blink/lib/readme.txt create mode 100644 examples/arduino-blink/platformio.ini create mode 100644 examples/arduino-blink/src/Blink.cpp create mode 100644 examples/arduino-wifiscan/.gitignore create mode 100644 examples/arduino-wifiscan/.travis.yml create mode 100644 examples/arduino-wifiscan/README.rst create mode 100644 examples/arduino-wifiscan/lib/readme.txt create mode 100644 examples/arduino-wifiscan/platformio.ini create mode 100644 examples/arduino-wifiscan/src/WiFiScan.ino create mode 100644 examples/espidf-http-request/.gitignore create mode 100644 examples/espidf-http-request/.travis.yml create mode 100644 examples/espidf-http-request/README.rst create mode 100644 examples/espidf-http-request/lib/readme.txt create mode 100644 examples/espidf-http-request/platformio.ini create mode 100644 examples/espidf-http-request/src/main.c diff --git a/.travis.yml b/.travis.yml index a583d6b..a39fb22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ python: env: - PLATFORMIO_PROJECT_DIR=examples/arduino-blink + - PLATFORMIO_PROJECT_DIR=examples/arduino-wifiscan + - PLATFORMIO_PROJECT_DIR=examples/espidf-http-request install: - pip install -U https://github.com/platformio/platformio/archive/develop.zip diff --git a/appveyor.yml b/appveyor.yml index aa189aa..63bc3e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,8 @@ environment: matrix: - PLATFORMIO_PROJECT_DIR: "examples/arduino-blink" + - PLATFORMIO_PROJECT_DIR: "examples/arduino-wifiscan" + - PLATFORMIO_PROJECT_DIR: "examples/espidf-http-request" install: - cmd: git submodule update --init --recursive diff --git a/boards/esp32.json b/boards/esp32.json new file mode 100644 index 0000000..2f3d137 --- /dev/null +++ b/boards/esp32.json @@ -0,0 +1,27 @@ +{ + "build": { + "core": "esp32", + "extra_flags": "-DESP32_DEV -DARDUINO_ESP32_DEV", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "ldscript": "esp32.out.ld", + "mcu": "esp32", + "variant": "esp32" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32 Dev Module", + "upload": { + "maximum_ram_size": 114688, + "maximum_size": 1044464, + "require_upload_port": true, + "resetmethod": "nodemcu", + "speed": 115200, + "wait_for_upload_port": true + }, + "url": "https://en.wikipedia.org/wiki/ESP32", + "vendor": "Espressif" +} diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index aec4b39..a0aa1ae 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -22,4 +22,89 @@ kinds of creative coding, interactive objects, spaces or physical experiences. http://arduino.cc/en/Reference/HomePage """ -# TODO \ No newline at end of file +from os.path import isdir, join + +from SCons.Script import DefaultEnvironment + +env = DefaultEnvironment() +platform = env.PioPlatform() + +FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") +FRAMEWORK_VERSION = platform.get_package_version( + "framework-arduinoespressif32") +assert isdir(FRAMEWORK_DIR) + +env.Prepend( + CPPDEFINES=[ + "ARDUINO=%s" % FRAMEWORK_VERSION.split(".")[1], + "ARDUINO_ARCH_ESP32" + ], + + CPPPATH=[ + join(FRAMEWORK_DIR, "tools", "sdk", "include", "config"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "bt"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "driver"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "esp32"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "freertos"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "log"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "lwip"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "newlib"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "nvs_flash"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "spi_flash"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "tcpip_adapter"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "expat"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "json"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "mbedtls"), + join(FRAMEWORK_DIR, "tools", "sdk", "include", "nghttp"), + join(FRAMEWORK_DIR, "cores", env.BoardConfig().get("build.core")) + ], + LIBPATH=[ + join(FRAMEWORK_DIR, "tools", "sdk", "lib"), + join(FRAMEWORK_DIR, "tools", "sdk", "ld"), + ], + LIBS=[ + "hal", "core", "net80211", "phy", "rtc", "pp", "wpa", + "smartconfig", "btdm_app", "bt", "driver", "esp32", "crypto", "expat", + "freertos", "json", "log", "lwip", "mbedtls", "nghttp", "nvs_flash", + "spi_flash", "tcpip_adapter", "gcc", "m", "c" + ] +) + +env.Append( + LIBSOURCE_DIRS=[ + join(FRAMEWORK_DIR, "libraries") + ], + + LINKFLAGS=[ + "-T", "esp32.common.ld", + "-T", "esp32.rom.ld", + "-T", "esp32.peripherals.ld" + ] +) + +# +# Target: Build Core Library +# + +libs = [] + +if "build.variant" in env.BoardConfig(): + env.Append( + CPPPATH=[ + join(FRAMEWORK_DIR, "variants", + env.BoardConfig().get("build.variant")) + ] + ) + libs.append(env.BuildLibrary( + join("$BUILD_DIR", "FrameworkArduinoVariant"), + join(FRAMEWORK_DIR, "variants", env.BoardConfig().get("build.variant")) + )) + +envsafe = env.Clone() + +libs.append(envsafe.BuildLibrary( + join("$BUILD_DIR", "FrameworkArduino"), + join(FRAMEWORK_DIR, "cores", env.BoardConfig().get("build.core")) +)) + +env.Prepend(LIBS=libs) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9a6473b..3afdd87 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -13,11 +13,93 @@ # limitations under the License. """ -ESP IDF +Espressif IDF -Espressif IoT Development Framework. Official development framework for ESP32. +Espressif IoT Development Framework for ESP32 MCU https://github.com/espressif/esp-idf """ -# TODO \ No newline at end of file +from os import listdir +from os.path import isdir, join + +from SCons.Script import DefaultEnvironment + +env = DefaultEnvironment() +platform = env.PioPlatform() + +FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") +FRAMEWORK_VERSION = platform.get_package_version( + "framework-espidf") +assert isdir(FRAMEWORK_DIR) + + +env.Prepend( + CPPPATH=[ + join(FRAMEWORK_DIR, "config"), + join(FRAMEWORK_DIR, "components", "nghttp", "include"), + join(FRAMEWORK_DIR, "components", "nghttp", "port", "include"), + join(FRAMEWORK_DIR, "components", "bt", "include"), + join(FRAMEWORK_DIR, "components", "driver", "include"), + join(FRAMEWORK_DIR, "components", "esp32", "include"), + join(FRAMEWORK_DIR, "components", "freertos", "include"), + join(FRAMEWORK_DIR, "components", "freertos", "include", "freertos"), + join(FRAMEWORK_DIR, "components", "log", "include"), + join(FRAMEWORK_DIR, "components", "newlib", "include"), + join(FRAMEWORK_DIR, "components", "nvs_flash", "include"), + join(FRAMEWORK_DIR, "components", "spi_flash", "include"), + join(FRAMEWORK_DIR, "components", "tcpip_adapter", "include"), + join(FRAMEWORK_DIR, "components", "lwip", "include", "lwip"), + join(FRAMEWORK_DIR, "components", "lwip", "include", "lwip", "port"), + join(FRAMEWORK_DIR, "components", "lwip", "include", "lwip", "posix"), + join(FRAMEWORK_DIR, "components", "expat", "include", "expat"), + join(FRAMEWORK_DIR, "components", "expat", "port", "include"), + join(FRAMEWORK_DIR, "components", "json", "include"), + join(FRAMEWORK_DIR, "components", "json", "port", "include"), + join(FRAMEWORK_DIR, "components", "mbedtls", "include"), + join(FRAMEWORK_DIR, "components", "mbedtls", "port", "include") + ], + + LIBPATH=[ + join(FRAMEWORK_DIR, "components", "esp32"), + join(FRAMEWORK_DIR, "components", "esp32", "lib"), + join(FRAMEWORK_DIR, "components", "bt", "lib"), + join(FRAMEWORK_DIR, "components", "newlib", "lib"), + join(FRAMEWORK_DIR, "components", "esp32", "ld") + ], + + LIBS=[ + "hal", "crypto", "core", "net80211", "phy", "rtc", "pp", "wpa", + "smartconfig", "btdm_app", "m", "c", "gcc" + ] +) + +env.Append( + LIBSOURCE_DIRS=[ + join(FRAMEWORK_DIR, "libraries") + ], + + LINKFLAGS=[ + "-T", "esp32.common.ld", + "-T", "esp32.rom.ld", + "-T", "esp32.peripherals.ld" + ], +) + +# +# Target: Build Core Library +# + +libs = [] + +for d in listdir(join(FRAMEWORK_DIR, "components")): + if d == "bootloader": + continue + if isdir(join(FRAMEWORK_DIR, "components", d)): + libs.append(env.BuildLibrary( + join("$BUILD_DIR", "IDFComponents_%s" % d), + join(FRAMEWORK_DIR, "components", d), + src_filter="+<*> -" + )) + +env.Prepend(LIBS=libs) diff --git a/builder/main.py b/builder/main.py index edbcab1..388fd80 100644 --- a/builder/main.py +++ b/builder/main.py @@ -12,4 +12,253 @@ # See the License for the specific language governing permissions and # limitations under the License. -# @TODO + +import re +from os.path import join + +from SCons.Script import (AlwaysBuild, Builder, Default, DefaultEnvironment) + + +def _get_board_f_flash(env): + frequency = env.subst("$BOARD_F_FLASH") + frequency = str(frequency).replace("L", "") + return str(int(int(frequency) / 1000000)) + "m" + + +def build_espidf_bootloader(): + envsafe = env.Clone() + framework_dir = env.subst("$ESPIDF_DIR") + envsafe.Replace( + CPPDEFINES=["ESP_PLATFORM", "BOOTLOADER_BUILD=1"], + + LIBPATH=[ + join(framework_dir, "components", "esp32", "ld"), + join(framework_dir, "components", "bootloader", "src", "main") + ], + + LINKFLAGS=[ + "-Os", + "-nostdlib", + "-Wl,-static", + "-u", "call_user_start_cpu0", + "-Wl,-static", + "-Wl,--gc-sections", + "-T", "esp32.bootloader.ld", + "-T", "esp32.rom.ld" + ] + ), + + envsafe.Append(CCFLAGS=["-fstrict-volatile-bitfields"]) + + envsafe.Replace( + LIBS=[ + envsafe.BuildLibrary( + join("$BUILD_DIR", "bootloaderLog"), + join(framework_dir, "components", "log") + ), "gcc" + ] + ) + + return envsafe.Program( + join("$BUILD_DIR", "bootloader.elf"), + envsafe.CollectBuildFiles( + join("$BUILD_DIR", "bootloader"), + join(framework_dir, "components", "bootloader", "src", "main") + ) + ) + + +env = DefaultEnvironment() +platform = env.PioPlatform() + +env.Replace( + __get_board_f_flash=_get_board_f_flash, + + AR="xtensa-esp32-elf-ar", + AS="xtensa-esp32-elf-as", + CC="xtensa-esp32-elf-gcc", + CXX="xtensa-esp32-elf-g++", + OBJCOPY=join(platform.get_package_dir("tool-esptool"), "esptool.py"), + RANLIB="xtensa-esp32-elf-ranlib", + SIZETOOL="xtensa-esp32-elf-size", + + ARFLAGS=["rcs"], + + ASFLAGS=["-x", "assembler-with-cpp"], + + CFLAGS=["-std=gnu99"], + + CCFLAGS=[ + "-Os", # optimize for size + "-nostdlib", + "-Wpointer-arith", + "-Wno-error=unused-function", + "-Wno-error=unused-but-set-variable", + "-Wno-error=unused-variable", + "-mlongcalls", + "-ffunction-sections", + "-fdata-sections" + ], + + CXXFLAGS=[ + "-fno-rtti", + "-fno-exceptions", + "-std=gnu++11" + ], + + CPPDEFINES=[ + "ESP32", + "ESP_PLATFORM", + "F_CPU=$BOARD_F_CPU", + "HAVE_CONFIG_H", + "MBEDTLS_CONFIG_FILE=\\\"mbedtls/esp_config.h\\\"" + ], + + LINKFLAGS=[ + "-Os", + "-nostdlib", + "-Wl,-static", + "-u", "call_user_start_cpu0", + "-Wl,-static", + "-Wl,--undefined=uxTopUsedPriority", + "-Wl,--gc-sections" + ], + + # + # Packages + # + + FRAMEWORK_ARDUINOESP32_DIR=platform.get_package_dir( + "framework-arduinoespressif32"), + ESPIDF_DIR=platform.get_package_dir("framework-espidf"), + + # + # Upload + # + + UPLOADER=join(platform.get_package_dir("tool-esptool"), "esptool.py"), + + UPLOADERFLAGS=[ + "--chip", "esp32", + "--port", '"$UPLOAD_PORT"', + "--baud", "$UPLOAD_SPEED", + "write_flash", "-z", + "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_freq", "${__get_board_f_flash(__env__)}" + ], + + UPLOADCMD='"$PYTHONEXE" "$UPLOADER" $UPLOADERFLAGS $SOURCE', + + PROGNAME="firmware", + PROGSUFFIX=".elf" +) + +if env.subst("$PIOFRAMEWORK") == "arduino": + framework_dir = platform.get_package_dir("framework-arduinoespressif32") + env.Append( + UPLOADERFLAGS=[ + "0x1000", join("$FRAMEWORK_ARDUINOESP32_DIR", "tools", + "sdk", "bin", "bootloader.bin"), + "0x4000", join("$FRAMEWORK_ARDUINOESP32_DIR", "tools", + "sdk", "bin", "partitions_singleapp.bin"), + "0x10000" + ] + ) +if env.subst("$PIOFRAMEWORK") == "espidf": + framework_dir = platform.get_package_dir("framework-espidf") + env.Append( + UPLOADERFLAGS=[ + "0x1000", join("$BUILD_DIR", "bootloader.bin"), + "0x4000", join("$BUILD_DIR", "partitions_singleapp.bin"), + "0x10000" + ], + + PTABLE_SCRIPT=join("$ESPIDF_DIR", "components", + "partition_table", "gen_esp32part.py"), + + PTABLE_FLAGS=[ + "-q", join("$ESPIDF_DIR", "components", + "partition_table", "partitions_singleapp.csv"), + join(env.subst("$BUILD_DIR"), "partitions_singleapp.bin") + + ], + + PTABLE_CMD='"$PYTHONEXE" "$PTABLE_SCRIPT" $PTABLE_FLAGS' + ) + + +env.Append( + ASFLAGS=env.get("CCFLAGS", [])[:] +) + +# +# Framework and SDK specific configuration +# + +env.Append( + BUILDERS=dict( + ElfToBin=Builder( + action=env.VerboseAction(" ".join([ + '"$PYTHONEXE" "$OBJCOPY"', + "--chip", "esp32", + "elf2image", + "--flash_mode", "$BOARD_FLASH_MODE", + "--flash_freq", "${__get_board_f_flash(__env__)}", + "-o", "$TARGET", "$SOURCES" + ]), "Building $TARGET"), + suffix=".bin" + ) + ) +) + +# +# Target: Build executable and linkable firmware or SPIFFS image +# + + +def __tmp_hook_before_pio_3_2(): + env.ProcessFlags(env.get("BUILD_FLAGS")) + # append specified LD_SCRIPT + if ("LDSCRIPT_PATH" in env and + not any(["-Wl,-T" in f for f in env['LINKFLAGS']])): + env.Append(LINKFLAGS=['-Wl,-T"$LDSCRIPT_PATH"']) + + +target_elf = env.BuildProgram() +if "PIOFRAMEWORK" in env: + target_firm = env.ElfToBin(join("$BUILD_DIR", "firmware"), target_elf) + +if env.subst("$PIOFRAMEWORK") == "espidf": + bootloader_bin = env.ElfToBin( + join("$BUILD_DIR", "bootloader"), build_espidf_bootloader()) + target_buildprog = env.Alias( + "buildprog", [target_firm, bootloader_bin], "$PTABLE_CMD") +else: + target_buildprog = env.Alias("buildprog", target_firm) + + +# +# Target: Print binary size +# + +target_size = env.Alias( + "size", target_elf, + env.VerboseAction("$SIZEPRINTCMD", "Calculating size $SOURCE")) +AlwaysBuild(target_size) + +# +# Target: Upload firmware or SPIFFS image +# + +target_upload = env.Alias( + "upload", target_firm, + [env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port..."), + env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")]) +env.AlwaysBuild(target_upload) + + +# +# Default targets +# + +Default([target_buildprog, target_size]) diff --git a/examples/arduino-blink/.gitignore b/examples/arduino-blink/.gitignore new file mode 100644 index 0000000..5402c18 --- /dev/null +++ b/examples/arduino-blink/.gitignore @@ -0,0 +1,3 @@ +.pioenvs +.clang_complete +.gcc-flags.json diff --git a/examples/arduino-blink/.travis.yml b/examples/arduino-blink/.travis.yml new file mode 100644 index 0000000..ac0a029 --- /dev/null +++ b/examples/arduino-blink/.travis.yml @@ -0,0 +1,65 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < http://docs.platformio.org/en/stable/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < http://docs.platformio.org/en/stable/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < http://docs.platformio.org/en/stable/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to by used as a library with examples +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-blink/README.rst b/examples/arduino-blink/README.rst new file mode 100644 index 0000000..2bb346a --- /dev/null +++ b/examples/arduino-blink/README.rst @@ -0,0 +1,38 @@ +.. Copyright 2014-present PlatformIO + 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. + +How to build PlatformIO based project +===================================== + +1. `Install PlatformIO `_ +2. Download `development platform with examples `_ +3. Extract ZIP archive +4. Run these commands: + +.. code-block:: bash + + # Change directory to example + > cd platform-espressif32/examples/arduino-blink + + # Build project + > platformio run + + # Upload firmware + > platformio run --target upload + + # Build specific environment + > platformio run -e nodemcuv2 + + # Upload firmware for the specific environment + > platformio run -e nodemcuv2 --target upload + + # Clean build files + > platformio run --target clean diff --git a/examples/arduino-blink/lib/readme.txt b/examples/arduino-blink/lib/readme.txt new file mode 100644 index 0000000..0d0e7be --- /dev/null +++ b/examples/arduino-blink/lib/readme.txt @@ -0,0 +1,38 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +See additional options for PlatformIO Library Dependency Finder `lib_*`: + +http://docs.platformio.org/en/stable/projectconf.html#lib-install + diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini new file mode 100644 index 0000000..830b591 --- /dev/null +++ b/examples/arduino-blink/platformio.ini @@ -0,0 +1,13 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/en/stable/projectconf.html + +[env:esp32] +platform = espressif32 +framework = arduino +board = esp32 diff --git a/examples/arduino-blink/src/Blink.cpp b/examples/arduino-blink/src/Blink.cpp new file mode 100644 index 0000000..f4059a0 --- /dev/null +++ b/examples/arduino-blink/src/Blink.cpp @@ -0,0 +1,27 @@ +/* + * Blink + * Turns on an LED on for one second, + * then off for one second, repeatedly. + */ + +#include + +#define LED_BUILTIN 13 + +void setup() +{ + // initialize LED digital pin as an output. + pinMode(LED_BUILTIN, OUTPUT); +} + +void loop() +{ + // turn the LED on (HIGH is the voltage level) + digitalWrite(LED_BUILTIN, HIGH); + // wait for a second + delay(1000); + // turn the LED off by making the voltage LOW + digitalWrite(LED_BUILTIN, LOW); + // wait for a second + delay(1000); +} diff --git a/examples/arduino-wifiscan/.gitignore b/examples/arduino-wifiscan/.gitignore new file mode 100644 index 0000000..5402c18 --- /dev/null +++ b/examples/arduino-wifiscan/.gitignore @@ -0,0 +1,3 @@ +.pioenvs +.clang_complete +.gcc-flags.json diff --git a/examples/arduino-wifiscan/.travis.yml b/examples/arduino-wifiscan/.travis.yml new file mode 100644 index 0000000..ac0a029 --- /dev/null +++ b/examples/arduino-wifiscan/.travis.yml @@ -0,0 +1,65 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < http://docs.platformio.org/en/stable/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < http://docs.platformio.org/en/stable/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < http://docs.platformio.org/en/stable/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to by used as a library with examples +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/arduino-wifiscan/README.rst b/examples/arduino-wifiscan/README.rst new file mode 100644 index 0000000..eb2609b --- /dev/null +++ b/examples/arduino-wifiscan/README.rst @@ -0,0 +1,38 @@ +.. Copyright 2014-present PlatformIO + 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. + +How to build PlatformIO based project +===================================== + +1. `Install PlatformIO `_ +2. Download `development platform with examples `_ +3. Extract ZIP archive +4. Run these commands: + +.. code-block:: bash + + # Change directory to example + > cd platform-espressif32/examples/arduino-wifiscan + + # Build project + > platformio run + + # Upload firmware + > platformio run --target upload + + # Build specific environment + > platformio run -e nodemcuv2 + + # Upload firmware for the specific environment + > platformio run -e nodemcuv2 --target upload + + # Clean build files + > platformio run --target clean diff --git a/examples/arduino-wifiscan/lib/readme.txt b/examples/arduino-wifiscan/lib/readme.txt new file mode 100644 index 0000000..0d0e7be --- /dev/null +++ b/examples/arduino-wifiscan/lib/readme.txt @@ -0,0 +1,38 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +See additional options for PlatformIO Library Dependency Finder `lib_*`: + +http://docs.platformio.org/en/stable/projectconf.html#lib-install + diff --git a/examples/arduino-wifiscan/platformio.ini b/examples/arduino-wifiscan/platformio.ini new file mode 100644 index 0000000..830b591 --- /dev/null +++ b/examples/arduino-wifiscan/platformio.ini @@ -0,0 +1,13 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/en/stable/projectconf.html + +[env:esp32] +platform = espressif32 +framework = arduino +board = esp32 diff --git a/examples/arduino-wifiscan/src/WiFiScan.ino b/examples/arduino-wifiscan/src/WiFiScan.ino new file mode 100644 index 0000000..5d11fbb --- /dev/null +++ b/examples/arduino-wifiscan/src/WiFiScan.ino @@ -0,0 +1,48 @@ +/* + * This sketch demonstrates how to scan WiFi networks. + * The API is almost the same as with the WiFi Shield library, + * the most obvious difference being the different file you need to include: + */ +#include "WiFi.h" + +void setup() +{ + Serial.begin(115200); + + // Set WiFi to station mode and disconnect from an AP if it was previously connected + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + delay(100); + + Serial.println("Setup done"); +} + +void loop() +{ + Serial.println("scan start"); + + // WiFi.scanNetworks will return the number of networks found + int n = WiFi.scanNetworks(); + Serial.println("scan done"); + if (n == 0) { + Serial.println("no networks found"); + } else { + Serial.print(n); + Serial.println(" networks found"); + for (int i = 0; i < n; ++i) { + // Print SSID and RSSI for each network found + Serial.print(i + 1); + Serial.print(": "); + Serial.print(WiFi.SSID(i)); + Serial.print(" ("); + Serial.print(WiFi.RSSI(i)); + Serial.print(")"); + Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*"); + delay(10); + } + } + Serial.println(""); + + // Wait a bit before scanning again + delay(5000); +} diff --git a/examples/espidf-http-request/.gitignore b/examples/espidf-http-request/.gitignore new file mode 100644 index 0000000..5402c18 --- /dev/null +++ b/examples/espidf-http-request/.gitignore @@ -0,0 +1,3 @@ +.pioenvs +.clang_complete +.gcc-flags.json diff --git a/examples/espidf-http-request/.travis.yml b/examples/espidf-http-request/.travis.yml new file mode 100644 index 0000000..72c6e43 --- /dev/null +++ b/examples/espidf-http-request/.travis.yml @@ -0,0 +1,65 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < http://docs.platformio.org/en/stable/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < http://docs.platformio.org/en/stable/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < http://docs.platformio.org/en/stable/userguide/cmd_ci.html > +# +# +# Please choice one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to by used as a library with examples +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/examples/espidf-http-request/README.rst b/examples/espidf-http-request/README.rst new file mode 100644 index 0000000..939467a --- /dev/null +++ b/examples/espidf-http-request/README.rst @@ -0,0 +1,29 @@ +.. Copyright 2014-present PlatformIO + 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. + +How to build PlatformIO based project +===================================== + +1. `Install PlatformIO `_ +2. Download `development platform with examples `_ +3. Extract ZIP archive +4. Run these commands: + +.. code-block:: bash + + # Change directory to example + > cd platform-espressif8266/examples/espidf-http-request + + # Process example project + > platformio run + + # Upload firmware + > platformio run --target upload diff --git a/examples/espidf-http-request/lib/readme.txt b/examples/espidf-http-request/lib/readme.txt new file mode 100644 index 0000000..a3271c7 --- /dev/null +++ b/examples/espidf-http-request/lib/readme.txt @@ -0,0 +1,38 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organised `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +See additional options for PlatformIO Library Dependency Finder `lib_*`: + +http://docs.platformio.org/en/stable/projectconf.html#lib-install + diff --git a/examples/espidf-http-request/platformio.ini b/examples/espidf-http-request/platformio.ini new file mode 100644 index 0000000..55eafde --- /dev/null +++ b/examples/espidf-http-request/platformio.ini @@ -0,0 +1,14 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter, extra scripting +; Upload options: custom port, speed and extra flags +; Library options: dependencies, extra library storages +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/en/stable/projectconf.html + +[env:esp32] +platform = espressif32 +framework = espidf +board = esp32 +build_flags = -DCONFIG_WIFI_SSID=\"ESP_AP\" -DCONFIG_WIFI_PASSWORD=\"MYPASS\" \ No newline at end of file diff --git a/examples/espidf-http-request/src/main.c b/examples/espidf-http-request/src/main.c new file mode 100644 index 0000000..1f8d988 --- /dev/null +++ b/examples/espidf-http-request/src/main.c @@ -0,0 +1,181 @@ +/* HTTP GET Example using plain POSIX sockets + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID +#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int CONNECTED_BIT = BIT0; + +/* Constants that aren't configurable in menuconfig */ +#define WEB_SERVER "example.com" +#define WEB_PORT 80 +#define WEB_URL "http://example.com/" + +static const char *TAG = "example"; + +static const char *REQUEST = "GET " WEB_URL " HTTP/1.1\n" + "Host: "WEB_SERVER"\n" + "User-Agent: esp-idf/1.0 esp32\n" + "\n"; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +static void initialise_wifi(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_WIFI_SSID, + .password = EXAMPLE_WIFI_PASS, + }, + }; + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +static void http_get_task(void *pvParameters) +{ + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }; + struct addrinfo *res; + struct in_addr *addr; + int s, r; + char recv_buf[64]; + + while(1) { + /* Wait for the callback to set the CONNECTED_BIT in the + event group. + */ + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, + false, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connected to AP"); + + int err = getaddrinfo(WEB_SERVER, "80", &hints, &res); + + if(err != 0 || res == NULL) { + ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res); + vTaskDelay(1000 / portTICK_RATE_MS); + continue; + } + + /* Code to print the resolved IP. + + Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */ + addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; + ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr)); + + s = socket(res->ai_family, res->ai_socktype, 0); + if(s < 0) { + ESP_LOGE(TAG, "... Failed to allocate socket."); + freeaddrinfo(res); + vTaskDelay(1000 / portTICK_RATE_MS); + continue; + } + ESP_LOGI(TAG, "... allocated socket\r\n"); + + if(connect(s, res->ai_addr, res->ai_addrlen) != 0) { + ESP_LOGE(TAG, "... socket connect failed errno=%d", errno); + close(s); + freeaddrinfo(res); + vTaskDelay(4000 / portTICK_RATE_MS); + continue; + } + + ESP_LOGI(TAG, "... connected"); + freeaddrinfo(res); + + if (write(s, REQUEST, strlen(REQUEST)) < 0) { + ESP_LOGE(TAG, "... socket send failed"); + close(s); + vTaskDelay(4000 / portTICK_RATE_MS); + continue; + } + ESP_LOGI(TAG, "... socket send success"); + + /* Read HTTP response */ + do { + bzero(recv_buf, sizeof(recv_buf)); + r = read(s, recv_buf, sizeof(recv_buf)-1); + for(int i = 0; i < r; i++) { + putchar(recv_buf[i]); + } + } while(r > 0); + + ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno); + close(s); + for(int countdown = 10; countdown >= 0; countdown--) { + ESP_LOGI(TAG, "%d... ", countdown); + vTaskDelay(1000 / portTICK_RATE_MS); + } + ESP_LOGI(TAG, "Starting again!"); + } +} + +void app_main() +{ + nvs_flash_init(); + system_init(); + initialise_wifi(); + xTaskCreate(&http_get_task, "http_get_task", 2048, NULL, 5, NULL); +} \ No newline at end of file diff --git a/platform.json b/platform.json index 8e3b8ed..a3122ef 100644 --- a/platform.json +++ b/platform.json @@ -33,7 +33,7 @@ "packages": { "toolchain-xtensa32": { "type": "toolchain", - "version": "~1.40802.0" + "version": "~1.40805.0" }, "framework-arduinoespressif32": { "type": "framework", @@ -44,6 +44,10 @@ "type": "framework", "optional": true, "version": "~1.90.0" + }, + "tool-esptool": { + "type": "uploader", + "version": "~1.409.0" } } }