From 2be2ba9bb30e1e7a1eeb3d43ddefdfaffd744d9b Mon Sep 17 00:00:00 2001 From: kangping Date: Thu, 14 May 2020 15:16:25 +0800 Subject: [PATCH] initial commit --- .clang-format | 112 ++++++++ .github/workflows/build.yml | 73 +++++ .gitignore | 41 +++ .gitmodules | 4 + CODE_OF_CONDUCT.md | 46 ++++ CONTRIBUTING.md | 129 +++++++++ LICENSE | 25 ++ README.md | 25 ++ component.mk | 79 ++++++ doc/images/connect-devices.jpg | Bin 0 -> 206960 bytes example/Makefile | 51 ++++ example/README.md | 95 +++++++ example/main/cli.c | 117 ++++++++ example/main/component.mk | 30 ++ example/partitions.csv | 35 +++ example/sdkconfig.defaults | 34 +++ include/openthread/openthread-esp32.h | 162 +++++++++++ script/bootstrap | 34 +++ script/check-esp32-build | 57 ++++ script/clang-format | 30 ++ script/clang-format-check | 30 ++ script/make-pretty | 30 ++ src/alarm.c | 122 ++++++++ src/api_lock.c | 63 +++++ src/error_handling.h | 36 +++ src/flash.c | 165 +++++++++++ src/logging.c | 75 +++++ src/memory.c | 39 +++ src/misc.c | 90 ++++++ src/openthread-core-esp32-config.h | 257 +++++++++++++++++ src/platform-esp32.h | 227 +++++++++++++++ src/radio.cpp | 382 ++++++++++++++++++++++++++ src/spinel_hdlc.cpp | 337 +++++++++++++++++++++++ src/spinel_hdlc.hpp | 191 +++++++++++++ src/system.c | 113 ++++++++ src/time.c | 54 ++++ src/uart.c | 145 ++++++++++ third_party/openthread | 1 + 38 files changed, 3536 insertions(+) create mode 100644 .clang-format create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 component.mk create mode 100644 doc/images/connect-devices.jpg create mode 100644 example/Makefile create mode 100644 example/README.md create mode 100644 example/main/cli.c create mode 100644 example/main/component.mk create mode 100644 example/partitions.csv create mode 100644 example/sdkconfig.defaults create mode 100644 include/openthread/openthread-esp32.h create mode 100755 script/bootstrap create mode 100755 script/check-esp32-build create mode 100755 script/clang-format create mode 100755 script/clang-format-check create mode 100755 script/make-pretty create mode 100644 src/alarm.c create mode 100644 src/api_lock.c create mode 100644 src/error_handling.h create mode 100644 src/flash.c create mode 100644 src/logging.c create mode 100644 src/memory.c create mode 100644 src/misc.c create mode 100644 src/openthread-core-esp32-config.h create mode 100644 src/platform-esp32.h create mode 100644 src/radio.cpp create mode 100644 src/spinel_hdlc.cpp create mode 100644 src/spinel_hdlc.hpp create mode 100644 src/system.c create mode 100644 src/time.c create mode 100644 src/uart.c create mode 160000 third_party/openthread diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..9a0a6ea --- /dev/null +++ b/.clang-format @@ -0,0 +1,112 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: false + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeCategories: + - Regex: '^/ot-esp32.git + +# Configure upstream alias +git remote add upstream git@github.com:openthread/ot-esp32.git +``` + +### Contributor License Agreement (CLA) + +Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. + +### Submitting a Pull Request + +#### Branch + +For each new feature, create a working branch: + +```bash +# Create a working branch for your new feature +git branch --track origin/master + +# Checkout the branch +git checkout +``` + +#### Create Commits + +```bash +# Add each modified file you'd like to include in the commit +git add + +# Create a commit +git commit +``` + +This will open up a text editor where you can craft your commit message. + +#### Upstream Sync and Clean Up + +Prior to submitting your pull request, you might want to do a few things to clean up your branch and make it as simple as possible for the original repo's maintainer to test, accept, and merge your work. + +If any commits have been made to the upstream master branch, you should rebase your development branch so that merging it will be a simple fast-forward that won't require any conflict resolution work. + +```bash +# Fetch upstream master and merge with your repo's master branch +git checkout master +git pull upstream master + +# If there were any new commits, rebase your development branch +git checkout +git rebase master +``` + +Now, it may be desirable to squash some of your smaller commits down into a small number of larger more cohesive commits. You can do this with an interactive rebase: + +```bash +# Rebase all commits on your development branch +git checkout +git rebase -i master +``` + +This will open up a text editor where you can specify which commits to squash. + +#### Coding Conventions and Style + +ot-esp32 uses and enforces the [OpenThread Coding Conventions and Style](https://github.com/openthread/openthread/blob/master/STYLE_GUIDE.md) on all code, except for code located in [third_party](third_party). Use `script/make-pretty` and `script/make-pretty check` to automatically reformat code and check for code-style compliance, respectively. ot-esp32 currently requires [clang-format v6.0.0](http://releases.llvm.org/download.html#6.0.0) for C/C++ and [yapf v0.29.0](https://github.com/google/yapf) for Python. + +As part of the cleanup process, you should also run `script/make-pretty check` to ensure that your code passes the baseline code style checks. + +#### Push and Test + +```bash +# Checkout your branch +git checkout + +# Push to your GitHub fork: +git push origin +``` + +This will trigger continuous-integration checks using GitHub Actions. You can view the status and logs via the "Actions" tab in your fork. + +#### Submit Pull Request + +Once you've validated that all continuous-integration checks have passed, go to the page for your fork on GitHub, select your development branch, and click the pull request button. If you need to make any adjustments to your pull request, just push the updates to GitHub. Your pull request will automatically track the changes on your development branch and update. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d63767e --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2020, The OpenThread Authors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b91704 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# OpenThread on ESP32 + +**ot-esp32** is a port of OpenThread for the [Espressif ESP32 platform](https://www.espressif.com/en/products/socs/esp32/overview), where OpenThread uses a [Radio Co-Processor (RCP) design](https://openthread.io/platforms#radio-co-processor-rcp), transmitting and receiving radio using an 802.15.4-capable SoC. + +For more information on OpenThread, see [openthread.io](https://openthread.io). + +## Getting started + +Get started with the [example CLI application](example/README.md). + +## Contributing + +We would love for you to contribute to OpenThread ESP32 and help make it even better than it is today! See our [Contributing Guidelines](https://github.com/openthread/ot-esp32/blob/master/CONTRIBUTING.md) for more information. + +Contributors are required to abide by our [Code of Conduct](https://github.com/openthread/ot-esp32/blob/master/CODE_OF_CONDUCT.md) and [Coding Conventions and Style Guide](https://github.com/openthread/openthread/blob/master/STYLE_GUIDE.md). + +## Versioning + +OpenThread ESP32 follows the [Semantic Versioning guidelines](http://semver.org/) for release cycle transparency and to maintain backwards compatibility. + +## License + +OpenThread ESP32 is released under the [BSD 3-Clause license](https://github.com/openthread/ot-esp32/blob/master/LICENSE). See the [`LICENSE`](https://github.com/openthread/ot-esp32/blob/master/LICENSE) file for more information. + +Please only use the OpenThread ESP32 name and marks when accurately referencing this software distribution. Do not use the marks in a way that suggests you are endorsed by or otherwise affiliated with Nest, Google, or The Thread Group. diff --git a/component.mk b/component.mk new file mode 100644 index 0000000..d13cc7e --- /dev/null +++ b/component.mk @@ -0,0 +1,79 @@ +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Description: +# This file is the component file builds ot-esp32 project as an esp-idf component. +# + +COMPONENT_ADD_INCLUDEDIRS := \ + include \ + third_party/openthread/include + +COMPONENT_PRIV_INCLUDEDIRS := \ + src \ + third_party/openthread/src \ + third_party/openthread/src/core \ + third_party/openthread/src/lib/hdlc \ + third_party/openthread/src/lib/spinel \ + third_party/openthread/src/ncp \ + third_party/openthread/third_party/jlink/SEGGER_RTT_V640/RTT + +COMPONENT_SRCDIRS := \ + src \ + third_party/openthread/src/cli \ + third_party/openthread/src/core \ + third_party/openthread/src/core/api \ + third_party/openthread/src/core/coap \ + third_party/openthread/src/core/common \ + third_party/openthread/src/core/crypto \ + third_party/openthread/src/core/mac \ + third_party/openthread/src/core/meshcop \ + third_party/openthread/src/core/net \ + third_party/openthread/src/core/radio \ + third_party/openthread/src/core/thread \ + third_party/openthread/src/core/utils \ + third_party/openthread/src/lib/hdlc \ + third_party/openthread/src/lib/spinel \ + third_party/openthread/src/ncp + +COMPONENT_OBJEXCLUDE := \ + third_party/openthread/src/core/common/extension_example.o + +COMMON_FLAGS := \ + -D_GNU_SOURCE \ + -DOPENTHREAD_CONFIG_FILE=\ \ + -DOPENTHREAD_FTD=1 \ + -DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1 \ + -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"openthread-core-esp32-config.h\" \ + -DSPINEL_PLATFORM_HEADER=\"spinel_platform.h\" \ + -Wno-error=non-virtual-dtor + +CFLAGS += $(COMMON_FLAGS) + +CXXFLAGS += $(COMMON_FLAGS) + +CPPFLAGS += $(COMMON_FLAGS) diff --git a/doc/images/connect-devices.jpg b/doc/images/connect-devices.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43511e2f6cbe60e9afbe5972c502407f77ef6a24 GIT binary patch literal 206960 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 nRF52840.P0.06 +- ESP32.IO4 <---> nRF52840.P0.08 + +![Connect-Devices](../doc/images/connect-devices.jpg) + +## Run the CLI application + +Connect to the ESP32 board from the Linux host: + +```shell +make monitor +``` + +_Note: Dependending on your Linux distribution, the new line characters ('\r', '\n') may cause commands display issues. To have good look of the CLI, Connect the ESP32 board with advanced command `picocom -b 115200 /dev/ttyUSB0 --imap lfcrlf` (install `picocom` with `sudo apt-get install picocom`)._ + +The CLI application is now in interactive mode and waiting for commands, start the OpenThread stack to verify your setup: + +```shell +> dataset init new +Done +> dataset +Active Timestamp: 1 +Channel: 13 +Channel Mask: 07fff800 +Ext PAN ID: d63e8e3e495ebbc3 +Mesh Local Prefix: fd3d:b50b:f96d:722d/64 +Master Key: dfd34f0f05cad978ec4e32b0413038ff +Network Name: OpenThread-8f28 +PAN ID: 0x8f28 +PSKc: c23a76e98f1a6483639b1ac1271e2e27 +Security Policy: 0, onrcb +Done +> dataset commit active +Done +> ifconfig up +Done +> thread start +Done +``` diff --git a/example/main/cli.c b/example/main/cli.c new file mode 100644 index 0000000..13a45e2 --- /dev/null +++ b/example/main/cli.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements an example OpenThread CLI application. + * + * This file is just for example, but not for production. + * + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define CLI_LOG_TAG "OT_CLI" + +static void run_cli(void *aContext) +{ + OT_UNUSED_VARIABLE(aContext); + +pseudo_reset: + + otSysInit(0, NULL); + + otSysApiLock(); + + size_t instanceSize = 0; + + // Get the instance size. + otInstanceInit(NULL, &instanceSize); + void *instanceBuffer = malloc(instanceSize); + + otInstance *instance = otInstanceInit(instanceBuffer, &instanceSize); + + assert(instance != NULL); + + otCliUartInit(instance); + otSysApiUnlock(); + + if (!heap_caps_check_integrity_all(true)) + { + ESP_LOGE(CLI_LOG_TAG, "heap corrupted"); + abort(); + } + + while (!otSysPseudoResetWasRequested()) + { + otSysMainloopContext mainloop; + + otSysMainloopInit(&mainloop); + + otSysApiLock(); + otTaskletsProcess(instance); + otSysMainloopUpdate(instance, &mainloop); + otSysApiUnlock(); + + if (otSysMainloopPoll(&mainloop) >= 0) + { + otSysApiLock(); + otSysMainloopProcess(instance, &mainloop); + otSysApiUnlock(); + } + else + { + ESP_LOGE(CLI_LOG_TAG, "OpenThread system polling failed"); + abort(); + } + } + + otInstanceFinalize(instance); + otSysDeinit(); + + goto pseudo_reset; + + vTaskDelete(NULL); +} + +void app_main() +{ + xTaskCreate(run_cli, "cli", 10 * 1024, NULL, 5, NULL); +} diff --git a/example/main/component.mk b/example/main/component.mk new file mode 100644 index 0000000..42861ed --- /dev/null +++ b/example/main/component.mk @@ -0,0 +1,30 @@ +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Description: +# Dummy component file. +# diff --git a/example/partitions.csv b/example/partitions.csv new file mode 100644 index 0000000..3581674 --- /dev/null +++ b/example/partitions.csv @@ -0,0 +1,35 @@ +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Description: +# Espressif ESP32 Partition Table for openthread-esp32-cli demo App. +# +# Name, Type, SubType, Offset, Size + nvs, data, nvs, 0x9000, 0x6000 + phy_init, data, phy, 0xf000, 0x1000 + factory, app, factory, 0x10000, 1M + ot_storage, data, fat, , 512K, diff --git a/example/sdkconfig.defaults b/example/sdkconfig.defaults new file mode 100644 index 0000000..26cf12b --- /dev/null +++ b/example/sdkconfig.defaults @@ -0,0 +1,34 @@ +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= +CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= +CONFIG_MBEDTLS_DEBUG= +CONFIG_MBEDTLS_ECP_RESTARTABLE= +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI= +CONFIG_MBEDTLS_HARDWARE_SHA= +CONFIG_MBEDTLS_HAVE_TIME=y +CONFIG_MBEDTLS_HAVE_TIME_DATE= +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +CONFIG_MBEDTLS_TLS_SERVER_ONLY= +CONFIG_MBEDTLS_TLS_CLIENT_ONLY= +CONFIG_MBEDTLS_TLS_DISABLED= +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP= +CONFIG_PARTITION_TABLE_TWO_OTA= +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y diff --git a/include/openthread/openthread-esp32.h b/include/openthread/openthread-esp32.h new file mode 100644 index 0000000..fb3fbd3 --- /dev/null +++ b/include/openthread/openthread-esp32.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file defines the platform-specific functions needed by OpenThread's example applications. + */ + +#ifndef OT_ESP32_OPENTHREAD_ESP32_H_ +#define OT_ESP32_OPENTHREAD_ESP32_H_ + +#include +#include +#include + +#include +#include + +/** + * The minimum FreeRTOS stack size required by the OT stack. + * + * It is not recommended to run the OT stack in tasks with + * stack size smaller than this value. + * + */ +#define OT_MIN_RTOS_STACK_SIZE (10 * 1024) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This structure represents a context for a select() based mainloop. + * + */ +typedef struct otSysMainloopContext +{ + fd_set mReadFdSet; ///< The read file descriptors. + fd_set mWriteFdSet; ///< The write file descriptors. + fd_set mErrorFdSet; ///< The error file descriptors. + int mMaxFd; ///< The max file descriptor. + struct timeval mTimeout; ///< The timeout. +} otSysMainloopContext; + +/** + * This function performs all platform-specific initialization of OpenThread's drivers. + * + * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function + * when initialization of OpenThread's drivers is most appropriate. + * + * @param[in] argc Number of arguments in @p argv. + * @param[in] argv Argument vector. + * + */ +void otSysInit(int argc, char *argv[]); + +/** + * This function performs all platform-specific deinitialization for OpenThread's drivers. + * + * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function + * when deinitialization of OpenThread's drivers is most appropriate. + * + */ +void otSysDeinit(void); + +/** + * This function returns true if a pseudo-reset was requested. + * + * In such a case, the main loop should shut down and re-initialize the OpenThread instance. + * + * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function + * in the main loop to determine when to shut down and re-initialize the OpenThread instance. + * + */ +bool otSysPseudoResetWasRequested(void); + +/** + * This function initialize a mainloop context. + * + * @param[inout] aMainloop A pointer to the mainloop to be initialized. + * + */ +void otSysMainloopInit(otSysMainloopContext *aMainloop); + +/** + * This function updates the mainloop context. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[inout] aMainloop A pointer to the mainloop context. + * + */ +void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop); + +/** + * This function polls OpenThread's mainloop. + * + * @param[inout] aMainloop A pointer to the mainloop context. + * + * @returns value returned from select(). + * + */ +int otSysMainloopPoll(otSysMainloopContext *aMainloop); + +/** + * This function performs all platform-specific processing for OpenThread's example applications. + * + * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function + * in the main loop when processing OpenThread's drivers is most appropriate. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[in] aMainloop A pointer to the mainloop context. + * + */ +void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); + +/** + * This functions locks the OpenThread API lock. + * + * Every OT APIs that takes an otInstance argument + * MUST be protected with this API lock except that + * the call site is in OT callbacks. + * + */ +void otSysApiLock(void); + +/** + * This function unlocks the OpenThread API lock. + * + */ +void otSysApiUnlock(void); + +#ifdef __cplusplus +} // end of extern "C" +#endif + +#endif // OT_ESP32_OPENTHREAD_ESP32_H_ diff --git a/script/bootstrap b/script/bootstrap new file mode 100755 index 0000000..dcc7339 --- /dev/null +++ b/script/bootstrap @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Description: +# This file installs all needed dependencies and toolchains needed for +# example compilation and programming. +# + +third_party/openthread/script/bootstrap diff --git a/script/check-esp32-build b/script/check-esp32-build new file mode 100755 index 0000000..35f5675 --- /dev/null +++ b/script/check-esp32-build @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set -euxo pipefail + +setup_esp_idf() +{ + git clone --branch release/v3.3 --recursive https://github.com/espressif/esp-idf.git + export IDF_PATH="$(pwd)"/esp-idf + + pip3 install wheel setuptools + "${IDF_PATH}"/install.sh + python3 -m pip install --user -r "${IDF_PATH}"/requirements.txt + + source ${IDF_PATH}/export.sh +} + +build_cli_app() +{ + cd example + VERBOSE=1 make defconfig + VERBOSE=1 make -j4 +} + +main() +{ + setup_esp_idf + build_cli_app +} + +main diff --git a/script/clang-format b/script/clang-format new file mode 100755 index 0000000..8cbcc0d --- /dev/null +++ b/script/clang-format @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +third_party/openthread/script/clang-format "$@" diff --git a/script/clang-format-check b/script/clang-format-check new file mode 100755 index 0000000..470e95d --- /dev/null +++ b/script/clang-format-check @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +third_party/openthread/script/clang-format-check "$@" diff --git a/script/make-pretty b/script/make-pretty new file mode 100755 index 0000000..dc32c12 --- /dev/null +++ b/script/make-pretty @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Copyright (c) 2019, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +third_party/openthread/script/make-pretty "$@" diff --git a/src/alarm.c b/src/alarm.c new file mode 100644 index 0000000..4f36327 --- /dev/null +++ b/src/alarm.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "error_handling.h" + +static uint64_t sAlarmT0 = 0; +static uint64_t sAlarmDt = 0; +static bool sIsRunning = false; + +void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) +{ + OT_UNUSED_VARIABLE(aInstance); + + sAlarmT0 = aT0; + sAlarmDt = aDt; + sIsRunning = true; + + ESP_LOGD(OT_PLAT_LOG_TAG, "alarm start running, t0=%llu, dt=%llu", sAlarmT0, sAlarmDt); +} + +void otPlatAlarmMilliStop(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + + sIsRunning = false; +} + +uint32_t otPlatAlarmMilliGetNow(void) +{ + return esp_timer_get_time() / OT_US_PER_MS; +} + +void platformAlarmUpdate(otSysMainloopContext *aMainloop) +{ + struct timeval *timeout = &aMainloop->mTimeout; + uint32_t now = otPlatAlarmMilliGetNow(); + + if (!sIsRunning) + { + timeout->tv_sec = INT32_MAX; + timeout->tv_usec = 0; + } + else if (sAlarmDt + sAlarmT0 > now) + { + uint64_t remaining = sAlarmDt + sAlarmT0 - now; + timeout->tv_sec = remaining / OT_MS_PER_S; + timeout->tv_usec = (remaining % OT_MS_PER_S) * OT_US_PER_MS; + } + else + { + timeout->tv_sec = 0; + timeout->tv_usec = 0; + } +} + +void platformAlarmProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop) +{ + OT_UNUSED_VARIABLE(aMainloop); + + if (sIsRunning) + { + if (sAlarmT0 + sAlarmDt <= otPlatAlarmMilliGetNow()) + { + sIsRunning = false; + +#if OPENTHREAD_CONFIG_DIAG_ENABLE + + if (otPlatDiagModeGet()) + { + otPlatDiagAlarmFired(aInstance); + } + else +#endif + { + otPlatAlarmMilliFired(aInstance); + } + + ESP_LOGD(OT_PLAT_LOG_TAG, "alarm fired"); + } + } +} diff --git a/src/api_lock.c b/src/api_lock.c new file mode 100644 index 0000000..14cd4b8 --- /dev/null +++ b/src/api_lock.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include +#include +#include + +#include + +#include "error_handling.h" + +static SemaphoreHandle_t sApiMutex = NULL; + +void otSysApiLock(void) +{ + BaseType_t ret = xSemaphoreTake(sApiMutex, portMAX_DELAY); + VerifyOrDie(ret == pdTRUE, OT_EXIT_FAILURE); +} + +void otSysApiUnlock(void) +{ + xSemaphoreGive(sApiMutex); +} + +void platformApiLockInit(void) +{ + sApiMutex = xSemaphoreCreateMutex(); + VerifyOrDie(sApiMutex != NULL, OT_EXIT_FAILURE); +} + +void platformApiLockDeinit(void) +{ + vSemaphoreDelete(sApiMutex); + sApiMutex = NULL; +} diff --git a/src/error_handling.h b/src/error_handling.h new file mode 100644 index 0000000..4dd0ab1 --- /dev/null +++ b/src/error_handling.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_ESP32_ERROR_HANDLING_H_ +#define OT_ESP32_ERROR_HANDLING_H_ + +#include "core/common/code_utils.hpp" +#include "core/common/logging.hpp" +#include "lib/platform/exit_code.h" + +#endif // OT_ESP32_ERROR_HANDLING_H_ diff --git a/src/flash.c b/src/flash.c new file mode 100644 index 0000000..fb2d939 --- /dev/null +++ b/src/flash.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "error_handling.h" + +static const esp_partition_t *sSettingsPartition = NULL; + +/** + * Dummy otPlatSettings APIs implementation. + */ +void otPlatSettingsInit(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); +} + +void otPlatSettingsDeinit(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); +} + +otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aIndex); + OT_UNUSED_VARIABLE(aValue); + OT_UNUSED_VARIABLE(aValueLength); + return OT_ERROR_NOT_FOUND; +} + +otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aValue); + OT_UNUSED_VARIABLE(aValueLength); + return OT_ERROR_NONE; +} + +otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aValue); + OT_UNUSED_VARIABLE(aValueLength); + return OT_ERROR_NONE; +} + +otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aIndex); + return OT_ERROR_NONE; +} + +void otPlatFlashInit(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + + // esp32 startup code automatically call spi_flash_init(); + + sSettingsPartition = + esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, OT_FLASH_PARTITION_NAME); + + VerifyOrDie(sSettingsPartition != NULL, OT_EXIT_FAILURE); +} + +uint32_t otPlatFlashGetSwapSize(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + + return SETTINGS_CONFIG_PAGE_NUM * SETTINGS_CONFIG_PAGE_SIZE; +} + +void otPlatFlashErase(otInstance *aInstance, uint8_t aSwapIndex) +{ + const esp_partition_t *partition; + uint32_t address; + uint32_t size; + + OT_UNUSED_VARIABLE(aInstance); + + assert(sSettingsPartition != NULL); + + partition = sSettingsPartition; + address = SETTINGS_CONFIG_PAGE_SIZE * (aSwapIndex != 0); + size = SETTINGS_CONFIG_PAGE_SIZE; + + esp_err_t error = esp_partition_erase_range(partition, address, size); + VerifyOrDie(error == ESP_OK, OT_EXIT_FAILURE); +} + +void otPlatFlashRead(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, void *aData, uint32_t aSize) +{ + OT_UNUSED_VARIABLE(aInstance); + + esp_err_t error = ESP_FAIL; + + VerifyOrExit(sSettingsPartition != NULL, OT_NOOP); + + aOffset += SETTINGS_CONFIG_PAGE_SIZE * (aSwapIndex != 0); + + SuccessOrExit(error = esp_partition_read(sSettingsPartition, aOffset, aData, aSize)); + +exit: + VerifyOrDie(error == ESP_OK, OT_EXIT_FAILURE); +} + +void otPlatFlashWrite(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, const void *aData, uint32_t aSize) +{ + OT_UNUSED_VARIABLE(aInstance); + + esp_err_t error = ESP_FAIL; + + VerifyOrExit(sSettingsPartition != NULL, OT_NOOP); + + aOffset += SETTINGS_CONFIG_PAGE_SIZE * (aSwapIndex != 0); + + SuccessOrExit(error = esp_partition_write(sSettingsPartition, aOffset, aData, aSize)); + +exit: + VerifyOrDie(error == ESP_OK, OT_EXIT_FAILURE); +} diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..79824f2 --- /dev/null +++ b/src/logging.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include + +#include + +#include +#include + +#include "error_handling.h" + +#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \ + (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL) +OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) +{ + char logString[256]; + int charsWritten; + va_list args; + + OT_UNUSED_VARIABLE(aLogRegion); + + va_start(args, aFormat); + charsWritten = vsnprintf(logString, sizeof(logString), aFormat, args); + if (charsWritten < 0) + { + logString[0] = '\0'; + } + + switch (aLogLevel) + { + case OT_LOG_LEVEL_CRIT: + ESP_LOGE(OT_PLAT_LOG_TAG, "%s", logString); + break; + case OT_LOG_LEVEL_WARN: + ESP_LOGW(OT_PLAT_LOG_TAG, "%s", logString); + break; + case OT_LOG_LEVEL_NOTE: + case OT_LOG_LEVEL_INFO: + ESP_LOGI(OT_PLAT_LOG_TAG, "%s", logString); + break; + default: + ESP_LOGD(OT_PLAT_LOG_TAG, "%s", logString); + break; + } + va_end(args); +} +#endif diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..bba3bc0 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +void *otPlatCAlloc(size_t aNum, size_t aSize) +{ + return calloc(aNum, aSize); +} + +void otPlatFree(void *aPtr) +{ + free(aPtr); +} diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..322a7e0 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include + +#include + +#include + +static otPlatResetReason sPlatResetReason = OT_PLAT_RESET_REASON_POWER_ON; +bool gPlatformPseudoResetWasRequested; +static otPlatMcuPowerState gPlatMcuPowerState = OT_PLAT_MCU_POWER_STATE_ON; + +void otPlatReset(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + gPlatformPseudoResetWasRequested = true; +} + +otPlatResetReason otPlatGetResetReason(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sPlatResetReason; +} + +void otPlatWakeHost(void) +{ + // Not Implemented. +} + +otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) +{ + otError error = OT_ERROR_NONE; + + OT_UNUSED_VARIABLE(aInstance); + + switch (aState) + { + case OT_PLAT_MCU_POWER_STATE_ON: + case OT_PLAT_MCU_POWER_STATE_LOW_POWER: + gPlatMcuPowerState = aState; + break; + + default: + error = OT_ERROR_FAILED; + break; + } + + return error; +} + +otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return gPlatMcuPowerState; +} + +void otPlatAssertFail(const char *aFilename, int aLineNumber) +{ + OT_UNUSED_VARIABLE(aFilename); + OT_UNUSED_VARIABLE(aLineNumber); + assert(false); +} diff --git a/src/openthread-core-esp32-config.h b/src/openthread-core-esp32-config.h new file mode 100644 index 0000000..f7d8da1 --- /dev/null +++ b/src/openthread-core-esp32-config.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_ESP32_OPENTHREAD_CORE_ESP32_CONFIG_H_ +#define OT_ESP32_OPENTHREAD_CORE_ESP32_CONFIG_H_ + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_INFO + * + * The platform-specific string to insert into the OpenThread version string. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_INFO "ESP32" + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT + * + * The assert is managed by platform defined logic when this flag is set. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT 1 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE + * + * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage. + * + * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_LOG_OUTPUT + * + * The ESP32 platform provides an otPlatLog() function. + */ +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED + +/** + * @def OPENTHREAD_CONFIG_LOG_LEVEL + * + * The log level (used at compile time). If `OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE` is set, this defines the most + * verbose log level possible. See `OPENTHREAD_CONFIG_LOG_LEVEL_INIT` to set the initial log level. + * + */ +#ifndef OPENTHREAD_CONFIG_LOG_LEVEL +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_INFO +#endif + +/** + * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS + * + * The number of message buffers in buffer pool + */ +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50 + +/** + * @def OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE + * + * Enable setting steering data out of band. + * + */ +#ifndef OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE +#define OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_COAP_API_ENABLE + * + * Define to 1 to enable the CoAP API. + * + */ +#define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE + * + * Define to 1 to enable Border Router support. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + * + * Define to 1 to enable Thread Test Harness reference device support. + * + */ +#ifndef OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE + * + * Define to 1 to enable Child Supervision support. + * + */ +#ifndef OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE +#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE + * + * Define to 1 to enable DHCPv6 Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE + * + * Define to 1 to enable DHCPv6 Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE + * + * Define to 1 to enable DNS Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE + * + * Define to 1 to enable multiple instance support. + * + */ +#define OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE + * + * Define to 1 to enable NCP SPI support. + * + */ +#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0 + +/** + * @def OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER + * + * Define to 1 to enable NCP Spinel Encrypter. + * + */ +#define OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 0 + +/** + * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE + * + * Define to 1 to enable NCP UART support. + * + */ +#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + * + * Define to 1 to support injecting Service entries into the Thread Network Data. + * + */ +#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1 + +/** + * @def PACKAGE + * + * Name of package. + * + */ +#define PACKAGE "openthread" + +/** + * @def PACKAGE_BUGREPORT + * + * Define to the address where bug reports for this package should be sent. + * + */ +#define PACKAGE_BUGREPORT "openthread-devel@googlegroups.com" + +/** + * @def PACKAGE_NAME + * + * Define to the full name of this package. + * + */ +#define PACKAGE_NAME "ot-esp32" + +/** + * @def PACKAGE_VERSION + * + * The package version. + * + */ +#define PACKAGE_VERSION "1.0.0" + +/** + * @def PACKAGE_STRING + * + * Define to the full name and version of this package. + * + */ +#define PACKAGE_STRING (PACKAGE_NAME " - " PACKAGE_VERSION) + +/** + * @def PACKAGE_TARNAME + * + * Define to the one symbol short name of this package. + * + */ +#define PACKAGE_TARNAME PACKAGE_NAME + +/** + * @def PACKAGE_URL + * + * Define to the home page for this package. + * + */ +#define PACKAGE_URL "https://github.com/openthread/ot-esp32" + +#endif // OT_ESP32_OPENTHREAD_CORE_ESP32_CONFIG_H_ diff --git a/src/platform-esp32.h b/src/platform-esp32.h new file mode 100644 index 0000000..862b280 --- /dev/null +++ b/src/platform-esp32.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_ESP32_PLATFORM_ESP32_H_ +#define OT_ESP32_PLATFORM_ESP32_H_ + +#include +#include + +#include + +#include + +#include + +#include "openthread-core-esp32-config.h" + +/** + * The default SPI flash partition used by OpenThread settings. + * + */ +#define OT_FLASH_PARTITION_NAME "ot_storage" + +/** + * The default page number of SPI flash partition used by OpenThread settings. + * + */ +#define SETTINGS_CONFIG_PAGE_NUM 2 + +/** + * The default page size of SPI flash partition used by OpenThread settings. + * + */ +#define SETTINGS_CONFIG_PAGE_SIZE 4096 + +/** + * The default platform logging tag. + * + */ +#define OT_PLAT_LOG_TAG "OT_ESP32_PLAT" + +/** + * The default TXD pin of the radio uart. + * + */ +#ifndef OT_RADIO_UART_TXD +#define OT_RADIO_UART_TXD (GPIO_NUM_2) +#endif + +/** + * The default RXD pin of the radio uart. + * + */ +#ifndef OT_RADIO_UART_RXD +#define OT_RADIO_UART_RXD (GPIO_NUM_5) +#endif + +/** + * The uart used by radio spinel. + * + */ +#ifndef OT_RADIO_UART_NUM +#define OT_RADIO_UART_NUM (UART_NUM_1) +#endif + +/** + * The uart used by OpenThread CLI. + * + */ +#define OT_CLI_UART_NUM (UART_NUM_0) + +/** + * The uart receive buffer size for both CLI uart and radio uart. + * + */ +#define OT_UART_RX_BUF_SIZE (UART_FIFO_LEN * 2) + +/** + * Milliseconds per Second. + * + */ +#ifndef OT_MS_PER_S +#define OT_MS_PER_S 1000 +#endif + +/** + * Microseconds per Millisecond. + * + */ +#ifndef OT_US_PER_MS +#define OT_US_PER_MS 1000 +#endif + +/** + * Microseconds per Second. + * + */ +#ifndef OT_US_PER_S +#define OT_US_PER_S (OT_MS_PER_S * OT_US_PER_MS) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function updates OpenThread alarm events to the mainloop context. + * + * @param[inout] aMainloop The mainloop context; + * + */ +void platformAlarmUpdate(otSysMainloopContext *aMainloop); + +/** + * This function process alarm events. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aMainloop The mainloop context. + * + */ +void platformAlarmProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); + +/** + * This function initialize the CLI UART driver. + * + */ +void platformCliUartInit(void); + +/** + * This function deinitialize the CLI UART driver. + * + */ +void platformCliUartDeinit(void); + +/** + * This function updates CLI UART events to the mainloop context. + * + * param[inout] aMainloop The mainloop context. + * + */ +void platformCliUartUpdate(otSysMainloopContext *aMainloop); + +/** + * This function process CLI UART events. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aMainloop The mainloop context. + * + */ +void platformCliUartProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); + +/** + * This function initializes the radio transceiver. + * + * @param[in] aResetRadio TRUE to reset on init, FALSE to not reset on init. + * @param[in] aRestoreDatasetFromNcp TRUE to restore dataset to host from non-volatile memory + * (only used when attempts to upgrade from NCP to RCP mode), + * FALSE otherwise. + * + */ +void platformRadioInit(bool aResetRadio, bool aRestoreDataSetFromNcp); + +/** + * This function deinitialize the radio driver. + * + */ +void platformRadioDeinit(void); + +/** + * This function updates spinel radio events to the mainloop context. + * + * param[inout] aMainloop The mainloop context. + * + */ +void platformRadioUpdate(otSysMainloopContext *aMainloop); + +/** + * This function process radio events. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aMainloop The mainloop context. + * + */ +void platformRadioProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); + +/** + * This function initializes the API lock. + * + */ +void platformApiLockInit(void); + +/** + * This function deinitialize the API lock. + * + */ +void platformApiLockDeinit(void); + +#ifdef __cplusplus +} +#endif + +#endif // OT_ESP32_PLATFORM_ESP32_H_ diff --git a/src/radio.cpp b/src/radio.cpp new file mode 100644 index 0000000..3f17025 --- /dev/null +++ b/src/radio.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements OpenThread platform driver API in openthread/platform/radio.h. + * + */ + +#include "platform-esp32.h" + +#include + +#include "radio_spinel.hpp" +#include "spinel_hdlc.hpp" + +static ot::Spinel::RadioSpinel sRadioSpinel; + +void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.GetIeeeEui64(aIeeeEui64)); +} + +void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.SetPanId(panid)); +} + +void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + otExtAddress addr; + + for (size_t i = 0; i < sizeof(addr); i++) + { + addr.m8[i] = aAddress->m8[sizeof(addr) - 1 - i]; + } + + SuccessOrDie(sRadioSpinel.SetExtendedAddress(addr)); +} + +void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.SetShortAddress(aAddress)); +} + +void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.SetPromiscuous(aEnable)); +} + +bool otPlatRadioIsEnabled(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.IsEnabled(); +} + +otError otPlatRadioEnable(otInstance *aInstance) +{ + return sRadioSpinel.Enable(aInstance); +} + +otError otPlatRadioDisable(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.Disable(); +} + +otError otPlatRadioSleep(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.Sleep(); +} + +otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.Receive(aChannel); +} + +otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.Transmit(*aFrame); +} + +otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return &sRadioSpinel.GetTransmitFrame(); +} + +int8_t otPlatRadioGetRssi(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetRssi(); +} + +otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetRadioCaps(); +} + +const char *otPlatRadioGetVersionString(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetVersion(); +} + +bool otPlatRadioGetPromiscuous(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.IsPromiscuous(); +} + +void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.EnableSrcMatch(aEnable)); +} + +otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.AddSrcMatchShortEntry(aShortAddress); +} + +otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + otExtAddress addr; + + for (size_t i = 0; i < sizeof(addr); i++) + { + addr.m8[i] = aExtAddress->m8[sizeof(addr) - 1 - i]; + } + + return sRadioSpinel.AddSrcMatchExtEntry(addr); +} + +otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.ClearSrcMatchShortEntry(aShortAddress); +} + +otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) +{ + OT_UNUSED_VARIABLE(aInstance); + otExtAddress addr; + + for (size_t i = 0; i < sizeof(addr); i++) + { + addr.m8[i] = aExtAddress->m8[sizeof(addr) - 1 - i]; + } + + return sRadioSpinel.ClearSrcMatchExtEntry(addr); +} + +void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.ClearSrcMatchShortEntries()); +} + +void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + SuccessOrDie(sRadioSpinel.ClearSrcMatchExtEntries()); +} + +otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.EnergyScan(aScanChannel, aScanDuration); +} + +otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower) +{ + otError error; + + OT_UNUSED_VARIABLE(aInstance); + VerifyOrExit(aPower != NULL, error = OT_ERROR_INVALID_ARGS); + error = sRadioSpinel.GetTransmitPower(*aPower); + +exit: + return error; +} + +otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.SetTransmitPower(aPower); +} + +otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold) +{ + otError error; + + OT_UNUSED_VARIABLE(aInstance); + VerifyOrExit(aThreshold != NULL, error = OT_ERROR_INVALID_ARGS); + error = sRadioSpinel.GetCcaEnergyDetectThreshold(*aThreshold); + +exit: + return error; +} + +otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.SetCcaEnergyDetectThreshold(aThreshold); +} + +int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetReceiveSensitivity(); +} + +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE +otError otPlatRadioSetCoexEnabled(otInstance *aInstance, bool aEnabled) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.SetCoexEnabled(aEnabled); +} + +bool otPlatRadioIsCoexEnabled(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.IsCoexEnabled(); +} + +otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics) +{ + OT_UNUSED_VARIABLE(aInstance); + + otError error = OT_ERROR_NONE; + + VerifyOrExit(aCoexMetrics != NULL, error = OT_ERROR_INVALID_ARGS); + + error = sRadioSpinel.GetCoexMetrics(*aCoexMetrics); + +exit: + return error; +} +#endif + +#if OPENTHREAD_CONFIG_DIAG_ENABLE +otError otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) +{ + // deliver the platform specific diags commands to radio only ncp. + OT_UNUSED_VARIABLE(aInstance); + char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {'\0'}; + char *cur = cmd; + char *end = cmd + sizeof(cmd); + + for (int index = 0; index < argc; index++) + { + cur += snprintf(cur, static_cast(end - cur), "%s ", argv[index]); + } + + return sRadioSpinel.PlatDiagProcess(cmd, aOutput, aOutputMaxLen); +} + +void otPlatDiagModeSet(bool aMode) +{ + SuccessOrExit(sRadioSpinel.PlatDiagProcess(aMode ? "start" : "stop", NULL, 0)); + sRadioSpinel.SetDiagEnabled(aMode); + +exit: + return; +} + +bool otPlatDiagModeGet(void) +{ + return sRadioSpinel.IsDiagEnabled(); +} + +void otPlatDiagTxPowerSet(int8_t aTxPower) +{ + char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE]; + + snprintf(cmd, sizeof(cmd), "power %d", aTxPower); + SuccessOrExit(sRadioSpinel.PlatDiagProcess(cmd, NULL, 0)); + +exit: + return; +} + +void otPlatDiagChannelSet(uint8_t aChannel) +{ + char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE]; + + snprintf(cmd, sizeof(cmd), "channel %d", aChannel); + SuccessOrExit(sRadioSpinel.PlatDiagProcess(cmd, NULL, 0)); + +exit: + return; +} + +void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aFrame); + OT_UNUSED_VARIABLE(aError); +} + +void otPlatDiagAlarmCallback(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); +} +#endif // OPENTHREAD_CONFIG_DIAG_ENABLE + +uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetRadioChannelMask(false); +} + +uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetRadioChannelMask(true); +} + +otRadioState otPlatRadioGetState(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + return sRadioSpinel.GetState(); +} + +void platformRadioInit(bool aResetRadio, bool aRestoreDataSetFromNcp) +{ + sRadioSpinel.GetSpinelInterface().Init(); + sRadioSpinel.Init(aResetRadio, aRestoreDataSetFromNcp); +} + +void platformRadioDeinit(void) +{ + sRadioSpinel.Deinit(); +} + +void platformRadioProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop) +{ + (void)aInstance; + sRadioSpinel.Process(*aMainloop); +} + +void platformRadioUpdate(otSysMainloopContext *aMainloop) +{ + sRadioSpinel.GetSpinelInterface().Update(*aMainloop); +} diff --git a/src/spinel_hdlc.cpp b/src/spinel_hdlc.cpp new file mode 100644 index 0000000..0f29efa --- /dev/null +++ b/src/spinel_hdlc.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spinel_hdlc.hpp" + +#include "platform-esp32.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "error_handling.h" + +namespace ot { + +namespace Esp32 { + +HdlcInterface::HdlcInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback aCallback, + void * aCallbackContext, + ot::Spinel::SpinelInterface::RxFrameBuffer & aFrameBuffer) + : mReceiveFrameCallback(aCallback) + , mReceiveFrameContext(aCallbackContext) + , mReceiveFrameBuffer(aFrameBuffer) + , mHdlcDecoder(aFrameBuffer, HandleHdlcFrame, this) +{ +} + +HdlcInterface::~HdlcInterface(void) +{ +} + +void HdlcInterface::Init(void) +{ + mUartRxBuffer = static_cast(heap_caps_malloc(kMaxFrameSize, MALLOC_CAP_8BIT)); + VerifyOrDie(mUartRxBuffer != NULL, OT_EXIT_FAILURE); + + InitUart(); +} + +void HdlcInterface::Deinit(void) +{ + DeinitUart(); + + heap_caps_free(mUartRxBuffer); + mUartRxBuffer = NULL; +} + +otError HdlcInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength) +{ + otError error = OT_ERROR_NONE; + ot::Hdlc::FrameBuffer encoderBuffer; + ot::Hdlc::Encoder hdlcEncoder(encoderBuffer); + + SuccessOrExit(error = hdlcEncoder.BeginFrame()); + SuccessOrExit(error = hdlcEncoder.Encode(aFrame, aLength)); + SuccessOrExit(error = hdlcEncoder.EndFrame()); + + SuccessOrExit(error = Write(encoderBuffer.GetFrame(), encoderBuffer.GetLength())); + +exit: + if (error != OT_ERROR_NONE) + { + ESP_LOGE(OT_PLAT_LOG_TAG, "send radio frame failed"); + } + else + { + ESP_LOGD(OT_PLAT_LOG_TAG, "sent radio frame\n"); + } + + return error; +} + +void HdlcInterface::Process(const otSysMainloopContext &aMainloop) +{ + if (FD_ISSET(mUartFd, &aMainloop.mReadFdSet)) + { + ESP_LOGD(OT_PLAT_LOG_TAG, "radio uart read event"); + TryReadAndDecode(); + } +} + +void HdlcInterface::Update(otSysMainloopContext &aMainloop) +{ + // Register only READ events for radio UART and always wait + // for a radio WRITE to complete. + FD_SET(mUartFd, &aMainloop.mReadFdSet); + if (mUartFd > aMainloop.mMaxFd) + { + aMainloop.mMaxFd = mUartFd; + } +} + +int HdlcInterface::TryReadAndDecode(void) +{ + uint8_t buffer[kMaxFrameSize]; + ssize_t rval; + + rval = read(mUartFd, buffer, sizeof(buffer)); + + if (rval > 0) + { + mHdlcDecoder.Decode(buffer, static_cast(rval)); + } + else if ((rval < 0) && (errno != EAGAIN) && (errno != EINTR)) + { + abort(); + } + + return rval; +} + +otError HdlcInterface::WaitForWritable(void) +{ + otError error = OT_ERROR_NONE; + struct timeval timeout = {kMaxWaitTime / OT_MS_PER_S, (kMaxWaitTime % OT_MS_PER_S) * OT_US_PER_MS}; + uint64_t now = otPlatTimeGet(); + uint64_t end = now + kMaxWaitTime * OT_US_PER_MS; + fd_set writeFds; + fd_set errorFds; + int rval; + + while (true) + { + FD_ZERO(&writeFds); + FD_ZERO(&errorFds); + FD_SET(mUartFd, &writeFds); + FD_SET(mUartFd, &errorFds); + + rval = select(mUartFd + 1, NULL, &writeFds, &errorFds, &timeout); + + if (rval > 0) + { + if (FD_ISSET(mUartFd, &writeFds)) + { + ExitNow(); + } + else if (FD_ISSET(mUartFd, &errorFds)) + { + VerifyOrDie(false, OT_EXIT_FAILURE); + } + else + { + assert(false); + } + } + else if ((rval < 0) && (errno != EINTR)) + { + VerifyOrDie(false, OT_EXIT_FAILURE); + } + + now = otPlatTimeGet(); + + if (end > now) + { + uint64_t remain = end - now; + + timeout.tv_sec = static_cast(remain / 1000000); + timeout.tv_usec = static_cast(remain % 1000000); + } + else + { + break; + } + } + + error = OT_ERROR_FAILED; + +exit: + return error; +} + +otError HdlcInterface::Write(const uint8_t *aFrame, uint16_t aLength) +{ + otError error = OT_ERROR_NONE; + + while (aLength) + { + ssize_t rval = write(mUartFd, aFrame, aLength); + + if (rval > 0) + { + assert(rval <= aLength); + aLength -= static_cast(rval); + aFrame += static_cast(rval); + continue; + } + + if ((rval < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) + { + abort(); + } + + SuccessOrExit(error = WaitForWritable()); + } + +exit: + return error; +} + +otError HdlcInterface::WaitForFrame(uint64_t aTimeoutUs) +{ + otError error = OT_ERROR_NONE; + struct timeval timeout; + fd_set read_fds; + fd_set error_fds; + int rval; + + FD_ZERO(&read_fds); + FD_ZERO(&error_fds); + FD_SET(mUartFd, &read_fds); + FD_SET(mUartFd, &error_fds); + + timeout.tv_sec = static_cast(aTimeoutUs / OT_US_PER_S); + timeout.tv_usec = static_cast(aTimeoutUs % OT_US_PER_S); + + rval = select(mUartFd + 1, &read_fds, NULL, &error_fds, &timeout); + + if (rval > 0) + { + if (FD_ISSET(mUartFd, &read_fds)) + { + TryReadAndDecode(); + } + else if (FD_ISSET(mUartFd, &error_fds)) + { + abort(); + } + else + { + abort(); + } + } + else if (rval == 0) + { + ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT); + } + else if (errno != EINTR) + { + abort(); + } + +exit: + return error; +} + +void HdlcInterface::HandleHdlcFrame(void *aContext, otError aError) +{ + static_cast(aContext)->HandleHdlcFrame(aError); +} + +void HdlcInterface::HandleHdlcFrame(otError aError) +{ + if (aError == OT_ERROR_NONE) + { + ESP_LOGD(OT_PLAT_LOG_TAG, "received hdlc radio frame\n"); + mReceiveFrameCallback(mReceiveFrameContext); + } + else + { + ESP_LOGE(OT_PLAT_LOG_TAG, "dropping radio frame: %s\n", otThreadErrorToString(aError)); + mReceiveFrameBuffer.DiscardFrame(); + } +} + +void HdlcInterface::InitUart(void) +{ + char uartPath[16]; + uart_config_t uart_config = {.baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 0, + .use_ref_tick = false}; + + ESP_ERROR_CHECK(uart_param_config(OT_RADIO_UART_NUM, &uart_config)); + ESP_ERROR_CHECK( + uart_set_pin(OT_RADIO_UART_NUM, OT_RADIO_UART_TXD, OT_RADIO_UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + ESP_ERROR_CHECK(uart_driver_install(OT_RADIO_UART_NUM, OT_UART_RX_BUF_SIZE, 0, 0, NULL, 0)); + + // We have a driver now installed so set up the read/write functions to use driver also. + esp_vfs_dev_uart_use_driver(OT_RADIO_UART_NUM); + + sprintf(uartPath, "/dev/uart/%d", OT_RADIO_UART_NUM); + mUartFd = open(uartPath, O_RDWR | O_NONBLOCK); + + VerifyOrDie(mUartFd != -1, OT_EXIT_FAILURE); +} + +void HdlcInterface::DeinitUart(void) +{ + if (mUartFd != -1) + { + close(mUartFd); + mUartFd = -1; + } + ESP_ERROR_CHECK(uart_driver_delete(OT_RADIO_UART_NUM)); +} + +} // namespace Esp32 + +} // namespace ot diff --git a/src/spinel_hdlc.hpp b/src/spinel_hdlc.hpp new file mode 100644 index 0000000..7a944e0 --- /dev/null +++ b/src/spinel_hdlc.hpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_ESP32_SPINEL_HDLC_HPP_ +#define OT_ESP32_SPINEL_HDLC_HPP_ + +#include "openthread-core-esp32-config.h" + +#include + +#include "lib/spinel/spinel_interface.hpp" + +namespace ot { + +namespace Esp32 { + +typedef uint8_t HdlcSpinelContext; + +/** + * This class defines an HDLC spinel interface to the Radio Co-processor (RCP). + * + */ +class HdlcInterface +{ +public: + /** + * This constructor initializes the object. + * + * @param[in] aCallback Callback on frame received + * @param[in] aCallbackContext Callback context + * @param[in] aFrameBuffer A reference to a `RxFrameBuffer` object. + * + */ + HdlcInterface(ot::Spinel::SpinelInterface::ReceiveFrameCallback aCallback, + void * aCallbackContext, + ot::Spinel::SpinelInterface::RxFrameBuffer & aFrameBuffer); + + /** + * This destructor deinitializes the object. + * + */ + ~HdlcInterface(void); + + /** + * This method initializes the HDLC interface. + * + */ + void Init(void); + + /** + * This method deinitializes the HDLC interface. + * + */ + void Deinit(void); + + /** + * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket. + * + * This is blocking call, i.e., if the socket is not writable, this method waits for it to become writable for + * up to `kMaxWaitTime` interval. + * + * @param[in] aFrame A pointer to buffer containing the spinel frame to send. + * @param[in] aLength The length (number of bytes) in the frame. + * + * @retval OT_ERROR_NONE Successfully encoded and sent the spinel frame. + * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode the frame. + * @retval OT_ERROR_FAILED Failed to send due to socket not becoming writable within `kMaxWaitTime`. + * + */ + otError SendFrame(const uint8_t *aFrame, uint16_t aLength); + + /** + * This method waits for receiving part or all of spinel frame within specified timeout. + * + * @param[in] aTimeoutUs The timeout value in microseconds. + * + * @retval OT_ERROR_NONE Part or all of spinel frame is received. + * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeoutUs. + * + */ + otError WaitForFrame(uint64_t aTimeoutUs); + + /** + * This method performs radio driver processing. + * + * @param[in] aContext The context containing no thing, never used. + * + */ + void Process(const otSysMainloopContext &aMainloop); + + /** + * This methods updates the mainloop context. + * + * @param[in] aMainloop A mainloop context. + * + */ + void Update(otSysMainloopContext &aMainloop); + +private: + enum + { + /** + * Maximum spinel frame size. + * + */ + kMaxFrameSize = ot::Spinel::SpinelInterface::kMaxFrameSize, + + /** + * Maximum wait time in Milliseconds for socket to become writable (see `SendFrame`). + * + */ + kMaxWaitTime = 2000, + }; + + void InitUart(void); + void DeinitUart(void); + + int TryReadAndDecode(void); + + /** + * This method waits for the UART file descriptor associated with the HDLC interface to become writable within + * `kMaxWaitTime` interval. + * + * @retval OT_ERROR_NONE Socket is writable. + * @retval OT_ERROR_FAILED Socket did not become writable within `kMaxWaitTime`. + * + */ + otError WaitForWritable(void); + + /** + * This method writes a given frame to the socket. + * + * This is blocking call, i.e., if the UART is not writable, this method waits for it to become writable for + * up to `kMaxWaitTime` interval. + * + * @param[in] aFrame A pointer to buffer containing the frame to write. + * @param[in] aLength The length (number of bytes) in the frame. + * + * @retval OT_ERROR_NONE Frame was written successfully. + * @retval OT_ERROR_FAILED Failed to write due to UART not becoming writable within `kMaxWaitTime`. + * + */ + otError Write(const uint8_t *aFrame, uint16_t aLength); + + static void HandleHdlcFrame(void *aContext, otError aError); + void HandleHdlcFrame(otError aError); + + ot::Spinel::SpinelInterface::ReceiveFrameCallback mReceiveFrameCallback; + void * mReceiveFrameContext; + ot::Spinel::SpinelInterface::RxFrameBuffer & mReceiveFrameBuffer; + + ot::Hdlc::Decoder mHdlcDecoder; + uint8_t * mUartRxBuffer; + + int mUartFd; + + // Non-copyable, intentionally not implemented. + HdlcInterface(const HdlcInterface &); + HdlcInterface &operator=(const HdlcInterface &); +}; + +} // namespace Esp32 + +} // namespace ot + +#endif // OT_ESP32_SPINEL_HDLC_HPP_ diff --git a/src/system.c b/src/system.c new file mode 100644 index 0000000..b8289d0 --- /dev/null +++ b/src/system.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +extern bool gPlatformPseudoResetWasRequested; + +void otSysInit(int argc, char *argv[]) +{ + OT_UNUSED_VARIABLE(argc); + OT_UNUSED_VARIABLE(argv); + + if (gPlatformPseudoResetWasRequested) + { + gPlatformPseudoResetWasRequested = false; + } + + platformApiLockInit(); + platformCliUartInit(); + platformRadioInit(/* aResetRadio */ true, /* aRestoreDataSetFromNcp */ false); + + ESP_LOGI(OT_PLAT_LOG_TAG, "init radio done"); +} + +void otSysDeinit(void) +{ + platformRadioDeinit(); + platformCliUartDeinit(); + platformApiLockDeinit(); +} + +bool otSysPseudoResetWasRequested(void) +{ + return gPlatformPseudoResetWasRequested; +} + +void otSysMainloopInit(otSysMainloopContext *aMainloop) +{ + FD_ZERO(&aMainloop->mReadFdSet); + FD_ZERO(&aMainloop->mWriteFdSet); + FD_ZERO(&aMainloop->mErrorFdSet); + + aMainloop->mMaxFd = -1; + aMainloop->mTimeout.tv_sec = 10; + aMainloop->mTimeout.tv_usec = 0; +} + +void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop) +{ + platformAlarmUpdate(aMainloop); + + platformCliUartUpdate(aMainloop); + + platformRadioUpdate(aMainloop); + + if (otTaskletsArePending(aInstance)) + { + aMainloop->mTimeout.tv_sec = 0; + aMainloop->mTimeout.tv_usec = 0; + } +} + +int otSysMainloopPoll(otSysMainloopContext *aMainloop) +{ + return select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, + &aMainloop->mTimeout); +} + +void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop) +{ + platformCliUartProcess(aInstance, aMainloop); + platformRadioProcess(aInstance, aMainloop); + platformAlarmProcess(aInstance, aMainloop); +} diff --git a/src/time.c b/src/time.c new file mode 100644 index 0000000..0b35a65 --- /dev/null +++ b/src/time.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include +#include + +#include +#include + +#include "error_handling.h" + +/** + * Get the current time (64bits width). + * + * @returns The current time in microseconds. + * + */ +uint64_t otPlatTimeGet(void) +{ + struct timeval tv_now; + + int err = gettimeofday(&tv_now, NULL); + VerifyOrDie(err == 0, OT_EXIT_FAILURE); + + return (uint64_t)tv_now.tv_sec * OT_US_PER_S + tv_now.tv_usec; +} diff --git a/src/uart.c b/src/uart.c new file mode 100644 index 0000000..e52a57b --- /dev/null +++ b/src/uart.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-esp32.h" + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "error_handling.h" + +static int sCliUartFd; + +otError otPlatUartEnable(void) +{ + return OT_ERROR_NONE; +} + +otError otPlatUartDisable(void) +{ + return OT_ERROR_NONE; +} + +otError otPlatUartFlush(void) +{ + return OT_ERROR_NONE; +} + +otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) +{ + otError error = OT_ERROR_NONE; + + int rval = write(sCliUartFd, aBuf, aBufLength); + + VerifyOrExit(rval == (int)aBufLength, error = OT_ERROR_FAILED); + + otPlatUartSendDone(); + +exit: + return error; +} + +void platformCliUartInit() +{ + char uartPath[16]; + uart_config_t uart_config = {.baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 0, + .use_ref_tick = false}; + ESP_ERROR_CHECK(uart_param_config(OT_CLI_UART_NUM, &uart_config)); + + // Disable IO buffer. + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + + // Install UART driver for interrupt-driven reads and writes. + ESP_ERROR_CHECK(uart_driver_install(OT_CLI_UART_NUM, OT_UART_RX_BUF_SIZE, 0, 0, NULL, 0)); + + // Tell VFS to use UART driver. + esp_vfs_dev_uart_use_driver(OT_CLI_UART_NUM); + + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_LF); + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_LF); + + sprintf(uartPath, "/dev/uart/%d", OT_CLI_UART_NUM); + sCliUartFd = open(uartPath, O_RDWR | O_NONBLOCK); + + VerifyOrDie(sCliUartFd != -1, OT_EXIT_FAILURE); +} + +void platformCliUartDeinit(void) +{ + if (sCliUartFd != -1) + { + close(sCliUartFd); + sCliUartFd = -1; + } + uart_driver_delete(OT_CLI_UART_NUM); +} + +void platformCliUartUpdate(otSysMainloopContext *aMainloop) +{ + FD_SET(sCliUartFd, &aMainloop->mReadFdSet); + if (sCliUartFd > aMainloop->mMaxFd) + { + aMainloop->mMaxFd = sCliUartFd; + } +} + +void platformCliUartProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop) +{ + (void)aInstance; + + if (FD_ISSET(sCliUartFd, &aMainloop->mReadFdSet)) + { + uint8_t buffer[256]; + + int rval = read(sCliUartFd, buffer, sizeof(buffer)); + + if (rval > 0) + { + otPlatUartReceived(buffer, (uint16_t)rval); + } + else if (rval > 0) + { + VerifyOrDie(errno == EAGAIN || errno == EINTR, OT_EXIT_FAILURE); + } + } +} diff --git a/third_party/openthread b/third_party/openthread new file mode 160000 index 0000000..aa1b292 --- /dev/null +++ b/third_party/openthread @@ -0,0 +1 @@ +Subproject commit aa1b2927c8898f46583b427ee3293133dd2e7f2c