mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-03 05:36:34 +02:00
Compare commits
180 Commits
console_cm
...
eppp-v0.2.
Author | SHA1 | Date | |
---|---|---|---|
68da69e4d8 | |||
c6e2eb2dac | |||
a9dd78ffad | |||
eb09e42638 | |||
adafeae5cf | |||
d7eaa77b89 | |||
402176c9e0 | |||
085dd79079 | |||
a05fbc7ed9 | |||
ba35d14e43 | |||
2b64e80acd | |||
ac9972aa48 | |||
1c5a149b14 | |||
8d0152f612 | |||
b2272b410d | |||
5d43f9660f | |||
bdbf16c113 | |||
7f248bd03f | |||
dabd4bfd0e | |||
70fa3af771 | |||
5d69d3f0ac | |||
39d59032a2 | |||
e3418b5527 | |||
21d1540b76 | |||
186e258798 | |||
139166c2c5 | |||
7437d31368 | |||
d20255a40c | |||
6af6ca52a2 | |||
042533af90 | |||
732b1d5084 | |||
9e13870ad4 | |||
3f12ef6eea | |||
f1bc070b86 | |||
28c0e0b77b | |||
24ce86756d | |||
39dfe268a3 | |||
d96f45a1f9 | |||
90fdcfc340 | |||
7829e8f976 | |||
ce27c13352 | |||
eab58de630 | |||
fcb60806a9 | |||
22914d4b7b | |||
150a3ec06a | |||
c12616c91d | |||
f05c765e8b | |||
ed021a90d4 | |||
6393fcd79a | |||
c9439bd3d5 | |||
2c4c88b4fb | |||
d45c5cef9a | |||
afd98bb9c5 | |||
8f19c60c19 | |||
281e933808 | |||
f4bdf0ab6c | |||
e25b2a1d9d | |||
608b835680 | |||
93256d159b | |||
3a48c06e96 | |||
e011188377 | |||
1fb1ea9300 | |||
16be2f963b | |||
d786f0db88 | |||
f6f6ded001 | |||
eb84eed8d3 | |||
5df46437f2 | |||
bd6b66d9d1 | |||
d0c17ef0d5 | |||
06d013b20b | |||
f032a9f023 | |||
d16387859f | |||
6c82ce2915 | |||
d2b7c55b89 | |||
fd168d86fc | |||
d4c6d5ed5d | |||
c728eae5ea | |||
bd6e120509 | |||
13793a8236 | |||
0140455ff7 | |||
c4d9cc6beb | |||
887dbcd73b | |||
b3ba71ff4d | |||
fbdb2483f5 | |||
af330b6396 | |||
0b94d9ec47 | |||
f26f2f88c2 | |||
08d06a4b7d | |||
cb682a793e | |||
d053d671f4 | |||
16b79d170b | |||
dfb0035858 | |||
1750a3fda9 | |||
2a3db45ef1 | |||
fcc61e0929 | |||
4bdd90cc88 | |||
14763888ed | |||
a5954dda17 | |||
8bd4712677 | |||
a65d81c954 | |||
2585565483 | |||
b9c675b0b1 | |||
d4e693e392 | |||
963b32e7b4 | |||
cffe26818b | |||
08a62ccc85 | |||
56fe53279e | |||
5baaf54291 | |||
38de23fb1c | |||
84390eb4d4 | |||
4e844936b7 | |||
21c84bfa8d | |||
438449f58f | |||
a23a0027fa | |||
3f74b4e8c0 | |||
46a6244c37 | |||
7be16bcc88 | |||
1fb02a9a60 | |||
b5be844c92 | |||
5b467cbf5c | |||
f8a776d8a5 | |||
a82c7922aa | |||
d31ad025c8 | |||
4977f96a61 | |||
dcdf31187a | |||
b6bbe47cae | |||
302b46f8e2 | |||
45b1597ac3 | |||
a06de6431b | |||
3b80181d30 | |||
edc3c2dee0 | |||
943b683d38 | |||
d0ace0d1c9 | |||
9c54b72e1f | |||
16174470ee | |||
a363beea6f | |||
a8035c21a2 | |||
7eefcf084e | |||
18f845275f | |||
ad27414a64 | |||
a7610395ef | |||
9b7c8755e9 | |||
0d0630ed76 | |||
38a3631a27 | |||
96f4ebd994 | |||
247ca41bb7 | |||
891384cc53 | |||
38ef603296 | |||
312982e4aa | |||
d9d377133e | |||
110536ebb2 | |||
d85311880d | |||
27adbfeb3b | |||
5ba7cfab8e | |||
2f7c58259d | |||
2b092e0db4 | |||
f42c0adfc0 | |||
2782277f3f | |||
3225f40c22 | |||
d63f831fff | |||
f62db5cfa2 | |||
68ce794098 | |||
60174f290e | |||
efa26b7062 | |||
7b777948fc | |||
1dc4299eb0 | |||
ce7daddc77 | |||
09e68cc0c0 | |||
fc59f87c4e | |||
7a2b23909f | |||
d3bf773445 | |||
1c29af9237 | |||
b53981a68c | |||
5000a9a20a | |||
2646dcd23a | |||
741d166034 | |||
eb7699388c | |||
aa4e9d5795 | |||
6d2c475c20 | |||
adde6df6e8 |
16
.github/workflows/asio__build-target-test.yml
vendored
16
.github/workflows/asio__build-target-test.yml
vendored
@ -13,16 +13,16 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32", "esp32s2"]
|
||||
example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/asio/examples
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
@ -43,7 +43,7 @@ jobs:
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
esptool.py --chip ${{ matrix.idf_target }} merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
path: |
|
||||
@ -64,7 +64,7 @@ jobs:
|
||||
name: Target tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
example: ["asio_chat", "tcp_echo_server", "udp_echo_server", "ssl_client_server"]
|
||||
needs: build_asio
|
||||
@ -76,8 +76,8 @@ jobs:
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: examples_app_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
path: ${{ env.TEST_DIR }}/${{ matrix.example }}/build
|
||||
@ -93,7 +93,7 @@ jobs:
|
||||
working-directory: ${{ env.TEST_DIR }}/${{ matrix.example }}
|
||||
run: |
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.config }}.xml --target=${{ matrix.idf_target }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: examples_results_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.example }}
|
||||
|
55
.github/workflows/clang-tidy.yml
vendored
Normal file
55
.github/workflows/clang-tidy.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
name: Run clang-tidy
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Run clang-tidy
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: Install esp-clang
|
||||
run: |
|
||||
${IDF_PATH}/tools/idf_tools.py --non-interactive install esp-clang
|
||||
- name: Install clang-tidy-sarif
|
||||
run: |
|
||||
curl -sSL https://github.com/psastras/sarif-rs/releases/download/clang-tidy-sarif-v0.3.3/clang-tidy-sarif-x86_64-unknown-linux-gnu -o clang-tidy-sarif
|
||||
chmod +x clang-tidy-sarif
|
||||
curl -sSL https://raw.githubusercontent.com/espressif/idf-extra-components/master/.github/filter_sarif.py -o filter_sarif.py
|
||||
- name: Install pyclang
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install pyclang~=0.2.0
|
||||
- name: Run code analysis
|
||||
shell: bash
|
||||
env:
|
||||
IDF_TOOLCHAIN: clang
|
||||
IDF_TARGET: esp32
|
||||
working-directory: test_app
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
idf.py clang-check --include-paths $GITHUB_WORKSPACE --exclude-paths $PWD --run-clang-tidy-py run-clang-tidy
|
||||
cp warnings.txt ../
|
||||
- name: Convert clang-tidy results into SARIF output
|
||||
run: |
|
||||
export PATH=$PWD:$PATH
|
||||
./clang-tidy-sarif -o results.sarif.raw warnings.txt
|
||||
python3 filter_sarif.py -o results.sarif --include-prefix ${GITHUB_WORKSPACE}/ results.sarif.raw
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
path: |
|
||||
warnings.txt
|
||||
results.sarif
|
||||
results.sarif.raw
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: clang-tidy
|
@ -13,20 +13,26 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: ifconfig-basic, path: "components/console_cmd_ifconfig/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
test: [ { app: ifconfig-basic, path: "components/console_cmd_ifconfig/examples"}]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
warning: "the choice symbol ETHERNET_PHY_LAN867X\nis deprecated: Please use smi_gpio instead"
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
32
.github/workflows/console_cmd_iperf__build.yml
vendored
32
.github/workflows/console_cmd_iperf__build.yml
vendored
@ -1,32 +0,0 @@
|
||||
name: "console_cmd_iperf: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_console_cmd_iperf:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'console') || github.event_name == 'push'
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.0"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: iperf-basic, path: "components/console_cmd_iperf/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
@ -13,20 +13,20 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: ping-basic, path: "components/console_cmd_ping/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
@ -13,20 +13,20 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: wifi-basic, path: "components/console_cmd_wifi/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
@ -13,20 +13,20 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: console_basic, path: "components/console_simple_init/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
28
.github/workflows/eppp__build.yml
vendored
Normal file
28
.github/workflows/eppp__build.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: "eppp_link: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_eppp:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'eppp') || github.event_name == 'push'
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3"]
|
||||
test: [ { app: host, path: "examples/host" }, { app: slave, path: "examples/slave" }, { app: test_app, path: "test/test_app" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/eppp_link/${{matrix.test.path}} -vv --preserve-all
|
10
.github/workflows/examples_build-host-test.yml
vendored
10
.github/workflows/examples_build-host-test.yml
vendored
@ -13,12 +13,12 @@ jobs:
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.1"]
|
||||
runs-on: ubuntu-20.04
|
||||
idf_ver: ["latest", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
@ -33,11 +33,11 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
|
16
.github/workflows/mdns__build-target-test.yml
vendored
16
.github/workflows/mdns__build-target-test.yml
vendored
@ -13,20 +13,20 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.2", "release-v5.3"]
|
||||
test: [ { app: example, path: "examples/query_advertise" }, { app: unit_test, path: "tests/unit_test" }, { app: test_app, path: "tests/test_apps" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
# Build default configs for all targets
|
||||
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }} -r default -m components/mdns/.build-test-rules.yml -d
|
||||
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }} -r default -d
|
||||
# Build specific configs for test targets
|
||||
python ./ci/build_apps.py components/mdns/${{ matrix.test.path }}
|
||||
cd components/mdns/${{ matrix.test.path }}
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
|
||||
zip -qur artifacts.zip $dir
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mdns_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: components/mdns/${{ matrix.test.path }}/artifacts.zip
|
||||
@ -58,8 +58,8 @@ jobs:
|
||||
steps:
|
||||
- name: Clear repository
|
||||
run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: mdns_bin_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: components/mdns/${{ matrix.test.path }}/ci/
|
||||
@ -77,7 +77,7 @@ jobs:
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml
|
||||
|
8
.github/workflows/mdns__host-tests.yml
vendored
8
.github/workflows/mdns__host-tests.yml
vendored
@ -11,12 +11,12 @@ jobs:
|
||||
host_test_mdns:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||
name: Host test
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:release-v5.1
|
||||
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
|
||||
@ -40,11 +40,11 @@ jobs:
|
||||
idf_ver: ["latest"]
|
||||
idf_target: ["esp32"]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Install Necessary Libs
|
||||
|
39
.github/workflows/modem__build-host-tests.yml
vendored
39
.github/workflows/modem__build-host-tests.yml
vendored
@ -13,27 +13,29 @@ jobs:
|
||||
name: Build examples
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v4.3", "release-v4.4", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v4.4", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
example: ["pppos_client", "modem_console", "modem_tcp_client", "ap_to_pppos", "simple_cmux_client"]
|
||||
exclude:
|
||||
- idf_ver: "release-v4.3"
|
||||
example: modem_tcp_client
|
||||
- idf_ver: "release-v4.4"
|
||||
example: modem_tcp_client
|
||||
include:
|
||||
- idf_ver: "release-v4.3"
|
||||
skip_config: usb
|
||||
- idf_ver: "release-v5.0"
|
||||
example: "simple_cmux_client"
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
- name: Check out code (v3) # @v4 failed due to Node 20's requirement, incompatible with older IDF versions
|
||||
if: matrix.idf_ver != 'latest' && matrix.idf_ver < 'release-v5.0'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: protocols
|
||||
- name: Check out code (v4)
|
||||
if: matrix.idf_ver == 'latest' || matrix.idf_ver >= 'release-v5.0'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: protocols
|
||||
- if: ${{ matrix.skip_config }}
|
||||
run: rm -f $GITHUB_WORKSPACE/protocols/components/esp_modem/examples/${{ matrix.example }}/sdkconfig.ci.${{ matrix.skip_config }}*
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }}
|
||||
@ -51,14 +53,14 @@ jobs:
|
||||
name: Build tests
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "latest"]
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
|
||||
test: ["target", "target_ota", "target_iperf"]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: protocols
|
||||
- name: Build ${{ matrix.test }} with IDF-${{ matrix.idf_ver }}
|
||||
@ -76,10 +78,25 @@ jobs:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
|
||||
uses: "./.github/workflows/run-host-tests.yml"
|
||||
with:
|
||||
idf_version: "release-v4.3"
|
||||
idf_version: "latest"
|
||||
app_name: "host_modem_test"
|
||||
app_path: "esp-protocols/components/esp_modem/test/host_test"
|
||||
component_path: "esp-protocols/components/esp_modem"
|
||||
upload_artifacts: true
|
||||
run_executable: true
|
||||
run_coverage: true
|
||||
pre_run_script: "esp-protocols/components/esp_modem/test/host_test/env.sh"
|
||||
publish_unit_test_result: true
|
||||
|
||||
build_linux_example:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'modem') || github.event_name == 'push'
|
||||
uses: "./.github/workflows/run-host-tests.yml"
|
||||
with:
|
||||
idf_version: "latest"
|
||||
app_name: "linux_modem"
|
||||
app_path: "esp-protocols/components/esp_modem/examples/linux_modem"
|
||||
component_path: "esp-protocols/components/esp_modem"
|
||||
upload_artifacts: true
|
||||
run_executable: false
|
||||
run_coverage: false
|
||||
pre_run_script: "esp-protocols/components/esp_modem/test/host_test/env.sh"
|
||||
|
5
.github/workflows/modem__target-test.yml
vendored
5
.github/workflows/modem__target-test.yml
vendored
@ -20,13 +20,13 @@ jobs:
|
||||
- idf_ver: "latest"
|
||||
idf_target: "esp32s2"
|
||||
test: { app: usb_a7670_s2, path: examples/pppos_client }
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/esp_modem/${{ matrix.test.path }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build esp-modem target tests with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
@ -80,4 +80,5 @@ jobs:
|
||||
- name: Run Example Test on target
|
||||
working-directory: ${{ env.TEST_DIR }}
|
||||
run: |
|
||||
python -m pip install -r $GITHUB_WORKSPACE/ci/requirements.txt
|
||||
python -m pytest --log-cli-level DEBUG --target=${{ matrix.idf_target }}
|
||||
|
8
.github/workflows/mqtt_cxx__build.yml
vendored
8
.github/workflows/mqtt_cxx__build.yml
vendored
@ -13,20 +13,20 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.0"]
|
||||
idf_ver: ["latest", "release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: mqtt-basic, path: "components/esp_mqtt_cxx/examples" }]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
shell: bash
|
||||
working-directory: ${{matrix.test.path}}
|
||||
run: |
|
||||
${IDF_PATH}/install.sh --enable-pytest
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ../../../ci/build_apps.py ./${{ matrix.test.app }} --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app
|
||||
|
4
.github/workflows/pre_commit_check.yml
vendored
4
.github/workflows/pre_commit_check.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
fetch-depth: 20
|
||||
@ -26,7 +26,7 @@ jobs:
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: v3.7
|
||||
python-version: v3.8
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
|
6
.github/workflows/publish-docs-component.yml
vendored
6
.github/workflows/publish-docs-component.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
if: github.repository == 'espressif/esp-protocols'
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
@ -92,11 +92,13 @@ jobs:
|
||||
components/esp_modem;
|
||||
components/esp_mqtt_cxx;
|
||||
components/esp_websocket_client;
|
||||
components/eppp_link;
|
||||
components/mdns;
|
||||
components/console_simple_init;
|
||||
components/console_cmd_ping;
|
||||
components/console_cmd_ifconfig;
|
||||
components/console_cmd_wifi;
|
||||
components/console_cmd_iperf;
|
||||
components/esp_wifi_remote;
|
||||
components/mbedtls_cxx;
|
||||
namespace: "espressif"
|
||||
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
|
||||
|
30
.github/workflows/run-host-tests.yml
vendored
30
.github/workflows/run-host-tests.yml
vendored
@ -18,6 +18,12 @@ on:
|
||||
upload_artifacts:
|
||||
type: boolean
|
||||
required: true
|
||||
run_executable:
|
||||
type: boolean
|
||||
required: true
|
||||
run_coverage:
|
||||
type: boolean
|
||||
required: true
|
||||
pre_run_script:
|
||||
type: string
|
||||
required: false
|
||||
@ -28,14 +34,14 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
name: Build App
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
checks: write
|
||||
contents: write
|
||||
container: espressif/idf:${{inputs.idf_version}}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: esp-protocols
|
||||
- name: Build ${{ inputs.app_name }} with IDF-${{ inputs.idf_version }}
|
||||
@ -51,7 +57,11 @@ jobs:
|
||||
# The sdkconfig.ci.linux specifies Linux as the build target with apropriate settings.
|
||||
cp sdkconfig.ci.linux sdkconfig.defaults
|
||||
idf.py build
|
||||
./build/${{inputs.app_name}}.elf -r junit -o junit.xml
|
||||
if [ "${{ inputs.run_executable}}" == "false" ]; then
|
||||
echo "Executeable wasn't run"
|
||||
exit 0
|
||||
fi
|
||||
./build/${{inputs.app_name}}.elf
|
||||
- name: Publish Unit Test Result
|
||||
uses: EnricoMi/publish-unit-test-result-action@v2
|
||||
if: ${{ inputs.publish_unit_test_result }}
|
||||
@ -59,6 +69,7 @@ jobs:
|
||||
files: ${{inputs.component_path}}/**/*junit.xml
|
||||
- name: Build with Coverage Enabled
|
||||
shell: bash
|
||||
if: ${{ inputs.run_coverage }}
|
||||
run: |
|
||||
component=$(basename ${{ inputs.component_path }})
|
||||
if [ -f "${{ inputs.pre_run_script }}" ]; then
|
||||
@ -74,9 +85,12 @@ jobs:
|
||||
./build/${{inputs.app_name}}.elf
|
||||
- name: Run Coverage
|
||||
shell: bash
|
||||
if: ${{ inputs.run_coverage }}
|
||||
run: |
|
||||
apt-get update && apt-get install -y python3-pip rsync
|
||||
python -m pip install gcovr
|
||||
apt-get update && apt-get install -y rsync
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python3 -m pip install gcovr
|
||||
cd $GITHUB_WORKSPACE/${{inputs.component_path}}
|
||||
component=$(basename ${{ inputs.component_path }})
|
||||
gcov `find . -name "$component*gcda"`
|
||||
@ -86,6 +100,7 @@ jobs:
|
||||
cp index.html ${{inputs.app_name}}_coverage_report
|
||||
cp -rf ${{inputs.app_name}}_coverage_report ${{inputs.app_name}}_coverage.xml $GITHUB_WORKSPACE
|
||||
- name: Code Coverage Summary Report
|
||||
if: ${{ inputs.run_coverage }}
|
||||
uses: irongut/CodeCoverageSummary@v1.3.0
|
||||
with:
|
||||
filename: esp-protocols/**/${{inputs.app_name}}_coverage.xml
|
||||
@ -99,9 +114,10 @@ jobs:
|
||||
thresholds: '60 80'
|
||||
- name: Write to Job Summary
|
||||
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY
|
||||
if: ${{ inputs.run_coverage }}
|
||||
- name: Upload files to artifacts for run-target job
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{inputs.upload_artifacts}}
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ inputs.run_coverage }}
|
||||
with:
|
||||
name: ${{inputs.app_name}}_coverage_report
|
||||
path: |
|
||||
|
30
.github/workflows/tls_cxx__build.yml
vendored
Normal file
30
.github/workflows/tls_cxx__build.yml
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
name: "mbedtls-cxx: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_tls_cxx:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'tls_cxx') || github.event_name == 'push'
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest", "release-v5.3", "release-v5.2", "release-v5.1"]
|
||||
test: [ { app: client, path: "examples/tls_client" }, { app: udp, path: "examples/udp_mutual_auth" }, { app: test, path: "tests/uart_mutual_auth" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/mbedtls_cxx/${{ matrix.test.path }} -vv --preserve-all
|
@ -17,4 +17,6 @@ jobs:
|
||||
app_name: "websocket"
|
||||
app_path: "esp-protocols/components/esp_websocket_client/examples/linux"
|
||||
component_path: "esp-protocols/components/esp_websocket_client"
|
||||
run_executable: true
|
||||
upload_artifacts: true
|
||||
run_coverage: true
|
||||
|
@ -13,15 +13,15 @@ jobs:
|
||||
name: Build
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "latest"]
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
|
||||
test: [ { app: example, path: "examples/target" }, { app: unit_test, path: "test" } ]
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
env:
|
||||
TEST_DIR: components/esp_websocket_client/${{ matrix.test.path }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }}
|
||||
@ -35,7 +35,7 @@ jobs:
|
||||
$GITHUB_WORKSPACE/ci/clean_build_artifacts.sh `pwd`/$dir
|
||||
zip -qur artifacts.zip $dir
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: websocket_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/artifacts.zip
|
||||
@ -51,7 +51,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "latest"]
|
||||
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"]
|
||||
idf_target: ["esp32"]
|
||||
test: [ { app: example, path: "examples/target" }, { app: unit_test, path: "test" } ]
|
||||
runs-on:
|
||||
@ -60,8 +60,8 @@ jobs:
|
||||
env:
|
||||
TEST_DIR: components/esp_websocket_client/${{ matrix.test.path }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: websocket_bin_esp32_${{ matrix.idf_ver }}_${{ matrix.test.app }}
|
||||
path: ${{ env.TEST_DIR }}/ci/
|
||||
@ -79,7 +79,7 @@ jobs:
|
||||
mv $dir build
|
||||
python -m pytest --log-cli-level DEBUG --junit-xml=./results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=${{ matrix.idf_target }}
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: results_${{ matrix.test.app }}_${{ matrix.idf_target }}_${{ matrix.idf_ver }}.xml
|
||||
|
77
.github/workflows/wifi_remote__build.yml
vendored
Normal file
77
.github/workflows/wifi_remote__build.yml
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
name: "esp_wifi_remote: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
wifi_remote_api_compat:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Check API compatibility of WiFi Remote
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Check that headers are the same as generated
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
cd ./components/esp_wifi_remote/scripts
|
||||
python generate_and_check.py
|
||||
|
||||
build_wifi_remote:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Test
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
test: [ { app: smoke_test, path: "test/smoke_test" }]
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ matrix.idf_ver }}
|
||||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.test.path}} -vv --preserve-all
|
||||
|
||||
build_wifi_remote_example:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'wifi_remote') || github.event_name == 'push'
|
||||
name: Build WiFi Remote Example
|
||||
strategy:
|
||||
matrix:
|
||||
idf_ver: ["latest"]
|
||||
example: [ { app: host, path: "examples/mqtt" }, { app: slave, path: "examples/server" }]
|
||||
include:
|
||||
- idf_ver: "latest"
|
||||
example: { app: slave, path: "examples/server" }
|
||||
warning: "Warning: The smallest app partition is nearly full"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v3
|
||||
- name: Build ${{ matrix.example.app }} with IDF-${{ matrix.idf_ver }}
|
||||
env:
|
||||
EXPECTED_WARNING: ${{ matrix.warning }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
pip install idf-component-manager idf-build-apps --upgrade
|
||||
python ./ci/build_apps.py ./components/esp_wifi_remote/${{matrix.example.path}} -vv --preserve-all
|
@ -48,10 +48,10 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'ci/check_copyright_ignore.txt', '--config', 'ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/igrr/astyle_py.git
|
||||
rev: c0013808882a15a0c0c2c1a9b5c903866c53a653
|
||||
rev: v1.0.5
|
||||
hooks:
|
||||
- id: astyle_py
|
||||
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper']
|
||||
args: ['--style=otbs', '--attach-namespaces', '--attach-classes', '--indent=spaces=4', '--convert-tabs', '--align-pointer=name', '--align-reference=name', '--keep-one-line-statements', '--pad-header', '--pad-oper', '--exclude-list=ci/ignore_astyle.txt']
|
||||
- repo: https://github.com/commitizen-tools/commitizen
|
||||
rev: v2.42.1
|
||||
hooks:
|
||||
@ -61,8 +61,8 @@ repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: commit message scopes
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples)\)\:)'
|
||||
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote, tls_cxx"
|
||||
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx)\)\:)'
|
||||
language: pygrep
|
||||
args: [--multiline]
|
||||
stages: [commit-msg]
|
||||
|
12
README.md
12
README.md
@ -49,3 +49,15 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf)
|
||||
### console_cmd_wifi
|
||||
|
||||
* Brief introduction [README](components/console_cmd_wifi/README.md)
|
||||
|
||||
### ESP PPP Link (eppp)
|
||||
|
||||
* Brief introduction [README](components/eppp_link/README.md)
|
||||
|
||||
### esp_wifi_remote
|
||||
|
||||
* Brief introduction [README](components/esp_wifi_remote/README.md)
|
||||
|
||||
### mbedtls_cxx
|
||||
|
||||
* Brief introduction [README](components/mbedtls_cxx/README.md)
|
||||
|
@ -83,13 +83,14 @@ def main():
|
||||
changelog += '\n### {}\n\n'.format(sections[section])
|
||||
for it in item:
|
||||
changelog += '- {}\n'.format(it)
|
||||
changelog += '\n'
|
||||
filename = os.path.join(root_path, 'components', component, 'CHANGELOG.md')
|
||||
# Check if the changelog file exists.
|
||||
if not os.path.exists(filename):
|
||||
# File does not exist, create it
|
||||
with open(filename, 'w') as file:
|
||||
file.write('# Changelog\n\n')
|
||||
else:
|
||||
changelog += '\n'
|
||||
# insert the actual changelog to the beginning of the file, just after the title (2nd line)
|
||||
with open(filename, 'r') as orig_changelog:
|
||||
changelog_title = orig_changelog.readline(
|
||||
|
2
ci/ignore_astyle.txt
Normal file
2
ci/ignore_astyle.txt
Normal file
@ -0,0 +1,2 @@
|
||||
# The below file is generated from esp_wifi_types_native.h in IDF, which doesn't follow atyle
|
||||
components/esp_wifi_remote/include/esp_wifi_types_native.h
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_iperf
|
||||
tag_format: console_cmd_iperf-v$version
|
||||
version: 1.0.0
|
||||
version_files:
|
||||
- idf_component.yml
|
@ -1,7 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_iperf-v1.0.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added component with iperf command ([93d14087](https://github.com/espressif/esp-protocols/commit/93d14087))
|
@ -1,4 +0,0 @@
|
||||
idf_component_register(SRCS "console_iperf.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console
|
||||
WHOLE_ARCHIVE)
|
@ -1,52 +0,0 @@
|
||||
# Console command iperf
|
||||
The component provides a console where the 'iperf' command can be executed for any example project.
|
||||
|
||||
## API
|
||||
|
||||
### Steps to enable console in an example code:
|
||||
1. Add this component to your project using ```idf.py add-dependency``` command.
|
||||
2. In the main file of the example, add the following line:
|
||||
```c
|
||||
#include "console_iperf.h"
|
||||
```
|
||||
3. Ensure esp-netif and NVS flash is initialized and default event loop is created in your app_main():
|
||||
```c
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
```
|
||||
4. In your app_main() function, add the following line as the last line:
|
||||
```c
|
||||
ESP_ERROR_CHECK(console_cmd_init()); // Initialize console
|
||||
|
||||
// Register all plugin command added to your project
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
// To register only iperf command skip calling console_cmd_all_register()
|
||||
ESP_ERROR_CHECK(console_cmd_iperf_register());
|
||||
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
|
||||
### Adding a plugin command or component:
|
||||
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.
|
||||
|
||||
For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)
|
||||
|
||||
|
||||
## Suported command:
|
||||
|
||||
### iperf:
|
||||
```
|
||||
iperf [-suVa] [-c <ip>] [-p <port>] [-l <length>] [-i <interval>] [-t <time>] [-b <bandwidth>]
|
||||
Command to measure network performance, through TCP or UDP connections.
|
||||
-c, --client=<ip> run in client mode, connecting to <host>
|
||||
-s, --server run in server mode
|
||||
-u, --udp use UDP rather than TCP
|
||||
-V, --ipv6_domain use IPV6 address rather than IPV4
|
||||
-p, --port=<port> server port to listen on/connect to
|
||||
-l, --len=<length> set read/write buffer size
|
||||
-i, --interval=<interval> seconds between periodic bandwidth reports
|
||||
-t, --time=<time> time in seconds to transmit for (default 10 secs)
|
||||
-b, --bandwidth=<bandwidth> bandwidth to send at in Mbits/sec
|
||||
-a, --abort abort running iperf
|
||||
```
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "console_simple_init.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Registers the iperf command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_iperf_register(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,2 +0,0 @@
|
||||
idf_component_register(SRCS "iperf-basic.c"
|
||||
INCLUDE_DIRS ".")
|
@ -1,6 +0,0 @@
|
||||
dependencies:
|
||||
idf:
|
||||
version: ">=5.0"
|
||||
console_cmd_iperf:
|
||||
version: "*"
|
||||
override_path: '../../../'
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "esp_netif.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_event.h"
|
||||
#include "console_iperf.h"
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Initialize console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_init());
|
||||
|
||||
ESP_ERROR_CHECK(console_cmd_all_register());
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_start());
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
def test_examples_iperf_command(dut):
|
||||
dut.expect('esp>', timeout=30)
|
||||
dut.write('help iperf')
|
||||
dut.expect('esp>', timeout=5)
|
||||
pass
|
@ -1,13 +0,0 @@
|
||||
version: 1.0.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_iperf
|
||||
description: The component provides a console where the 'iperf' command can be executed.
|
||||
dependencies:
|
||||
idf:
|
||||
version: '>=5.0'
|
||||
espressif/console_simple_init:
|
||||
version: '>=1.1.0'
|
||||
override_path: '../console_simple_init'
|
||||
public: true
|
||||
iperf:
|
||||
version: "*"
|
||||
path: '${IDF_PATH}/examples/common_components/iperf'
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(console): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_wifi
|
||||
tag_format: console_cmd_wifi-v$version
|
||||
version: 1.0.1
|
||||
version: 1.1.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added support to join pre-configured network ([bdbf16c1](https://github.com/espressif/esp-protocols/commit/bdbf16c1))
|
||||
|
||||
## [1.0.1](https://github.com/espressif/esp-protocols/commits/console_cmd_wifi-v1.0.1)
|
||||
|
||||
### Features
|
||||
|
@ -1,4 +1,8 @@
|
||||
idf_component_register(SRCS "console_wifi.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_netif console esp_wifi
|
||||
WHOLE_ARCHIVE)
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES lwip
|
||||
PRIV_REQUIRES esp_netif console esp_wifi esp_timer)
|
||||
|
||||
if(CONFIG_WIFI_CMD_AUTO_REGISTRATION)
|
||||
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_wifi_register")
|
||||
endif()
|
||||
|
22
components/console_cmd_wifi/Kconfig.projbuild
Normal file
22
components/console_cmd_wifi/Kconfig.projbuild
Normal file
@ -0,0 +1,22 @@
|
||||
menu "Wifi command Configuration"
|
||||
|
||||
config WIFI_CMD_AUTO_REGISTRATION
|
||||
bool "Enable Console command wifi Auto-registration"
|
||||
default y
|
||||
help
|
||||
Enabling this allows for the autoregistration of the wifi command.
|
||||
|
||||
config WIFI_CMD_NETWORK_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) to connect to.
|
||||
|
||||
config WIFI_CMD_NETWORK_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) to use.
|
||||
Can be left blank if the network has no security set.
|
||||
|
||||
endmenu
|
@ -33,12 +33,16 @@ The component offers a console with a command that enables runtime wifi configur
|
||||
ESP_ERROR_CHECK(console_cmd_start()); // Start console
|
||||
```
|
||||
|
||||
Note: Auto-registration of a specific plugin command can be disabled from menuconfig.
|
||||
|
||||
## Suported command:
|
||||
|
||||
### wifi:
|
||||
* ```wifi help```: Prints the help text for all wifi commands
|
||||
* ```wifi show network```: Scans and displays upto 10 available wifi networks.
|
||||
* ```wifi show sta```: Shows the details of wifi station.
|
||||
* ```wifi sta join <network ssid> <password>```: Station joins the given wifi network.
|
||||
* ```wifi sta join <network ssid>```: Station joins the given unsecured wifi network.
|
||||
* ```wifi sta leave```: Station leaves the wifi network.
|
||||
```
|
||||
wifi help: Prints the help text for all wifi commands
|
||||
wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station.
|
||||
wifi sta join <network ssid> <password>: Station joins the given wifi network.
|
||||
wifi sta join <network ssid>: Station joins the given unsecured wifi network.
|
||||
wifi sta join: Station joins the pre-configured wifi network.
|
||||
wifi sta leave: Station leaves the wifi network.
|
||||
```
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#define DEFAULT_SCAN_LIST_SIZE 10
|
||||
|
||||
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
@ -30,6 +31,7 @@ static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc
|
||||
.name = "console_cmd_wifi",
|
||||
.plugin_regd_fn = &console_cmd_wifi_register
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct wifi_op_t {
|
||||
char *name;
|
||||
@ -55,8 +57,9 @@ static const int CONNECTED_BIT = BIT1;
|
||||
static wifi_op_t cmd_list[] = {
|
||||
{.name = "help", .operation = wifi_help_op, .arg_cnt = 2, .start_index = 1, .help = "wifi help: Prints the help text for all wifi commands"},
|
||||
{.name = "show", .operation = wifi_show_op, .arg_cnt = 3, .start_index = 1, .help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 5, .start_index = 2, .help = "wifi sta join <network ssid> <password>: Station joins the given wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."},
|
||||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta join: Station joins the pre-configured wifi network."},
|
||||
{.name = "leave", .operation = wifi_sta_leave_op, .arg_cnt = 3, .start_index = 2, .help = "wifi sta leave: Station leaves the wifi network."},
|
||||
};
|
||||
|
||||
@ -162,7 +165,6 @@ static esp_err_t wifi_show_op(wifi_op_t *self, int argc, char *argv[])
|
||||
ESP_LOGI(TAG, "Showing Joind AP details:");
|
||||
ESP_LOGI(TAG, "*************************");
|
||||
ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);
|
||||
ESP_LOGI(TAG, "Password: %s", wifi_config.sta.password);
|
||||
ESP_LOGI(TAG, "Channel: %d", wifi_config.sta.channel);
|
||||
ESP_LOGI(TAG, "bssid: %02x:%02x:%02x:%02x:%02x:%02x", wifi_config.sta.bssid[0],
|
||||
wifi_config.sta.bssid[1], wifi_config.sta.bssid[2], wifi_config.sta.bssid[3],
|
||||
@ -184,7 +186,13 @@ static esp_err_t wifi_sta_join_op(wifi_op_t *self, int argc, char *argv[])
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
|
||||
if (self->arg_cnt == 3) {
|
||||
strlcpy((char *) wifi_config.sta.ssid, CONFIG_WIFI_CMD_NETWORK_SSID, sizeof(wifi_config.sta.ssid));
|
||||
strlcpy((char *) wifi_config.sta.password, CONFIG_WIFI_CMD_NETWORK_PASSWORD, sizeof(wifi_config.sta.password));
|
||||
} else {
|
||||
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid));
|
||||
}
|
||||
|
||||
if (self->arg_cnt == 5) {
|
||||
strlcpy((char *) wifi_config.sta.password, argv[self->start_index + 2], sizeof(wifi_config.sta.password));
|
||||
}
|
||||
@ -260,7 +268,7 @@ static esp_err_t do_cmd_wifi(int argc, char **argv)
|
||||
*/
|
||||
esp_err_t console_cmd_wifi_register(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_console_cmd_t command = {
|
||||
.command = "wifi",
|
||||
.help = "Command for wifi configuration and monitoring\n For more info run 'wifi help'",
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 1.0.1
|
||||
version: 1.1.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/console_cmd_wifi
|
||||
description: The component offers a console that enables runtime wifi configuration and monitoring.
|
||||
dependencies:
|
||||
|
8
components/eppp_link/.cz.yaml
Normal file
8
components/eppp_link/.cz.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(eppp): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py eppp_link
|
||||
tag_format: eppp-v$version
|
||||
version: 0.2.0
|
||||
version_files:
|
||||
- idf_component.yml
|
39
components/eppp_link/CHANGELOG.md
Normal file
39
components/eppp_link/CHANGELOG.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
## [0.2.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.2.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for SDIO transport ([085dd790](https://github.com/espressif/esp-protocols/commit/085dd790))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed strict prototype API decl issue in SDIO ([eb09e426](https://github.com/espressif/esp-protocols/commit/eb09e426))
|
||||
- Fix SIDO host to check/clear interrupts atomically ([402176c9](https://github.com/espressif/esp-protocols/commit/402176c9))
|
||||
|
||||
## [0.1.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.1)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Make some common netif options configurable ([7829e8f](https://github.com/espressif/esp-protocols/commit/7829e8f))
|
||||
|
||||
## [0.1.0](https://github.com/espressif/esp-protocols/commits/eppp-v0.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added CI job to build examples and tests ([7eefcf0](https://github.com/espressif/esp-protocols/commit/7eefcf0))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed to select PPP LWIP opts which are OFF by default ([16be2f9](https://github.com/espressif/esp-protocols/commit/16be2f9))
|
||||
- Example to use iperf component from the registry ([bd6b66d](https://github.com/espressif/esp-protocols/commit/bd6b66d))
|
||||
- Fixed defalt config designated init issue in C++ ([8bd4712](https://github.com/espressif/esp-protocols/commit/8bd4712))
|
||||
|
||||
## [0.0.1](https://github.com/espressif/esp-protocols/commits/eppp-v0.0.1)
|
||||
|
||||
### Features
|
||||
|
||||
- Added CI job to build examples and tests ([8686977](https://github.com/espressif/esp-protocols/commit/8686977))
|
||||
- Added support for SPI transport ([18f8452](https://github.com/espressif/esp-protocols/commit/18f8452))
|
||||
- Added support for UART transport ([ad27414](https://github.com/espressif/esp-protocols/commit/ad27414))
|
||||
- Introduced ESP-PPP-Link component ([a761039](https://github.com/espressif/esp-protocols/commit/a761039))
|
3
components/eppp_link/CMakeLists.txt
Normal file
3
components/eppp_link/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS eppp_link.c eppp_sdio_slave.c eppp_sdio_host.c
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES esp_netif esp_driver_spi esp_driver_gpio esp_timer driver)
|
70
components/eppp_link/Kconfig
Normal file
70
components/eppp_link/Kconfig
Normal file
@ -0,0 +1,70 @@
|
||||
menu "eppp_link"
|
||||
|
||||
config EPPP_LINK_USES_LWIP
|
||||
bool
|
||||
default "y"
|
||||
select LWIP_PPP_SUPPORT
|
||||
select LWIP_PPP_SERVER_SUPPORT
|
||||
|
||||
choice EPPP_LINK_DEVICE
|
||||
prompt "Choose PPP device"
|
||||
default EPPP_LINK_DEVICE_UART
|
||||
help
|
||||
Select which peripheral to use for PPP link
|
||||
|
||||
config EPPP_LINK_DEVICE_UART
|
||||
bool "UART"
|
||||
help
|
||||
Use UART.
|
||||
|
||||
config EPPP_LINK_DEVICE_SPI
|
||||
bool "SPI"
|
||||
help
|
||||
Use SPI.
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO
|
||||
bool "SDIO"
|
||||
depends on SOC_SDMMC_HOST_SUPPORTED || SOC_SDIO_SLAVE_SUPPORTED
|
||||
help
|
||||
Use SDIO.
|
||||
|
||||
endchoice
|
||||
|
||||
config EPPP_LINK_CONN_MAX_RETRY
|
||||
int "Maximum retry"
|
||||
default 6
|
||||
help
|
||||
Set the Maximum retry to infinitely avoid reconnecting
|
||||
This is used only with the simplified API (eppp_connect()
|
||||
and eppp_listen())
|
||||
|
||||
config EPPP_LINK_PACKET_QUEUE_SIZE
|
||||
int "Packet queue size"
|
||||
default 64
|
||||
depends on EPPP_LINK_DEVICE_SPI
|
||||
help
|
||||
Size of the Tx packet queue.
|
||||
You can decrease the number for slower bit rates.
|
||||
|
||||
choice EPPP_LINK_SDIO_ROLE
|
||||
prompt "Choose SDIO host or slave"
|
||||
depends on EPPP_LINK_DEVICE_SDIO
|
||||
default EPPP_LINK_DEVICE_SDIO_HOST if SOC_SDMMC_HOST_SUPPORTED
|
||||
help
|
||||
Select which either SDIO host or slave
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO_HOST
|
||||
bool "Host"
|
||||
depends on SOC_SDMMC_HOST_SUPPORTED
|
||||
help
|
||||
Use SDIO host.
|
||||
|
||||
config EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||
bool "SLAVE"
|
||||
depends on SOC_SDIO_SLAVE_SUPPORTED
|
||||
help
|
||||
Use SDIO slave.
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
@ -1,3 +1,4 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
57
components/eppp_link/README.md
Normal file
57
components/eppp_link/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# ESP PPP Link component (eppp_link)
|
||||
|
||||
The component provides a general purpose connectivity engine between two microcontrollers, one acting as PPP server (slave), the other one as PPP client (host).
|
||||
This component could be used for extending network using physical serial connection. Applications could vary from providing PRC engine for multiprocessor solutions to serial connection to POSIX machine. This uses a standard PPP protocol to negotiate IP addresses and networking, so standard PPP toolset could be used, e.g. a `pppd` service on linux. Typical application is a WiFi connectivity provider for chips that do not have WiFi
|
||||
|
||||
## Typical application
|
||||
|
||||
Using this component we can construct a WiFi connectivity gateway on PPP channel. The below diagram depicts an application where
|
||||
PPP server is running on a WiFi capable chip with NAPT module translating packets between WiFi and PPPoS interface.
|
||||
We usually call this node a SLAVE microcontroller. The "HOST" microcontroller runs PPP client and connects only to the serial line,
|
||||
brings in the WiFi connectivity from the "SLAVE" microcontroller.
|
||||
|
||||
```
|
||||
SLAVE micro HOST micro
|
||||
\|/ +----------------+ +----------------+
|
||||
| | | serial line | |
|
||||
+---+ WiFi NAT PPPoS |=== UART / SPI / SDIO =====| PPPoS client |
|
||||
| (server)| | |
|
||||
+----------------+ +----------------+
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Client
|
||||
|
||||
* `eppp_connect()` -- Simplified API. Provides the initialization, starts the task and blocks until we're connected
|
||||
|
||||
### Server
|
||||
|
||||
* `eppp_listen()` -- Simplified API. Provides the initialization, starts the task and blocks until the client connects
|
||||
|
||||
### Manual actions
|
||||
|
||||
* `eppp_init()` -- Initializes one endpoint (client/server).
|
||||
* `eppp_deinit()` -- Destroys the endpoint
|
||||
* `eppp_netif_start()` -- Starts the network, could be called after startup or whenever a connection is lost
|
||||
* `eppp_netif_stop()` -- Stops the network
|
||||
* `eppp_perform()` -- Perform one iteration of the PPP task (need to be called regularly in task-less configuration)
|
||||
|
||||
## Throughput
|
||||
|
||||
Tested with WiFi-NAPT example
|
||||
|
||||
### UART @ 3Mbauds
|
||||
|
||||
* TCP - 2Mbits/s
|
||||
* UDP - 2Mbits/s
|
||||
|
||||
### SPI @ 16MHz
|
||||
|
||||
* TCP - 5Mbits/s
|
||||
* UDP - 8Mbits/s
|
||||
|
||||
### SDIO
|
||||
|
||||
* TCP - 9Mbits/s
|
||||
* UDP - 11Mbits/s
|
887
components/eppp_link/eppp_link.c
Normal file
887
components/eppp_link/eppp_link.c
Normal file
@ -0,0 +1,887 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif_ppp.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_serial_slave_link/essl_sdio.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/spi_slave.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_rom_crc.h"
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
#include "driver/uart.h"
|
||||
#endif
|
||||
|
||||
static const int GOT_IPV4 = BIT0;
|
||||
static const int CONNECTION_FAILED = BIT1;
|
||||
#define CONNECT_BITS (GOT_IPV4|CONNECTION_FAILED)
|
||||
|
||||
static EventGroupHandle_t s_event_group = NULL;
|
||||
static const char *TAG = "eppp_link";
|
||||
static int s_retry_num = 0;
|
||||
static int s_eppp_netif_count = 0; // used as a suffix for the netif key
|
||||
|
||||
|
||||
struct packet {
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
#define MAX_PAYLOAD 1500
|
||||
#define MIN_TRIGGER_US 20
|
||||
#define SPI_HEADER_MAGIC 0x1234
|
||||
|
||||
static void timer_callback(void *arg);
|
||||
|
||||
struct header {
|
||||
uint16_t magic;
|
||||
uint16_t size;
|
||||
uint16_t next_size;
|
||||
uint16_t check;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum blocked_status {
|
||||
NONE,
|
||||
MASTER_BLOCKED,
|
||||
MASTER_WANTS_READ,
|
||||
SLAVE_BLOCKED,
|
||||
SLAVE_WANTS_WRITE,
|
||||
};
|
||||
|
||||
#endif // CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
|
||||
struct eppp_handle {
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
QueueHandle_t out_queue;
|
||||
QueueHandle_t ready_semaphore;
|
||||
spi_device_handle_t spi_device;
|
||||
spi_host_device_t spi_host;
|
||||
int gpio_intr;
|
||||
uint16_t next_size;
|
||||
uint16_t transaction_size;
|
||||
struct packet outbound;
|
||||
enum blocked_status blocked;
|
||||
uint32_t slave_last_edge;
|
||||
esp_timer_handle_t timer;
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
QueueHandle_t uart_event_queue;
|
||||
uart_port_t uart_port;
|
||||
#endif
|
||||
esp_netif_t *netif;
|
||||
eppp_type_t role;
|
||||
bool stop;
|
||||
bool exited;
|
||||
bool netif_stop;
|
||||
};
|
||||
|
||||
typedef esp_err_t (*transmit_t)(void *h, void *buffer, size_t len);
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len);
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif);
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif);
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len);
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config);
|
||||
esp_err_t eppp_sdio_slave_init(void);
|
||||
void eppp_sdio_slave_deinit(void);
|
||||
void eppp_sdio_host_deinit(void);
|
||||
#else
|
||||
static esp_err_t transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
struct eppp_handle *handle = h;
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
struct packet buf = { };
|
||||
uint8_t *current_buffer = buffer;
|
||||
size_t remaining = len;
|
||||
do { // TODO(IDF-9194): Refactor this loop to allocate only once and perform
|
||||
// fragmentation after receiving from the queue (applicable only if MTU > MAX_PAYLOAD)
|
||||
size_t batch = remaining > MAX_PAYLOAD ? MAX_PAYLOAD : remaining;
|
||||
buf.data = malloc(batch);
|
||||
if (buf.data == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to allocate packet");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
buf.len = batch;
|
||||
remaining -= batch;
|
||||
memcpy(buf.data, current_buffer, batch);
|
||||
current_buffer += batch;
|
||||
BaseType_t ret = xQueueSend(handle->out_queue, &buf, 0);
|
||||
if (ret != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to queue packet to slave!");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
} while (remaining > 0);
|
||||
|
||||
if (handle->role == EPPP_SERVER && handle->blocked == SLAVE_BLOCKED) {
|
||||
uint32_t now = esp_timer_get_time();
|
||||
uint32_t diff = now - handle->slave_last_edge;
|
||||
if (diff < MIN_TRIGGER_US) {
|
||||
esp_rom_delay_us(MIN_TRIGGER_US - diff);
|
||||
}
|
||||
gpio_set_level(handle->gpio_intr, 0);
|
||||
}
|
||||
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_send", buffer, len, ESP_LOG_VERBOSE);
|
||||
uart_write_bytes(handle->uart_port, buffer, len);
|
||||
#endif // DEVICE UART or SPI
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void netif_deinit(esp_netif_t *netif)
|
||||
{
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h == NULL) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
struct packet buf = { };
|
||||
while (xQueueReceive(h->out_queue, &buf, 0) == pdTRUE) {
|
||||
if (buf.len > 0) {
|
||||
free(buf.data);
|
||||
}
|
||||
}
|
||||
vQueueDelete(h->out_queue);
|
||||
if (h->role == EPPP_CLIENT) {
|
||||
vSemaphoreDelete(h->ready_semaphore);
|
||||
}
|
||||
#endif
|
||||
free(h);
|
||||
esp_netif_destroy(netif);
|
||||
if (s_eppp_netif_count > 0) {
|
||||
s_eppp_netif_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_netif_t *netif_init(eppp_type_t role, eppp_config_t *eppp_config)
|
||||
{
|
||||
if (s_eppp_netif_count > 9) { // Limit to max 10 netifs, since we use "EPPPx" as the unique key (where x is 0-9)
|
||||
ESP_LOGE(TAG, "Cannot create more than 10 instances");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the object first
|
||||
struct eppp_handle *h = calloc(1, sizeof(struct eppp_handle));
|
||||
if (!h) {
|
||||
ESP_LOGE(TAG, "Failed to allocate eppp_handle");
|
||||
return NULL;
|
||||
}
|
||||
h->role = role;
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
h->out_queue = xQueueCreate(CONFIG_EPPP_LINK_PACKET_QUEUE_SIZE, sizeof(struct packet));
|
||||
if (!h->out_queue) {
|
||||
ESP_LOGE(TAG, "Failed to create the packet queue");
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
if (role == EPPP_CLIENT) {
|
||||
h->ready_semaphore = xSemaphoreCreateBinary();
|
||||
if (!h->ready_semaphore) {
|
||||
ESP_LOGE(TAG, "Failed to create the packet queue");
|
||||
vQueueDelete(h->out_queue);
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
h->transaction_size = 0;
|
||||
h->outbound.data = NULL;
|
||||
h->outbound.len = 0;
|
||||
if (role == EPPP_SERVER) {
|
||||
esp_timer_create_args_t args = {
|
||||
.callback = &timer_callback,
|
||||
.arg = h,
|
||||
.name = "timer"
|
||||
};
|
||||
if (esp_timer_create(&args, &h->timer) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to create the packet queue");
|
||||
vQueueDelete(h->out_queue);
|
||||
vSemaphoreDelete(h->ready_semaphore);
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
esp_netif_driver_ifconfig_t driver_cfg = {
|
||||
.handle = h,
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
.transmit = role == EPPP_CLIENT ? eppp_sdio_host_tx : eppp_sdio_slave_tx,
|
||||
#else
|
||||
.transmit = transmit,
|
||||
#endif
|
||||
};
|
||||
const esp_netif_driver_ifconfig_t *ppp_driver_cfg = &driver_cfg;
|
||||
|
||||
esp_netif_inherent_config_t base_netif_cfg = ESP_NETIF_INHERENT_DEFAULT_PPP();
|
||||
char if_key[] = "EPPP0"; // netif key needs to be unique
|
||||
if_key[sizeof(if_key) - 2 /* 2 = two chars before the terminator */ ] += s_eppp_netif_count++;
|
||||
base_netif_cfg.if_key = if_key;
|
||||
if (eppp_config->ppp.netif_description) {
|
||||
base_netif_cfg.if_desc = eppp_config->ppp.netif_description;
|
||||
} else {
|
||||
base_netif_cfg.if_desc = role == EPPP_CLIENT ? "pppos_client" : "pppos_server";
|
||||
}
|
||||
if (eppp_config->ppp.netif_prio) {
|
||||
base_netif_cfg.route_prio = eppp_config->ppp.netif_prio;
|
||||
}
|
||||
esp_netif_config_t netif_ppp_config = { .base = &base_netif_cfg,
|
||||
.driver = ppp_driver_cfg,
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_PPP
|
||||
};
|
||||
|
||||
esp_netif_t *netif = esp_netif_new(&netif_ppp_config);
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Failed to create esp_netif");
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
vQueueDelete(h->out_queue);
|
||||
if (h->ready_semaphore) {
|
||||
vSemaphoreDelete(h->ready_semaphore);
|
||||
}
|
||||
#endif
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
return netif;
|
||||
|
||||
}
|
||||
|
||||
esp_err_t eppp_netif_stop(esp_netif_t *netif, int stop_timeout_ms)
|
||||
{
|
||||
esp_netif_action_disconnected(netif, 0, 0, 0);
|
||||
esp_netif_action_stop(netif, 0, 0, 0);
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
vTaskDelay(pdMS_TO_TICKS(stop_timeout_ms) / 100);
|
||||
if (h->netif_stop) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!h->netif_stop) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t eppp_netif_start(esp_netif_t *netif)
|
||||
{
|
||||
esp_netif_action_start(netif, 0, 0, 0);
|
||||
esp_netif_action_connected(netif, 0, 0, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int get_netif_num(esp_netif_t *netif)
|
||||
{
|
||||
if (netif == NULL) {
|
||||
return -1;
|
||||
}
|
||||
const char *ifkey = esp_netif_get_ifkey(netif);
|
||||
if (strstr(ifkey, "EPPP") == NULL) {
|
||||
return -1; // not our netif
|
||||
}
|
||||
int netif_cnt = ifkey[4] - '0';
|
||||
if (netif_cnt < 0 || netif_cnt > 9) {
|
||||
ESP_LOGE(TAG, "Unexpected netif key %s", ifkey);
|
||||
return -1;
|
||||
}
|
||||
return netif_cnt;
|
||||
}
|
||||
|
||||
static void on_ppp_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
esp_netif_t **netif = data;
|
||||
ESP_LOGD(TAG, "PPP status event: %" PRId32, event_id);
|
||||
if (base == NETIF_PPP_STATUS && event_id == NETIF_PPP_ERRORUSER) {
|
||||
ESP_LOGI(TAG, "Disconnected %d", get_netif_num(*netif));
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(*netif);
|
||||
h->netif_stop = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_ip_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)data;
|
||||
esp_netif_t *netif = event->esp_netif;
|
||||
int netif_cnt = get_netif_num(netif);
|
||||
if (netif_cnt < 0) {
|
||||
return;
|
||||
}
|
||||
if (event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s(%s)\" address: " IPSTR, esp_netif_get_desc(netif),
|
||||
esp_netif_get_ifkey(netif), IP2STR(&event->ip_info.ip));
|
||||
xEventGroupSetBits(s_event_group, GOT_IPV4 << (netif_cnt * 2));
|
||||
} else if (event_id == IP_EVENT_PPP_LOST_IP) {
|
||||
ESP_LOGI(TAG, "Disconnected");
|
||||
s_retry_num++;
|
||||
if (s_retry_num > CONFIG_EPPP_LINK_CONN_MAX_RETRY) {
|
||||
ESP_LOGE(TAG, "PPP Connection failed %d times, stop reconnecting.", s_retry_num);
|
||||
xEventGroupSetBits(s_event_group, CONNECTION_FAILED << (netif_cnt * 2));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "PPP Connection failed %d times, try to reconnect.", s_retry_num);
|
||||
eppp_netif_start(netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
|
||||
#define SPI_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||
#define TRANSFER_SIZE SPI_ALIGN((MAX_PAYLOAD + 6))
|
||||
#define NEXT_TRANSACTION_SIZE(a,b) (((a)>(b))?(a):(b)) /* next transaction: whichever is bigger */
|
||||
|
||||
static void IRAM_ATTR timer_callback(void *arg)
|
||||
{
|
||||
struct eppp_handle *h = arg;
|
||||
if (h->blocked == SLAVE_WANTS_WRITE) {
|
||||
gpio_set_level(h->gpio_intr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
||||
{
|
||||
static uint32_t s_last_time;
|
||||
uint32_t now = esp_timer_get_time();
|
||||
uint32_t diff = now - s_last_time;
|
||||
if (diff < MIN_TRIGGER_US) { // debounce
|
||||
return;
|
||||
}
|
||||
s_last_time = now;
|
||||
struct eppp_handle *h = arg;
|
||||
BaseType_t yield = false;
|
||||
|
||||
// Positive edge means SPI slave prepared the data
|
||||
if (gpio_get_level(h->gpio_intr) == 1) {
|
||||
xSemaphoreGiveFromISR(h->ready_semaphore, &yield);
|
||||
if (yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Negative edge (when master blocked) means that slave wants to transmit
|
||||
if (h->blocked == MASTER_BLOCKED) {
|
||||
struct packet buf = { .data = NULL, .len = -1 };
|
||||
xQueueSendFromISR(h->out_queue, &buf, &yield);
|
||||
if (yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t deinit_master(esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
ESP_RETURN_ON_ERROR(spi_bus_remove_device(h->spi_device), TAG, "Failed to remove SPI bus");
|
||||
ESP_RETURN_ON_ERROR(spi_bus_free(h->spi_host), TAG, "Failed to free SPI bus");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t init_master(struct eppp_config_spi_s *config, esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
h->spi_host = config->host;
|
||||
h->gpio_intr = config->intr;
|
||||
spi_bus_config_t bus_cfg = {};
|
||||
bus_cfg.mosi_io_num = config->mosi;
|
||||
bus_cfg.miso_io_num = config->miso;
|
||||
bus_cfg.sclk_io_num = config->sclk;
|
||||
bus_cfg.quadwp_io_num = -1;
|
||||
bus_cfg.quadhd_io_num = -1;
|
||||
bus_cfg.max_transfer_sz = TRANSFER_SIZE;
|
||||
bus_cfg.flags = 0;
|
||||
bus_cfg.intr_flags = 0;
|
||||
|
||||
// TODO: Init and deinit SPI bus separately (per Kconfig?)
|
||||
if (spi_bus_initialize(config->host, &bus_cfg, SPI_DMA_CH_AUTO) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
spi_device_interface_config_t dev_cfg = {};
|
||||
dev_cfg.clock_speed_hz = config->freq;
|
||||
dev_cfg.mode = 0;
|
||||
dev_cfg.spics_io_num = config->cs;
|
||||
dev_cfg.cs_ena_pretrans = config->cs_ena_pretrans;
|
||||
dev_cfg.cs_ena_posttrans = config->cs_ena_posttrans;
|
||||
dev_cfg.duty_cycle_pos = 128;
|
||||
dev_cfg.input_delay_ns = config->input_delay_ns;
|
||||
dev_cfg.pre_cb = NULL;
|
||||
dev_cfg.post_cb = NULL;
|
||||
dev_cfg.queue_size = 3;
|
||||
|
||||
if (spi_bus_add_device(config->host, &dev_cfg, &h->spi_device) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
//GPIO config for the handshake line.
|
||||
gpio_config_t io_conf = {
|
||||
.intr_type = GPIO_INTR_ANYEDGE,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = 1,
|
||||
.pin_bit_mask = BIT64(config->intr),
|
||||
};
|
||||
|
||||
gpio_config(&io_conf);
|
||||
gpio_install_isr_service(0);
|
||||
gpio_set_intr_type(config->intr, GPIO_INTR_ANYEDGE);
|
||||
gpio_isr_handler_add(config->intr, gpio_isr_handler, esp_netif_get_io_driver(netif));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void post_setup(spi_slave_transaction_t *trans)
|
||||
{
|
||||
struct eppp_handle *h = trans->user;
|
||||
h->slave_last_edge = esp_timer_get_time();
|
||||
gpio_set_level(h->gpio_intr, 1);
|
||||
if (h->transaction_size == 0) { // If no transaction planned:
|
||||
if (h->outbound.len == 0) { // we're blocked if we don't have any data
|
||||
h->blocked = SLAVE_BLOCKED;
|
||||
} else {
|
||||
h->blocked = SLAVE_WANTS_WRITE; // we notify the master that we want to write
|
||||
esp_timer_start_once(h->timer, MIN_TRIGGER_US);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void post_trans(spi_slave_transaction_t *trans)
|
||||
{
|
||||
struct eppp_handle *h = trans->user;
|
||||
h->blocked = NONE;
|
||||
gpio_set_level(h->gpio_intr, 0);
|
||||
}
|
||||
|
||||
static esp_err_t deinit_slave(esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
ESP_RETURN_ON_ERROR(spi_slave_free(h->spi_host), TAG, "Failed to free SPI slave host");
|
||||
ESP_RETURN_ON_ERROR(spi_bus_remove_device(h->spi_device), TAG, "Failed to remove SPI device");
|
||||
ESP_RETURN_ON_ERROR(spi_bus_free(h->spi_host), TAG, "Failed to free SPI bus");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t init_slave(struct eppp_config_spi_s *config, esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
h->spi_host = config->host;
|
||||
h->gpio_intr = config->intr;
|
||||
spi_bus_config_t bus_cfg = {};
|
||||
bus_cfg.mosi_io_num = config->mosi;
|
||||
bus_cfg.miso_io_num = config->miso;
|
||||
bus_cfg.sclk_io_num = config->sclk;
|
||||
bus_cfg.quadwp_io_num = -1;
|
||||
bus_cfg.quadhd_io_num = -1;
|
||||
bus_cfg.flags = 0;
|
||||
bus_cfg.intr_flags = 0;
|
||||
|
||||
//Configuration for the SPI slave interface
|
||||
spi_slave_interface_config_t slvcfg = {
|
||||
.mode = 0,
|
||||
.spics_io_num = config->cs,
|
||||
.queue_size = 3,
|
||||
.flags = 0,
|
||||
.post_setup_cb = post_setup,
|
||||
.post_trans_cb = post_trans,
|
||||
};
|
||||
|
||||
//Configuration for the handshake line
|
||||
gpio_config_t io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT64(config->intr),
|
||||
};
|
||||
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_pull_mode(config->mosi, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(config->sclk, GPIO_PULLUP_ONLY);
|
||||
gpio_set_pull_mode(config->cs, GPIO_PULLUP_ONLY);
|
||||
|
||||
//Initialize SPI slave interface
|
||||
if (spi_slave_initialize(config->host, &bus_cfg, &slvcfg, SPI_DMA_CH_AUTO) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
typedef esp_err_t (*perform_transaction_t)(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer);
|
||||
|
||||
static esp_err_t perform_transaction_master(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer)
|
||||
{
|
||||
spi_transaction_t t = {};
|
||||
t.length = len * 8;
|
||||
t.tx_buffer = tx_buffer;
|
||||
t.rx_buffer = rx_buffer;
|
||||
return spi_device_transmit(h->spi_device, &t);
|
||||
}
|
||||
|
||||
static esp_err_t perform_transaction_slave(struct eppp_handle *h, size_t len, const void *tx_buffer, void *rx_buffer)
|
||||
{
|
||||
spi_slave_transaction_t t = {};
|
||||
t.user = h;
|
||||
t.length = len * 8;
|
||||
t.tx_buffer = tx_buffer;
|
||||
t.rx_buffer = rx_buffer;
|
||||
return spi_slave_transmit(h->spi_host, &t, portMAX_DELAY);
|
||||
}
|
||||
|
||||
esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
{
|
||||
static WORD_ALIGNED_ATTR uint8_t out_buf[TRANSFER_SIZE] = {};
|
||||
static WORD_ALIGNED_ATTR uint8_t in_buf[TRANSFER_SIZE] = {};
|
||||
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
|
||||
// Perform transaction for master and slave
|
||||
const perform_transaction_t perform_transaction = h->role == EPPP_CLIENT ? perform_transaction_master : perform_transaction_slave;
|
||||
|
||||
if (h->stop) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
BaseType_t tx_queue_stat;
|
||||
bool allow_test_tx = false;
|
||||
uint16_t next_tx_size = 0;
|
||||
if (h->role == EPPP_CLIENT) {
|
||||
// SPI MASTER only code
|
||||
if (xSemaphoreTake(h->ready_semaphore, pdMS_TO_TICKS(1000)) != pdTRUE) {
|
||||
// slave might not be ready, but maybe we just missed an interrupt
|
||||
allow_test_tx = true;
|
||||
}
|
||||
if (h->outbound.len == 0 && h->transaction_size == 0 && h->blocked == NONE) {
|
||||
h->blocked = MASTER_BLOCKED;
|
||||
xQueueReceive(h->out_queue, &h->outbound, portMAX_DELAY);
|
||||
h->blocked = NONE;
|
||||
if (h->outbound.len == -1) {
|
||||
h->outbound.len = 0;
|
||||
h->blocked = MASTER_WANTS_READ;
|
||||
}
|
||||
} else if (h->blocked == MASTER_WANTS_READ) {
|
||||
h->blocked = NONE;
|
||||
}
|
||||
}
|
||||
struct header *head = (void *)out_buf;
|
||||
if (h->outbound.len <= h->transaction_size && allow_test_tx == false) {
|
||||
// sending outbound
|
||||
head->size = h->outbound.len;
|
||||
if (h->outbound.len > 0) {
|
||||
memcpy(out_buf + sizeof(struct header), h->outbound.data, h->outbound.len);
|
||||
free(h->outbound.data);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, out_buf + sizeof(struct header), head->size, ESP_LOG_VERBOSE);
|
||||
h->outbound.data = NULL;
|
||||
h->outbound.len = 0;
|
||||
}
|
||||
do {
|
||||
tx_queue_stat = xQueueReceive(h->out_queue, &h->outbound, 0);
|
||||
} while (tx_queue_stat == pdTRUE && h->outbound.len == -1);
|
||||
if (h->outbound.len == -1) { // used as a signal only, no actual data
|
||||
h->outbound.len = 0;
|
||||
}
|
||||
} else {
|
||||
// outbound is bigger, need to transmit in another transaction (keep this empty)
|
||||
head->size = 0;
|
||||
}
|
||||
next_tx_size = head->next_size = h->outbound.len;
|
||||
head->magic = SPI_HEADER_MAGIC;
|
||||
head->check = esp_rom_crc16_le(0, out_buf, sizeof(struct header) - sizeof(uint16_t));
|
||||
esp_err_t ret = perform_transaction(h, sizeof(struct header) + h->transaction_size, out_buf, in_buf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "spi_device_transmit failed");
|
||||
h->transaction_size = 0; // need to start with HEADER only transaction
|
||||
return ESP_FAIL;
|
||||
}
|
||||
head = (void *)in_buf;
|
||||
uint16_t check = esp_rom_crc16_le(0, in_buf, sizeof(struct header) - sizeof(uint16_t));
|
||||
if (check != head->check || head->magic != SPI_HEADER_MAGIC) {
|
||||
h->transaction_size = 0; // need to start with HEADER only transaction
|
||||
if (allow_test_tx) {
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Wrong checksum or magic");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (head->size > 0) {
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, in_buf + sizeof(struct header), head->size, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, in_buf + sizeof(struct header), head->size, NULL);
|
||||
}
|
||||
h->transaction_size = NEXT_TRANSACTION_SIZE(next_tx_size, head->next_size);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
#define BUF_SIZE (1024)
|
||||
|
||||
static esp_err_t init_uart(struct eppp_handle *h, eppp_config_t *config)
|
||||
{
|
||||
h->uart_port = config->uart.port;
|
||||
uart_config_t uart_config = {};
|
||||
uart_config.baud_rate = config->uart.baud;
|
||||
uart_config.data_bits = UART_DATA_8_BITS;
|
||||
uart_config.parity = UART_PARITY_DISABLE;
|
||||
uart_config.stop_bits = UART_STOP_BITS_1;
|
||||
uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
|
||||
uart_config.source_clk = UART_SCLK_DEFAULT;
|
||||
|
||||
ESP_RETURN_ON_ERROR(uart_driver_install(h->uart_port, config->uart.rx_buffer_size, 0, config->uart.queue_size, &h->uart_event_queue, 0), TAG, "Failed to install UART");
|
||||
ESP_RETURN_ON_ERROR(uart_param_config(h->uart_port, &uart_config), TAG, "Failed to set params");
|
||||
ESP_RETURN_ON_ERROR(uart_set_pin(h->uart_port, config->uart.tx_io, config->uart.rx_io, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), TAG, "Failed to set UART pins");
|
||||
ESP_RETURN_ON_ERROR(uart_set_rx_timeout(h->uart_port, 1), TAG, "Failed to set UART Rx timeout");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void deinit_uart(struct eppp_handle *h)
|
||||
{
|
||||
uart_driver_delete(h->uart_port);
|
||||
}
|
||||
|
||||
esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
{
|
||||
static uint8_t buffer[BUF_SIZE] = {};
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
uart_event_t event = {};
|
||||
if (h->stop) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (xQueueReceive(h->uart_event_queue, &event, pdMS_TO_TICKS(100)) != pdTRUE) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (event.type == UART_DATA) {
|
||||
size_t len;
|
||||
uart_get_buffered_data_len(h->uart_port, &len);
|
||||
if (len) {
|
||||
len = uart_read_bytes(h->uart_port, buffer, BUF_SIZE, 0);
|
||||
ESP_LOG_BUFFER_HEXDUMP("ppp_uart_recv", buffer, len, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, buffer, len, NULL);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Received UART event: %d", event.type);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
|
||||
esp_err_t eppp_perform(esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->stop) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
if (h->role == EPPP_SERVER) {
|
||||
return eppp_sdio_slave_rx(netif);
|
||||
} else {
|
||||
return eppp_sdio_host_rx(netif);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_EPPP_LINK_DEVICE_SPI / UART
|
||||
|
||||
static void ppp_task(void *args)
|
||||
{
|
||||
esp_netif_t *netif = args;
|
||||
while (eppp_perform(netif) != ESP_ERR_TIMEOUT) {}
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
h->exited = true;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static bool have_some_eppp_netif(esp_netif_t *netif, void *ctx)
|
||||
{
|
||||
return get_netif_num(netif) > 0;
|
||||
}
|
||||
|
||||
static void remove_handlers(void)
|
||||
{
|
||||
esp_netif_t *netif = esp_netif_find_if(have_some_eppp_netif, NULL);
|
||||
if (netif == NULL) {
|
||||
// if EPPP netif in the system, we cleanup the statics
|
||||
vEventGroupDelete(s_event_group);
|
||||
s_event_group = NULL;
|
||||
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event);
|
||||
esp_event_handler_unregister(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, on_ppp_event);
|
||||
}
|
||||
}
|
||||
|
||||
void eppp_deinit(esp_netif_t *netif)
|
||||
{
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->role == EPPP_CLIENT) {
|
||||
deinit_master(netif);
|
||||
} else {
|
||||
deinit_slave(netif);
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
deinit_uart(esp_netif_get_io_driver(netif));
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (h->role == EPPP_CLIENT) {
|
||||
eppp_sdio_host_deinit();
|
||||
} else {
|
||||
eppp_sdio_slave_deinit();
|
||||
}
|
||||
#endif
|
||||
netif_deinit(netif);
|
||||
}
|
||||
|
||||
esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config)
|
||||
{
|
||||
if (config == NULL || (role != EPPP_SERVER && role != EPPP_CLIENT)) {
|
||||
ESP_LOGE(TAG, "Invalid configuration or role");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_netif_t *netif = netif_init(role, config);
|
||||
if (!netif) {
|
||||
ESP_LOGE(TAG, "Failed to initialize PPP netif");
|
||||
return NULL;
|
||||
}
|
||||
esp_netif_ppp_config_t netif_params;
|
||||
ESP_ERROR_CHECK(esp_netif_ppp_get_params(netif, &netif_params));
|
||||
netif_params.ppp_our_ip4_addr = config->ppp.our_ip4_addr;
|
||||
netif_params.ppp_their_ip4_addr = config->ppp.their_ip4_addr;
|
||||
netif_params.ppp_error_event_enabled = true;
|
||||
ESP_ERROR_CHECK(esp_netif_ppp_set_params(netif, &netif_params));
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
if (role == EPPP_CLIENT) {
|
||||
init_master(&config->spi, netif);
|
||||
} else {
|
||||
init_slave(&config->spi, netif);
|
||||
|
||||
}
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
init_uart(esp_netif_get_io_driver(netif), config);
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
esp_err_t ret;
|
||||
if (role == EPPP_SERVER) {
|
||||
ret = eppp_sdio_slave_init();
|
||||
} else {
|
||||
ret = eppp_sdio_host_init(&config->sdio);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize SDIO %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return netif;
|
||||
}
|
||||
|
||||
esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_timeout_ms)
|
||||
{
|
||||
if (config == NULL || (role != EPPP_SERVER && role != EPPP_CLIENT)) {
|
||||
ESP_LOGE(TAG, "Invalid configuration or role");
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_EPPP_LINK_DEVICE_UART
|
||||
if (config->transport != EPPP_TRANSPORT_UART) {
|
||||
ESP_LOGE(TAG, "Invalid transport: UART device must be enabled in Kconfig");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
if (config->transport != EPPP_TRANSPORT_SPI) {
|
||||
ESP_LOGE(TAG, "Invalid transport: SPI device must be enabled in Kconfig");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
if (config->transport != EPPP_TRANSPORT_SDIO) {
|
||||
ESP_LOGE(TAG, "Invalid transport: SDIO device must be enabled in Kconfig");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (config->task.run_task == false) {
|
||||
ESP_LOGE(TAG, "task.run_task == false is invalid in this API. Please use eppp_init()");
|
||||
return NULL;
|
||||
}
|
||||
if (s_event_group == NULL) {
|
||||
s_event_group = xEventGroupCreate();
|
||||
if (esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_ip_event, NULL) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register IP event handler");
|
||||
remove_handlers();
|
||||
return NULL;
|
||||
}
|
||||
if (esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, on_ppp_event, NULL) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register PPP status handler");
|
||||
remove_handlers();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
esp_netif_t *netif = eppp_init(role, config);
|
||||
if (!netif) {
|
||||
remove_handlers();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eppp_netif_start(netif);
|
||||
|
||||
if (xTaskCreate(ppp_task, "ppp connect", config->task.stack_size, netif, config->task.priority, NULL) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Failed to create a ppp connection task");
|
||||
eppp_deinit(netif);
|
||||
return NULL;
|
||||
}
|
||||
int netif_cnt = get_netif_num(netif);
|
||||
if (netif_cnt < 0) {
|
||||
eppp_close(netif);
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Waiting for IP address %d", netif_cnt);
|
||||
EventBits_t bits = xEventGroupWaitBits(s_event_group, CONNECT_BITS << (netif_cnt * 2), pdFALSE, pdFALSE, pdMS_TO_TICKS(connect_timeout_ms));
|
||||
if (bits & (CONNECTION_FAILED << (netif_cnt * 2))) {
|
||||
ESP_LOGE(TAG, "Connection failed!");
|
||||
eppp_close(netif);
|
||||
return NULL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Connected! %d", netif_cnt);
|
||||
return netif;
|
||||
}
|
||||
|
||||
esp_netif_t *eppp_connect(eppp_config_t *config)
|
||||
{
|
||||
return eppp_open(EPPP_CLIENT, config, portMAX_DELAY);
|
||||
}
|
||||
|
||||
esp_netif_t *eppp_listen(eppp_config_t *config)
|
||||
{
|
||||
return eppp_open(EPPP_SERVER, config, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void eppp_close(esp_netif_t *netif)
|
||||
{
|
||||
struct eppp_handle *h = esp_netif_get_io_driver(netif);
|
||||
if (eppp_netif_stop(netif, 60000) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Network didn't exit cleanly");
|
||||
}
|
||||
h->stop = true;
|
||||
for (int wait = 0; wait < 100; wait++) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
if (h->exited) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!h->exited) {
|
||||
ESP_LOGE(TAG, "Cannot stop ppp_task");
|
||||
}
|
||||
eppp_deinit(netif);
|
||||
remove_handlers();
|
||||
}
|
19
components/eppp_link/eppp_sdio.h
Normal file
19
components/eppp_link/eppp_sdio.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define MAX_SDIO_PAYLOAD 1500
|
||||
#define SDIO_ALIGN(size) (((size) + 3U) & ~(3U))
|
||||
#define SDIO_PAYLOAD SDIO_ALIGN(MAX_SDIO_PAYLOAD)
|
||||
#define PPP_SOF 0x7E
|
||||
|
||||
// Interrupts and registers
|
||||
#define SLAVE_INTR 0
|
||||
#define SLAVE_REG_REQ 0
|
||||
|
||||
// Requests from host to slave
|
||||
#define REQ_RESET 1
|
||||
#define REQ_INIT 2
|
200
components/eppp_link/eppp_sdio_host.c
Normal file
200
components/eppp_link/eppp_sdio_host.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "esp_serial_slave_link/essl_sdio.h"
|
||||
#include "eppp_sdio.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "esp_check.h"
|
||||
#include "eppp_link.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_HOST
|
||||
|
||||
// For blocking operations
|
||||
#define TIMEOUT_MAX UINT32_MAX
|
||||
// Short timeout for sending/receiving ESSL packets
|
||||
#define PACKET_TIMEOUT_MS 50
|
||||
|
||||
static const char *TAG = "eppp_sdio_host";
|
||||
static SemaphoreHandle_t s_essl_mutex = NULL;
|
||||
static essl_handle_t s_essl = NULL;
|
||||
static sdmmc_card_t *s_card = NULL;
|
||||
|
||||
static DRAM_DMA_ALIGNED_ATTR uint8_t send_buffer[SDIO_PAYLOAD];
|
||||
static DMA_ATTR uint8_t rcv_buffer[SDIO_PAYLOAD];
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
if (s_essl == NULL || s_essl_mutex == NULL) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
memcpy(send_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's
|
||||
memset(&send_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
esp_err_t ret = essl_send_packet(s_essl, send_buffer, send_len, PACKET_TIMEOUT_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Slave not ready to receive packet %x", ret);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
ret = ESP_ERR_NO_MEM; // to inform the upper layers
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, send_buffer, send_len, ESP_LOG_VERBOSE);
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t request_slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGI(TAG, "send reset to slave...");
|
||||
ESP_GOTO_ON_ERROR(essl_write_reg(s_essl, SLAVE_REG_REQ, REQ_RESET, NULL, TIMEOUT_MAX), err, TAG, "write-reg failed");
|
||||
ESP_GOTO_ON_ERROR(essl_send_slave_intr(s_essl, BIT(SLAVE_INTR), TIMEOUT_MAX), err, TAG, "send-intr failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(PACKET_TIMEOUT_MS));
|
||||
ESP_GOTO_ON_ERROR(essl_wait_for_ready(s_essl, TIMEOUT_MAX), err, TAG, "wait-for-ready failed");
|
||||
ESP_LOGI(TAG, "slave io ready");
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *eppp_config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_GOTO_ON_ERROR(sdmmc_host_init(), err, TAG, "sdmmc host init failed");
|
||||
|
||||
// configure SDIO interface and slot
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
slot_config.width = eppp_config->width;
|
||||
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
|
||||
slot_config.clk = eppp_config->clk;
|
||||
slot_config.cmd = eppp_config->cmd;
|
||||
slot_config.d0 = eppp_config->d0;
|
||||
slot_config.d1 = eppp_config->d1;
|
||||
slot_config.d2 = eppp_config->d2;
|
||||
slot_config.d3 = eppp_config->d3;
|
||||
#endif
|
||||
|
||||
ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config), err, TAG, "init sdmmc host slot failed");
|
||||
|
||||
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
|
||||
config.flags = SDMMC_HOST_FLAG_4BIT;
|
||||
config.flags |= SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF;
|
||||
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
|
||||
|
||||
s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
|
||||
ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, err, TAG, "card allocation failed");
|
||||
ESP_GOTO_ON_ERROR(sdmmc_card_init(&config, s_card), err, TAG, "sdmmc card init failed");
|
||||
|
||||
essl_sdio_config_t ser_config = {
|
||||
.card = s_card,
|
||||
.recv_buffer_size = SDIO_PAYLOAD,
|
||||
};
|
||||
ESP_GOTO_ON_FALSE(essl_sdio_init_dev(&s_essl, &ser_config) == ESP_OK && s_essl, ESP_FAIL, err, TAG, "essl_sdio_init_dev failed");
|
||||
ESP_GOTO_ON_ERROR(essl_init(s_essl, TIMEOUT_MAX), err, TAG, "essl-init failed");
|
||||
ESP_GOTO_ON_ERROR(request_slave_reset(), err, TAG, "failed to reset the slave");
|
||||
ESP_GOTO_ON_FALSE((s_essl_mutex = xSemaphoreCreateMutex()), ESP_ERR_NO_MEM, err, TAG, "failed to create semaphore");
|
||||
return ret;
|
||||
|
||||
err:
|
||||
essl_sdio_deinit_dev(s_essl);
|
||||
s_essl = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t get_intr(uint32_t *out_raw)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_ERROR(essl_get_intr(s_essl, out_raw, NULL, 0), err, TAG, "essl-get-int failed");
|
||||
ESP_GOTO_ON_ERROR(essl_clear_intr(s_essl, *out_raw, 0), err, TAG, "essl-clear-int failed");
|
||||
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||
{
|
||||
uint32_t intr;
|
||||
esp_err_t err = essl_wait_int(s_essl, TIMEOUT_MAX);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
return ESP_OK;
|
||||
}
|
||||
xSemaphoreTake(s_essl_mutex, portMAX_DELAY);
|
||||
err = get_intr(&intr);
|
||||
if (err == ESP_ERR_TIMEOUT) {
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to check for interrupts %d", err);
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (intr & ESSL_SDIO_DEF_ESP32.new_packet_intr_mask) {
|
||||
esp_err_t ret;
|
||||
do {
|
||||
size_t size_read = SDIO_PAYLOAD;
|
||||
ret = essl_get_packet(s_essl, rcv_buffer, SDIO_PAYLOAD, &size_read, PACKET_TIMEOUT_MS);
|
||||
if (ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "interrupt but no data can be read");
|
||||
break;
|
||||
} else if (ret == ESP_OK) {
|
||||
ESP_LOGD(TAG, "receive data, size: %d", size_read);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_VERBOSE);
|
||||
esp_netif_receive(netif, rcv_buffer, size_read, NULL);
|
||||
break;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "rx packet error: %08X", ret);
|
||||
if (request_slave_reset() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to request slave reset %x", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (ret == ESP_ERR_NOT_FINISHED);
|
||||
}
|
||||
xSemaphoreGive(s_essl_mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void eppp_sdio_host_deinit(void)
|
||||
{
|
||||
essl_sdio_deinit_dev(s_essl);
|
||||
sdmmc_host_deinit();
|
||||
free(s_card);
|
||||
s_card = NULL;
|
||||
s_essl = NULL;
|
||||
}
|
||||
|
||||
#else // SDMMC_HOST NOT-SUPPORTED
|
||||
|
||||
esp_err_t eppp_sdio_host_tx(void *handle, void *buffer, size_t len)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_rx(esp_netif_t *netif)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void eppp_sdio_host_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_host_init(struct eppp_config_sdio_s *config)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
174
components/eppp_link/eppp_sdio_slave.c
Normal file
174
components/eppp_link/eppp_sdio_slave.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "eppp_sdio.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SDIO_SLAVE
|
||||
#define BUFFER_NUM 4
|
||||
#define BUFFER_SIZE SDIO_PAYLOAD
|
||||
static const char *TAG = "eppp_sdio_slave";
|
||||
static DMA_ATTR uint8_t sdio_slave_rx_buffer[BUFFER_NUM][BUFFER_SIZE];
|
||||
static DMA_ATTR uint8_t sdio_slave_tx_buffer[SDIO_PAYLOAD];
|
||||
static int s_slave_request = 0;
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
if (s_slave_request != REQ_INIT) {
|
||||
// silently skip the Tx if the SDIO not fully initialized
|
||||
return ESP_OK;
|
||||
}
|
||||
memcpy(sdio_slave_tx_buffer, buffer, len);
|
||||
size_t send_len = SDIO_ALIGN(len);
|
||||
if (send_len > len) {
|
||||
// pad with SOF's if the size is not 4 bytes aligned
|
||||
memset(&sdio_slave_tx_buffer[len], PPP_SOF, send_len - len);
|
||||
}
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, sdio_slave_tx_buffer, send_len, ESP_LOG_VERBOSE);
|
||||
esp_err_t ret = sdio_slave_transmit(sdio_slave_tx_buffer, send_len);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "sdio slave transmit error, ret : 0x%x", ret);
|
||||
// to inform the upper layers
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t slave_reset(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGI(TAG, "SDIO slave reset");
|
||||
sdio_slave_stop();
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_reset(), err, TAG, "slave reset failed");
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_start(), err, TAG, "slave start failed");
|
||||
|
||||
while (1) {
|
||||
sdio_slave_buf_handle_t handle;
|
||||
ret = sdio_slave_send_get_finished(&handle, 0);
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "slave-get-finished failed");
|
||||
ESP_GOTO_ON_ERROR(sdio_slave_recv_load_buf(handle), err, TAG, "slave-load-buf failed");
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||
{
|
||||
if (s_slave_request == REQ_RESET) {
|
||||
ESP_LOGD(TAG, "request: %x", s_slave_request);
|
||||
slave_reset();
|
||||
s_slave_request = REQ_INIT;
|
||||
}
|
||||
sdio_slave_buf_handle_t handle;
|
||||
size_t length;
|
||||
uint8_t *ptr;
|
||||
esp_err_t ret = sdio_slave_recv_packet(&handle, pdMS_TO_TICKS(1000));
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||
again:
|
||||
ptr = sdio_slave_recv_get_buf(handle, &length);
|
||||
esp_netif_receive(netif, ptr, length, NULL);
|
||||
if (sdio_slave_recv_load_buf(handle) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to recycle packet buffer");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (ret == ESP_ERR_NOT_FINISHED) {
|
||||
ret = sdio_slave_recv_packet(&handle, 0);
|
||||
if (ret == ESP_ERR_NOT_FINISHED || ret == ESP_OK) {
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, length, ESP_LOG_VERBOSE);
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "Error when receiving packet %d", ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
static void event_cb(uint8_t pos)
|
||||
{
|
||||
ESP_EARLY_LOGI(TAG, "SDIO event: %d", pos);
|
||||
if (pos == SLAVE_INTR) {
|
||||
s_slave_request = sdio_slave_read_reg(SLAVE_REG_REQ);
|
||||
sdio_slave_write_reg(SLAVE_REG_REQ, 0);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_init(void)
|
||||
{
|
||||
sdio_slave_config_t config = {
|
||||
.sending_mode = SDIO_SLAVE_SEND_PACKET,
|
||||
.send_queue_size = BUFFER_NUM,
|
||||
.recv_buffer_size = BUFFER_SIZE,
|
||||
.event_cb = event_cb,
|
||||
};
|
||||
esp_err_t ret = sdio_slave_initialize(&config);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BUFFER_NUM; i++) {
|
||||
sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(sdio_slave_rx_buffer[i]);
|
||||
if (handle == NULL) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ret = sdio_slave_recv_load_buf(handle);
|
||||
if (ret != ESP_OK) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
sdio_slave_set_host_intena(SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET); // only need one interrupt to notify of a new packet
|
||||
|
||||
ret = sdio_slave_start();
|
||||
if (ret != ESP_OK) {
|
||||
sdio_slave_deinit();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void eppp_sdio_slave_deinit(void)
|
||||
{
|
||||
sdio_slave_stop();
|
||||
sdio_slave_deinit();
|
||||
}
|
||||
|
||||
#else // SOC_SDIO_SLAVE NOT-SUPPORTED
|
||||
|
||||
esp_err_t eppp_sdio_slave_tx(void *h, void *buffer, size_t len)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_err_t eppp_sdio_slave_rx(esp_netif_t *netif)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void eppp_sdio_slave_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t eppp_sdio_slave_init(void)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif // CONFIG_SOC_SDIO_SLAVE_SUPPORTED
|
7
components/eppp_link/examples/host/CMakeLists.txt
Normal file
7
components/eppp_link/examples/host/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# The following four lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(pppos_host)
|
9
components/eppp_link/examples/host/README.md
Normal file
9
components/eppp_link/examples/host/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
# Client side demo of ESP-PPP-Link
|
||||
|
||||
This is a basic demo of using esp-mqtt library, but connects to the internet using a PPPoS client. To run this example, you would need a PPP server that provides connectivity to the MQTT broker used in this example (by default a public broker accessible on the internet).
|
||||
|
||||
If configured, this example could also run a ping session and an iperf console.
|
||||
|
||||
|
||||
The PPP server could be a Linux computer with `pppd` service or an ESP32 acting like a connection gateway with PPPoS server (see the "slave" project).
|
2
components/eppp_link/examples/host/main/CMakeLists.txt
Normal file
2
components/eppp_link/examples/host/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS app_main.c register_iperf.c
|
||||
INCLUDE_DIRS ".")
|
53
components/eppp_link/examples/host/main/Kconfig.projbuild
Normal file
53
components/eppp_link/examples/host/main/Kconfig.projbuild
Normal file
@ -0,0 +1,53 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_GLOBAL_DNS
|
||||
hex "Set global DNS server"
|
||||
range 0 0xFFFFFFFF
|
||||
default 0x08080808
|
||||
help
|
||||
Global DNS server address.
|
||||
|
||||
config EXAMPLE_MQTT
|
||||
bool "Run mqtt example"
|
||||
default y
|
||||
help
|
||||
Run MQTT client after startup.
|
||||
|
||||
config EXAMPLE_BROKER_URL
|
||||
string "Broker URL"
|
||||
depends on EXAMPLE_MQTT
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL of the broker to connect to.
|
||||
|
||||
config EXAMPLE_IPERF
|
||||
bool "Run iperf"
|
||||
default y
|
||||
help
|
||||
Init and run iperf console.
|
||||
|
||||
config EXAMPLE_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 10
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 11
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_UART_BAUDRATE
|
||||
int "Baudrate"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 2000000
|
||||
range 0 4000000
|
||||
help
|
||||
Baudrate used by the PPP over UART
|
||||
|
||||
endmenu
|
151
components/eppp_link/examples/host/main/app_main.c
Normal file
151
components/eppp_link/examples/host/main/app_main.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "eppp_link.h"
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "console_ping.h"
|
||||
|
||||
void register_iperf(void);
|
||||
|
||||
static const char *TAG = "eppp_host_example";
|
||||
|
||||
#if CONFIG_EXAMPLE_MQTT
|
||||
static void mqtt_event_handler(void *args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
esp_mqtt_client_handle_t client = event->client;
|
||||
int msg_id;
|
||||
switch ((esp_mqtt_event_id_t)event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0);
|
||||
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
|
||||
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
|
||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||
|
||||
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
|
||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||
|
||||
msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
|
||||
ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
|
||||
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
|
||||
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_app_start(void)
|
||||
{
|
||||
esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = "mqtt://mqtt.eclipseprojects.io",
|
||||
};
|
||||
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_start(client);
|
||||
}
|
||||
#endif // MQTT
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "[APP] Startup..");
|
||||
ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
|
||||
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
|
||||
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
/* Sets up the default EPPP-connection
|
||||
*/
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||
#else
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
#endif
|
||||
esp_netif_t *eppp_netif = eppp_connect(&config);
|
||||
if (eppp_netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to connect");
|
||||
return ;
|
||||
}
|
||||
// Setup global DNS
|
||||
esp_netif_dns_info_t dns;
|
||||
dns.ip.u_addr.ip4.addr = esp_netif_htonl(CONFIG_EXAMPLE_GLOBAL_DNS);
|
||||
dns.ip.type = ESP_IPADDR_TYPE_V4;
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(eppp_netif, ESP_NETIF_DNS_MAIN, &dns));
|
||||
|
||||
// Initialize console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_init());
|
||||
|
||||
#if CONFIG_EXAMPLE_IPERF
|
||||
register_iperf();
|
||||
|
||||
printf("\n =======================================================\n");
|
||||
printf(" | Steps to Test EPPP-host bandwidth |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | 1. Wait for the ESP32 to get an IP |\n");
|
||||
printf(" | 2. Server: 'iperf -u -s -i 3' (on host) |\n");
|
||||
printf(" | 3. Client: 'iperf -u -c SERVER_IP -t 60 -i 3' |\n");
|
||||
printf(" | |\n");
|
||||
printf(" =======================================================\n\n");
|
||||
|
||||
#endif // CONFIG_EXAMPLE_IPERF
|
||||
|
||||
// Register the ping command
|
||||
ESP_ERROR_CHECK(console_cmd_ping_register());
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(console_cmd_start());
|
||||
|
||||
#if CONFIG_EXAMPLE_MQTT
|
||||
mqtt_app_start();
|
||||
#endif
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
dependencies:
|
||||
espressif/iperf-cmd: "^0.1.1"
|
||||
espressif/eppp_link:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
||||
console_cmd_ping:
|
||||
version: "*"
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
@ -23,24 +24,11 @@
|
||||
#include "esp_event.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "iperf.h"
|
||||
#include "console_iperf.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* "iperf" command */
|
||||
|
||||
/**
|
||||
* Static registration of this plugin is achieved by defining the plugin description
|
||||
* structure and placing it into .console_cmd_desc section.
|
||||
* The name of the section and its placement is determined by linker.lf file in 'plugins' component.
|
||||
*/
|
||||
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
|
||||
.name = "console_cmd_iperf",
|
||||
.plugin_regd_fn = &console_cmd_iperf_register
|
||||
};
|
||||
|
||||
static const char *TAG = "console_iperf";
|
||||
|
||||
static struct {
|
||||
struct arg_str *ip;
|
||||
struct arg_lit *server;
|
||||
@ -55,10 +43,10 @@ static struct {
|
||||
struct arg_end *end;
|
||||
} iperf_args;
|
||||
|
||||
static int do_cmd_iperf(int argc, char **argv)
|
||||
static int ppp_cmd_iperf(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&iperf_args);
|
||||
/* ethernet iperf only support IPV4 address */
|
||||
// ethernet iperf only support IPV4 address
|
||||
iperf_cfg_t cfg = {.type = IPERF_IP_TYPE_IPV4};
|
||||
|
||||
if (nerrors != 0) {
|
||||
@ -151,9 +139,9 @@ static int do_cmd_iperf(int argc, char **argv)
|
||||
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
||||
cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
|
||||
(uint16_t) cfg.source_ip4 & 0xFF,
|
||||
(uint16_t)(cfg.source_ip4 >> 8) & 0xFF,
|
||||
(uint16_t)(cfg.source_ip4 >> 16) & 0xFF,
|
||||
(uint16_t)(cfg.source_ip4 >> 24) & 0xFF,
|
||||
(uint16_t) (cfg.source_ip4 >> 8) & 0xFF,
|
||||
(uint16_t) (cfg.source_ip4 >> 16) & 0xFF,
|
||||
(uint16_t) (cfg.source_ip4 >> 24) & 0xFF,
|
||||
cfg.sport,
|
||||
cfg.destination_ip4 & 0xFF, (cfg.destination_ip4 >> 8) & 0xFF,
|
||||
(cfg.destination_ip4 >> 16) & 0xFF, (cfg.destination_ip4 >> 24) & 0xFF, cfg.dport,
|
||||
@ -163,39 +151,29 @@ static int do_cmd_iperf(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers the iperf command.
|
||||
*
|
||||
* @return
|
||||
* - esp_err_t
|
||||
*/
|
||||
esp_err_t console_cmd_iperf_register(void)
|
||||
void register_iperf(void)
|
||||
{
|
||||
iperf_args.ip = arg_str0("c", "client", "<ip>", "run in client mode, connecting to <host>");
|
||||
|
||||
iperf_args.ip = arg_str0("c", "client", "<ip>",
|
||||
"run in client mode, connecting to <host>");
|
||||
iperf_args.server = arg_lit0("s", "server", "run in server mode");
|
||||
iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
|
||||
iperf_args.version = arg_lit0("V", "ipv6_domain", "use IPV6 address rather than IPV4");
|
||||
iperf_args.port = arg_int0("p", "port", "<port>", "server port to listen on/connect to");
|
||||
iperf_args.port = arg_int0("p", "port", "<port>",
|
||||
"server port to listen on/connect to");
|
||||
iperf_args.length = arg_int0("l", "len", "<length>", "set read/write buffer size");
|
||||
iperf_args.interval = arg_int0("i", "interval", "<interval>", "seconds between periodic bandwidth reports");
|
||||
iperf_args.interval = arg_int0("i", "interval", "<interval>",
|
||||
"seconds between periodic bandwidth reports");
|
||||
iperf_args.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
||||
iperf_args.bw_limit = arg_int0("b", "bandwidth", "<bandwidth>", "bandwidth to send at in Mbits/sec");
|
||||
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
||||
iperf_args.end = arg_end(1);
|
||||
|
||||
esp_err_t ret;
|
||||
const esp_console_cmd_t command = {
|
||||
const esp_console_cmd_t iperf_cmd = {
|
||||
.command = "iperf",
|
||||
.help = "Command to measure network performance, through TCP or UDP connections.",
|
||||
.help = "iperf command",
|
||||
.hint = NULL,
|
||||
.func = &do_cmd_iperf,
|
||||
.func = &ppp_cmd_iperf,
|
||||
.argtable = &iperf_args
|
||||
};
|
||||
|
||||
ret = esp_console_cmd_register(&command);
|
||||
if (ret) {
|
||||
ESP_LOGE(TAG, "Unable to register iperf");
|
||||
}
|
||||
|
||||
return ret;
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&iperf_cmd));
|
||||
}
|
1
components/eppp_link/examples/host/sdkconfig.ci.spi
Normal file
1
components/eppp_link/examples/host/sdkconfig.ci.spi
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_EPPP_LINK_DEVICE_SPI=y
|
1
components/eppp_link/examples/host/sdkconfig.ci.uart
Normal file
1
components/eppp_link/examples/host/sdkconfig.ci.uart
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_EPPP_LINK_DEVICE_UART=y
|
4
components/eppp_link/examples/host/sdkconfig.defaults
Normal file
4
components/eppp_link/examples/host/sdkconfig.defaults
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_SERVER_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n
|
||||
CONFIG_LWIP_PPP_DEBUG_ON=y
|
6
components/eppp_link/examples/slave/CMakeLists.txt
Normal file
6
components/eppp_link/examples/slave/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(pppos_slave)
|
7
components/eppp_link/examples/slave/README.md
Normal file
7
components/eppp_link/examples/slave/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
# Wi-Fi station to PPPoS server
|
||||
|
||||
This example demonstrate using NAPT to bring connectivity from WiFi station to PPPoS server.
|
||||
|
||||
This example expect a PPPoS client to connect to the server and use the connectivity.
|
||||
The client could be a Linux computer with `pppd` service or another microcontroller with PPP client (or another ESP32 with not WiFi interface)
|
2
components/eppp_link/examples/slave/main/CMakeLists.txt
Normal file
2
components/eppp_link/examples/slave/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "eppp_slave.c"
|
||||
INCLUDE_DIRS ".")
|
45
components/eppp_link/examples/slave/main/Kconfig.projbuild
Normal file
45
components/eppp_link/examples/slave/main/Kconfig.projbuild
Normal file
@ -0,0 +1,45 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config ESP_MAXIMUM_RETRY
|
||||
int "Maximum retry"
|
||||
default 5
|
||||
help
|
||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||
|
||||
config EXAMPLE_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 11
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 10
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_UART_BAUDRATE
|
||||
int "Baudrate"
|
||||
depends on EPPP_LINK_DEVICE_UART
|
||||
default 2000000
|
||||
range 0 4000000
|
||||
help
|
||||
Baudrate used by the PPP over UART
|
||||
|
||||
endmenu
|
152
components/eppp_link/examples/slave/main/eppp_slave.c
Normal file
152
components/eppp_link/examples/slave/main/eppp_slave.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "eppp_link.h"
|
||||
|
||||
static const char *TAG = "eppp_slave";
|
||||
|
||||
#if CONFIG_SOC_WIFI_SUPPORTED
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) {
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||
} else {
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
ESP_LOGI(TAG, "connect to the AP fail");
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void init_network_interface(void)
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
||||
IP_EVENT_STA_GOT_IP,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_got_ip));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||
.password = CONFIG_ESP_WIFI_PASSWORD,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
|
||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||
pdFALSE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||
* happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
|
||||
CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
|
||||
CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
void init_network_interface(void)
|
||||
{
|
||||
// placeholder to initialize any other network interface if WiFi is not available
|
||||
}
|
||||
|
||||
#endif // SoC WiFi capable chip
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
//Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
init_network_interface(); // WiFi station if withing SoC capabilities (otherwise a placeholder)
|
||||
// ESP_ERROR_CHECK(esp_netif_init());
|
||||
// ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
#if CONFIG_EPPP_LINK_DEVICE_SPI
|
||||
config.transport = EPPP_TRANSPORT_SPI;
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_UART
|
||||
config.transport = EPPP_TRANSPORT_UART;
|
||||
config.uart.tx_io = CONFIG_EXAMPLE_UART_TX_PIN;
|
||||
config.uart.rx_io = CONFIG_EXAMPLE_UART_RX_PIN;
|
||||
config.uart.baud = CONFIG_EXAMPLE_UART_BAUDRATE;
|
||||
#elif CONFIG_EPPP_LINK_DEVICE_SDIO
|
||||
config.transport = EPPP_TRANSPORT_SDIO;
|
||||
#endif // transport device
|
||||
|
||||
esp_netif_t *eppp_netif = eppp_listen(&config);
|
||||
if (eppp_netif == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to setup connection");
|
||||
return ;
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_netif_napt_enable(eppp_netif));
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/eppp_link:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
1
components/eppp_link/examples/slave/sdkconfig.ci.spi
Normal file
1
components/eppp_link/examples/slave/sdkconfig.ci.spi
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_EPPP_LINK_DEVICE_SPI=y
|
1
components/eppp_link/examples/slave/sdkconfig.ci.uart
Normal file
1
components/eppp_link/examples/slave/sdkconfig.ci.uart
Normal file
@ -0,0 +1 @@
|
||||
CONFIG_EPPP_LINK_DEVICE_UART=y
|
6
components/eppp_link/examples/slave/sdkconfig.defaults
Normal file
6
components/eppp_link/examples/slave/sdkconfig.defaults
Normal file
@ -0,0 +1,6 @@
|
||||
CONFIG_LWIP_IP_FORWARD=y
|
||||
CONFIG_LWIP_IPV4_NAPT=y
|
||||
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_SERVER_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n
|
6
components/eppp_link/idf_component.yml
Normal file
6
components/eppp_link/idf_component.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: 0.2.0
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/eppp_link
|
||||
description: The component provides a general purpose PPP connectivity, typically used as WiFi-PPP router
|
||||
dependencies:
|
||||
idf: '>=5.2'
|
||||
espressif/esp_serial_slave_link: "^1.1.0"
|
135
components/eppp_link/include/eppp_link.h
Normal file
135
components/eppp_link/include/eppp_link.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define EPPP_DEFAULT_SERVER_IP() ESP_IP4TOADDR(192, 168, 11, 1)
|
||||
#define EPPP_DEFAULT_CLIENT_IP() ESP_IP4TOADDR(192, 168, 11, 2)
|
||||
|
||||
#define EPPP_DEFAULT_CONFIG(our_ip, their_ip) { \
|
||||
.transport = EPPP_TRANSPORT_UART, \
|
||||
.spi = { \
|
||||
.host = 1, \
|
||||
.mosi = 11, \
|
||||
.miso = 13, \
|
||||
.sclk = 12, \
|
||||
.cs = 10, \
|
||||
.intr = 2, \
|
||||
.freq = 16*1000*1000, \
|
||||
.input_delay_ns = 0, \
|
||||
.cs_ena_pretrans = 0, \
|
||||
.cs_ena_posttrans = 0, \
|
||||
}, \
|
||||
.uart = { \
|
||||
.port = 1, \
|
||||
.baud = 921600, \
|
||||
.tx_io = 25, \
|
||||
.rx_io = 26, \
|
||||
.queue_size = 16, \
|
||||
.rx_buffer_size = 1024, \
|
||||
}, \
|
||||
.sdio = { \
|
||||
.width = 4, \
|
||||
.clk = 18, \
|
||||
.cmd = 19, \
|
||||
.d0 = 49, \
|
||||
.d1 = 50, \
|
||||
.d2 = 16, \
|
||||
.d3 = 17, \
|
||||
}, \
|
||||
. task = { \
|
||||
.run_task = true, \
|
||||
.stack_size = 4096, \
|
||||
.priority = 8, \
|
||||
}, \
|
||||
. ppp = { \
|
||||
.our_ip4_addr = { .addr = our_ip }, \
|
||||
.their_ip4_addr = { .addr = their_ip }, \
|
||||
.netif_prio = 0, \
|
||||
.netif_description = NULL, \
|
||||
} \
|
||||
}
|
||||
|
||||
#define EPPP_DEFAULT_SERVER_CONFIG() EPPP_DEFAULT_CONFIG(EPPP_DEFAULT_SERVER_IP(), EPPP_DEFAULT_CLIENT_IP())
|
||||
#define EPPP_DEFAULT_CLIENT_CONFIG() EPPP_DEFAULT_CONFIG(EPPP_DEFAULT_CLIENT_IP(), EPPP_DEFAULT_SERVER_IP())
|
||||
|
||||
typedef enum eppp_type {
|
||||
EPPP_SERVER,
|
||||
EPPP_CLIENT,
|
||||
} eppp_type_t;
|
||||
|
||||
typedef enum eppp_transport {
|
||||
EPPP_TRANSPORT_UART,
|
||||
EPPP_TRANSPORT_SPI,
|
||||
EPPP_TRANSPORT_SDIO,
|
||||
} eppp_transport_t;
|
||||
|
||||
|
||||
typedef struct eppp_config_t {
|
||||
eppp_transport_t transport;
|
||||
|
||||
struct eppp_config_spi_s {
|
||||
int host;
|
||||
int mosi;
|
||||
int miso;
|
||||
int sclk;
|
||||
int cs;
|
||||
int intr;
|
||||
int freq;
|
||||
int input_delay_ns;
|
||||
int cs_ena_pretrans;
|
||||
int cs_ena_posttrans;
|
||||
} spi;
|
||||
|
||||
struct eppp_config_uart_s {
|
||||
int port;
|
||||
int baud;
|
||||
int tx_io;
|
||||
int rx_io;
|
||||
int queue_size;
|
||||
int rx_buffer_size;
|
||||
} uart;
|
||||
|
||||
struct eppp_config_sdio_s {
|
||||
int width;
|
||||
int clk;
|
||||
int cmd;
|
||||
int d0;
|
||||
int d1;
|
||||
int d2;
|
||||
int d3;
|
||||
} sdio;
|
||||
|
||||
struct eppp_config_task_s {
|
||||
bool run_task;
|
||||
int stack_size;
|
||||
int priority;
|
||||
} task;
|
||||
|
||||
struct eppp_config_pppos_s {
|
||||
esp_ip4_addr_t our_ip4_addr;
|
||||
esp_ip4_addr_t their_ip4_addr;
|
||||
int netif_prio;
|
||||
const char *netif_description;
|
||||
} ppp;
|
||||
|
||||
} eppp_config_t;
|
||||
|
||||
esp_netif_t *eppp_connect(eppp_config_t *config);
|
||||
|
||||
esp_netif_t *eppp_listen(eppp_config_t *config);
|
||||
|
||||
void eppp_close(esp_netif_t *netif);
|
||||
|
||||
esp_netif_t *eppp_init(eppp_type_t role, eppp_config_t *config);
|
||||
|
||||
void eppp_deinit(esp_netif_t *netif);
|
||||
|
||||
esp_netif_t *eppp_open(eppp_type_t role, eppp_config_t *config, int connect_timeout_ms);
|
||||
|
||||
esp_err_t eppp_netif_stop(esp_netif_t *netif, int stop_timeout_ms);
|
||||
|
||||
esp_err_t eppp_netif_start(esp_netif_t *netif);
|
||||
|
||||
esp_err_t eppp_perform(esp_netif_t *netif);
|
7
components/eppp_link/test/test_app/CMakeLists.txt
Normal file
7
components/eppp_link/test/test_app/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# The following four lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/tools/unit-test-app/components)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_app)
|
73
components/eppp_link/test/test_app/README.md
Normal file
73
components/eppp_link/test/test_app/README.md
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
# Test application running both server and client on the same device
|
||||
|
||||
Need to connect client's Tx to server's Rx and vice versa:
|
||||
GPIO25 - GPIO4
|
||||
GPIO26 - GPIO5
|
||||
|
||||
We wait for the connection and then we start pinging the client's address on server's netif.
|
||||
|
||||
## Example of output:
|
||||
|
||||
```
|
||||
I (393) eppp_test_app: [APP] Startup..
|
||||
I (393) eppp_test_app: [APP] Free memory: 296332 bytes
|
||||
I (393) eppp_test_app: [APP] IDF version: v5.3-dev-1154-gf14d9e7431-dirty
|
||||
I (423) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
I (423) uart: queue free spaces: 16
|
||||
I (433) eppp_link: Waiting for IP address
|
||||
I (433) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
I (443) uart: queue free spaces: 16
|
||||
I (443) eppp_link: Waiting for IP address
|
||||
I (6473) esp-netif_lwip-ppp: Connected
|
||||
I (6513) eppp_link: Got IPv4 event: Interface "pppos_client" address: 192.168.11.2
|
||||
I (6523) esp-netif_lwip-ppp: Connected
|
||||
I (6513) eppp_link: Connected!
|
||||
I (6523) eppp_link: Got IPv4 event: Interface "pppos_server" address: 192.168.11.1
|
||||
I (6553) main_task: Returned from app_main()
|
||||
64bytes from 192.168.11.2 icmp_seq=1 ttl=255 time=18 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=2 ttl=255 time=19 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=3 ttl=255 time=19 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=4 ttl=255 time=20 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=5 ttl=255 time=19 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=6 ttl=255 time=19 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=7 ttl=255 time=19 ms
|
||||
From 192.168.11.2 icmp_seq=8 timeout // <-- Disconnected Tx-Rx wires
|
||||
From 192.168.11.2 icmp_seq=9 timeout
|
||||
```
|
||||
## Test cases
|
||||
|
||||
This test app exercises these methods of setting up server-client connection:
|
||||
* simple blocking API (eppp_listen() <--> eppp_connect()): Uses network events internally and waits for connection
|
||||
* simplified non-blocking API (eppp_open(EPPP_SERVER, ...) <--> eppp_open(EPPP_SERVER, ...) ): Uses events internally, optionally waits for connecting
|
||||
* manual API (eppp_init(), eppp_netif_start(), eppp_perform()): User to manually drive Rx task
|
||||
- Note that the ping test for this test case takes longer, since we call perform for both server and client from one task, for example:
|
||||
|
||||
```
|
||||
TEST(eppp_test, open_close_taskless)I (28562) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
I (28572) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
Note: esp_netif_init() has been called. Until next reset, TCP/IP task will periodicially allocate memory and consume CPU time.
|
||||
I (28602) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
I (28612) uart: queue free spaces: 16
|
||||
I (28612) uart: ESP_INTR_FLAG_IRAM flag not set while CONFIG_UART_ISR_IN_IRAM is enabled, flag updated
|
||||
I (28622) uart: queue free spaces: 16
|
||||
I (28642) esp-netif_lwip-ppp: Connected
|
||||
I (28642) esp-netif_lwip-ppp: Connected
|
||||
I (28642) test: Got IPv4 event: Interface "pppos_server(EPPP0)" address: 192.168.11.1
|
||||
I (28642) esp-netif_lwip-ppp: Connected
|
||||
I (28652) test: Got IPv4 event: Interface "pppos_client(EPPP1)" address: 192.168.11.2
|
||||
I (28662) esp-netif_lwip-ppp: Connected
|
||||
64bytes from 192.168.11.2 icmp_seq=1 ttl=255 time=93 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=2 ttl=255 time=98 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=3 ttl=255 time=99 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=4 ttl=255 time=99 ms
|
||||
64bytes from 192.168.11.2 icmp_seq=5 ttl=255 time=99 ms
|
||||
5 packets transmitted, 5 received, time 488ms
|
||||
I (29162) esp-netif_lwip-ppp: User interrupt
|
||||
I (29162) test: Disconnected interface "pppos_client(EPPP1)"
|
||||
I (29172) esp-netif_lwip-ppp: User interrupt
|
||||
I (29172) test: Disconnected interface "pppos_server(EPPP0)"
|
||||
MALLOC_CAP_8BIT usage: Free memory delta: 0 Leak threshold: -64
|
||||
MALLOC_CAP_32BIT usage: Free memory delta: 0 Leak threshold: -64
|
||||
PASS
|
||||
```
|
4
components/eppp_link/test/test_app/main/CMakeLists.txt
Normal file
4
components/eppp_link/test/test_app/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS app_main.c
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES test_utils
|
||||
PRIV_REQUIRES unity nvs_flash esp_netif driver esp_event)
|
344
components/eppp_link/test/test_app/main/app_main.c
Normal file
344
components/eppp_link/test/test_app/main/app_main.c
Normal file
@ -0,0 +1,344 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_netif_ppp.h"
|
||||
#include "eppp_link.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "esp_log.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "driver/uart.h"
|
||||
#include "test_utils.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "unity_fixture.h"
|
||||
#include "memory_checks.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#define CLIENT_INFO_CONNECTED BIT0
|
||||
#define CLIENT_INFO_DISCONNECT BIT1
|
||||
#define CLIENT_INFO_CLOSED BIT2
|
||||
#define PING_SUCCEEDED BIT3
|
||||
#define PING_FAILED BIT4
|
||||
#define STOP_WORKER_TASK BIT5
|
||||
#define WORKER_TASK_STOPPED BIT6
|
||||
|
||||
TEST_GROUP(eppp_test);
|
||||
TEST_SETUP(eppp_test)
|
||||
{
|
||||
// Perform some open/close operations to disregard lazy init one-time allocations
|
||||
// LWIP: core protection mutex
|
||||
sys_arch_protect();
|
||||
sys_arch_unprotect(0);
|
||||
// UART: install and delete both drivers to disregard potential leak in allocated interrupt slot
|
||||
TEST_ESP_OK(uart_driver_install(UART_NUM_1, 256, 0, 0, NULL, 0));
|
||||
TEST_ESP_OK(uart_driver_delete(UART_NUM_1));
|
||||
TEST_ESP_OK(uart_driver_install(UART_NUM_2, 256, 0, 0, NULL, 0));
|
||||
TEST_ESP_OK(uart_driver_delete(UART_NUM_2));
|
||||
// PING: used for timestamps
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(eppp_test)
|
||||
{
|
||||
test_utils_finish_and_evaluate_leaks(32, 64);
|
||||
}
|
||||
|
||||
static void test_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
EventGroupHandle_t event = args;
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
printf("%" PRId32 " packets transmitted, %" PRId32 " received, time %" PRId32 "ms\n", transmitted, received, total_time_ms);
|
||||
if (transmitted == received) {
|
||||
xEventGroupSetBits(event, PING_SUCCEEDED);
|
||||
} else {
|
||||
xEventGroupSetBits(event, PING_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
printf("%" PRId32 "bytes from %s icmp_seq=%d ttl=%d time=%" PRId32 " ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
struct client_info {
|
||||
esp_netif_t *netif;
|
||||
EventGroupHandle_t event;
|
||||
};
|
||||
|
||||
static void open_client_task(void *ctx)
|
||||
{
|
||||
struct client_info *info = ctx;
|
||||
eppp_config_t config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
config.uart.port = UART_NUM_2;
|
||||
config.uart.tx_io = 4;
|
||||
config.uart.rx_io = 5;
|
||||
|
||||
info->netif = eppp_connect(&config);
|
||||
xEventGroupSetBits(info->event, CLIENT_INFO_CONNECTED);
|
||||
|
||||
// wait for disconnection trigger
|
||||
EventBits_t bits = xEventGroupWaitBits(info->event, CLIENT_INFO_DISCONNECT, pdFALSE, pdFALSE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & CLIENT_INFO_DISCONNECT, CLIENT_INFO_DISCONNECT);
|
||||
eppp_close(info->netif);
|
||||
xEventGroupSetBits(info->event, CLIENT_INFO_CLOSED);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST(eppp_test, init_deinit)
|
||||
{
|
||||
// Init and deinit server size
|
||||
eppp_config_t config = EPPP_DEFAULT_CONFIG(0, 0);
|
||||
esp_netif_t *netif = eppp_init(EPPP_SERVER, &config);
|
||||
TEST_ASSERT_NOT_NULL(netif);
|
||||
eppp_deinit(netif);
|
||||
netif = NULL;
|
||||
// Init and deinit client size
|
||||
netif = eppp_init(EPPP_CLIENT, &config);
|
||||
TEST_ASSERT_NOT_NULL(netif);
|
||||
eppp_deinit(netif);
|
||||
}
|
||||
|
||||
static EventBits_t ping_test(uint32_t addr, esp_netif_t *netif, EventGroupHandle_t event)
|
||||
{
|
||||
ip_addr_t target_addr = { .type = IPADDR_TYPE_V4, .u_addr.ip4.addr = addr };
|
||||
esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
|
||||
ping_config.interval_ms = 100;
|
||||
ping_config.target_addr = target_addr;
|
||||
ping_config.interface = esp_netif_get_netif_impl_index(netif);
|
||||
esp_ping_callbacks_t cbs = { .cb_args = event, .on_ping_end = test_on_ping_end, .on_ping_success = test_on_ping_success };
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&ping_config, &cbs, &ping);
|
||||
esp_ping_start(ping);
|
||||
// Wait for the client thread closure and delete locally created objects
|
||||
EventBits_t bits = xEventGroupWaitBits(event, PING_SUCCEEDED | PING_FAILED, pdFALSE, pdFALSE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & (PING_SUCCEEDED | PING_FAILED), PING_SUCCEEDED);
|
||||
esp_ping_stop(ping);
|
||||
esp_ping_delete_session(ping);
|
||||
return bits;
|
||||
}
|
||||
|
||||
TEST(eppp_test, open_close)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
|
||||
eppp_config_t config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
struct client_info client = { .netif = NULL, .event = xEventGroupCreate()};
|
||||
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
|
||||
TEST_ASSERT_NOT_NULL(client.event);
|
||||
|
||||
// Need to connect the client in a separate thread, as the simplified API blocks until connection
|
||||
xTaskCreate(open_client_task, "client_task", 4096, &client, 5, NULL);
|
||||
|
||||
// Now start the server
|
||||
esp_netif_t *eppp_server = eppp_listen(&config);
|
||||
|
||||
// Wait for the client to connect
|
||||
EventBits_t bits = xEventGroupWaitBits(client.event, CLIENT_INFO_CONNECTED, pdFALSE, pdFALSE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & CLIENT_INFO_CONNECTED, CLIENT_INFO_CONNECTED);
|
||||
|
||||
// Check that both server and client are valid netif pointers
|
||||
TEST_ASSERT_NOT_NULL(eppp_server);
|
||||
TEST_ASSERT_NOT_NULL(client.netif);
|
||||
|
||||
// Now that we're connected, let's try to ping clients address
|
||||
bits = ping_test(config.ppp.their_ip4_addr.addr, eppp_server, client.event);
|
||||
TEST_ASSERT_EQUAL(bits & (PING_SUCCEEDED | PING_FAILED), PING_SUCCEEDED);
|
||||
|
||||
// Trigger client disconnection and close the server
|
||||
xEventGroupSetBits(client.event, CLIENT_INFO_DISCONNECT);
|
||||
eppp_close(eppp_server);
|
||||
|
||||
// Wait for the client thread closure and delete locally created objects
|
||||
bits = xEventGroupWaitBits(client.event, CLIENT_INFO_CLOSED, pdFALSE, pdFALSE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & CLIENT_INFO_CLOSED, CLIENT_INFO_CLOSED);
|
||||
|
||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||
vEventGroupDelete(client.event);
|
||||
|
||||
// wait for the lwip sockets to close cleanly
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
static void on_event(void *arg, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
EventGroupHandle_t event = arg;
|
||||
if (base == IP_EVENT && event_id == IP_EVENT_PPP_GOT_IP) {
|
||||
ip_event_got_ip_t *e = (ip_event_got_ip_t *)data;
|
||||
esp_netif_t *netif = e->esp_netif;
|
||||
ESP_LOGI("test", "Got IPv4 event: Interface \"%s(%s)\" address: " IPSTR, esp_netif_get_desc(netif),
|
||||
esp_netif_get_ifkey(netif), IP2STR(&e->ip_info.ip));
|
||||
if (strcmp("pppos_server", esp_netif_get_desc(netif)) == 0) {
|
||||
xEventGroupSetBits(event, 1 << EPPP_SERVER);
|
||||
} else if (strcmp("pppos_client", esp_netif_get_desc(netif)) == 0) {
|
||||
xEventGroupSetBits(event, 1 << EPPP_CLIENT);
|
||||
}
|
||||
} else if (base == NETIF_PPP_STATUS && event_id == NETIF_PPP_ERRORUSER) {
|
||||
esp_netif_t **netif = data;
|
||||
ESP_LOGI("test", "Disconnected interface \"%s(%s)\"", esp_netif_get_desc(*netif), esp_netif_get_ifkey(*netif));
|
||||
if (strcmp("pppos_server", esp_netif_get_desc(*netif)) == 0) {
|
||||
xEventGroupSetBits(event, 1 << EPPP_SERVER);
|
||||
} else if (strcmp("pppos_client", esp_netif_get_desc(*netif)) == 0) {
|
||||
xEventGroupSetBits(event, 1 << EPPP_CLIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(eppp_test, open_close_nonblocking)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
EventGroupHandle_t event = xEventGroupCreate();
|
||||
|
||||
eppp_config_t server_config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
|
||||
// Open the server size
|
||||
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_event, event));
|
||||
esp_netif_t *eppp_server = eppp_open(EPPP_SERVER, &server_config, 0);
|
||||
TEST_ASSERT_NOT_NULL(eppp_server);
|
||||
// Open the client size
|
||||
eppp_config_t client_config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
client_config.uart.port = UART_NUM_2;
|
||||
client_config.uart.tx_io = 4;
|
||||
client_config.uart.rx_io = 5;
|
||||
esp_netif_t *eppp_client = eppp_open(EPPP_CLIENT, &client_config, 0);
|
||||
TEST_ASSERT_NOT_NULL(eppp_client);
|
||||
const EventBits_t wait_bits = (1 << EPPP_SERVER) | (1 << EPPP_CLIENT);
|
||||
EventBits_t bits = xEventGroupWaitBits(event, wait_bits, pdTRUE, pdTRUE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & wait_bits, wait_bits);
|
||||
|
||||
// Now that we're connected, let's try to ping clients address
|
||||
bits = ping_test(server_config.ppp.their_ip4_addr.addr, eppp_server, event);
|
||||
TEST_ASSERT_EQUAL(bits & (PING_SUCCEEDED | PING_FAILED), PING_SUCCEEDED);
|
||||
|
||||
// stop network for both client and server
|
||||
eppp_netif_stop(eppp_client, 0); // ignore result, since we're not waiting for clean close
|
||||
eppp_close(eppp_server);
|
||||
eppp_close(eppp_client); // finish client close
|
||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||
vEventGroupDelete(event);
|
||||
|
||||
// wait for the lwip sockets to close cleanly
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
|
||||
struct worker {
|
||||
esp_netif_t *eppp_server;
|
||||
esp_netif_t *eppp_client;
|
||||
EventGroupHandle_t event;
|
||||
};
|
||||
|
||||
static void worker_task(void *ctx)
|
||||
{
|
||||
struct worker *info = ctx;
|
||||
while (1) {
|
||||
eppp_perform(info->eppp_server);
|
||||
eppp_perform(info->eppp_client);
|
||||
if (xEventGroupGetBits(info->event) & STOP_WORKER_TASK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
xEventGroupSetBits(info->event, WORKER_TASK_STOPPED);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST(eppp_test, open_close_taskless)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
struct worker info = { .event = xEventGroupCreate() };
|
||||
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, on_event, info.event));
|
||||
TEST_ESP_OK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, on_event, info.event));
|
||||
|
||||
// Create server
|
||||
eppp_config_t server_config = EPPP_DEFAULT_SERVER_CONFIG();
|
||||
info.eppp_server = eppp_init(EPPP_SERVER, &server_config);
|
||||
TEST_ASSERT_NOT_NULL(info.eppp_server);
|
||||
// Create client
|
||||
eppp_config_t client_config = EPPP_DEFAULT_CLIENT_CONFIG();
|
||||
client_config.uart.port = UART_NUM_2;
|
||||
client_config.uart.tx_io = 4;
|
||||
client_config.uart.rx_io = 5;
|
||||
info.eppp_client = eppp_init(EPPP_CLIENT, &client_config);
|
||||
TEST_ASSERT_NOT_NULL(info.eppp_client);
|
||||
// Start workers
|
||||
xTaskCreate(worker_task, "worker", 4096, &info, 5, NULL);
|
||||
// Start network
|
||||
TEST_ESP_OK(eppp_netif_start(info.eppp_server));
|
||||
TEST_ESP_OK(eppp_netif_start(info.eppp_client));
|
||||
|
||||
const EventBits_t wait_bits = (1 << EPPP_SERVER) | (1 << EPPP_CLIENT);
|
||||
EventBits_t bits = xEventGroupWaitBits(info.event, wait_bits, pdTRUE, pdTRUE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & wait_bits, wait_bits);
|
||||
xEventGroupClearBits(info.event, wait_bits);
|
||||
|
||||
// Now that we're connected, let's try to ping clients address
|
||||
bits = ping_test(server_config.ppp.their_ip4_addr.addr, info.eppp_server, info.event);
|
||||
TEST_ASSERT_EQUAL(bits & (PING_SUCCEEDED | PING_FAILED), PING_SUCCEEDED);
|
||||
|
||||
// stop network for both client and server, we won't wait for completion so expecting ESP_FAIL
|
||||
TEST_ASSERT_EQUAL(eppp_netif_stop(info.eppp_client, 0), ESP_FAIL);
|
||||
TEST_ASSERT_EQUAL(eppp_netif_stop(info.eppp_server, 0), ESP_FAIL);
|
||||
// and wait for completion
|
||||
bits = xEventGroupWaitBits(info.event, wait_bits, pdTRUE, pdTRUE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & wait_bits, wait_bits);
|
||||
|
||||
// now stop the worker
|
||||
xEventGroupSetBits(info.event, STOP_WORKER_TASK);
|
||||
bits = xEventGroupWaitBits(info.event, WORKER_TASK_STOPPED, pdTRUE, pdTRUE, pdMS_TO_TICKS(50000));
|
||||
TEST_ASSERT_EQUAL(bits & WORKER_TASK_STOPPED, WORKER_TASK_STOPPED);
|
||||
|
||||
// and destroy objects
|
||||
eppp_deinit(info.eppp_server);
|
||||
eppp_deinit(info.eppp_client);
|
||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||
vEventGroupDelete(info.event);
|
||||
|
||||
// wait for the lwip sockets to close cleanly
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
|
||||
TEST_GROUP_RUNNER(eppp_test)
|
||||
{
|
||||
RUN_TEST_CASE(eppp_test, init_deinit)
|
||||
RUN_TEST_CASE(eppp_test, open_close)
|
||||
RUN_TEST_CASE(eppp_test, open_close_nonblocking)
|
||||
RUN_TEST_CASE(eppp_test, open_close_taskless)
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UNITY_MAIN(eppp_test);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/eppp_link:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
9
components/eppp_link/test/test_app/sdkconfig.defaults
Normal file
9
components/eppp_link/test/test_app/sdkconfig.defaults
Normal file
@ -0,0 +1,9 @@
|
||||
CONFIG_IDF_TARGET="esp32"
|
||||
CONFIG_UART_ISR_IN_IRAM=y
|
||||
CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=0
|
||||
CONFIG_FREERTOS_UNICORE=y
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_SERVER_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_VJ_HEADER_COMPRESSION=n
|
||||
CONFIG_LWIP_PPP_DEBUG_ON=y
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
@ -1,6 +1,6 @@
|
||||
components/esp_modem/examples/ap_to_pppos:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32h2"]
|
||||
- if: IDF_TARGET in ["esp32h2", "esp32p4"]
|
||||
|
||||
components/esp_modem/examples/modem_console:
|
||||
disable:
|
||||
|
@ -3,6 +3,6 @@ commitizen:
|
||||
bump_message: 'bump(modem): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py esp_modem
|
||||
tag_format: modem-v$version
|
||||
version: 1.0.5
|
||||
version: 1.1.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
|
@ -1,5 +1,28 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0](https://github.com/espressif/esp-protocols/commits/modem-v1.1.0)
|
||||
|
||||
### Features
|
||||
|
||||
- Added support for at_raw() command ([ae38110](https://github.com/espressif/esp-protocols/commit/ae38110), [#471](https://github.com/espressif/esp-protocols/issues/471))
|
||||
- Added iperf test for PPP netifs ([976e98d](https://github.com/espressif/esp-protocols/commit/976e98d))
|
||||
- Added test that performs OTA to exercise modem layers ([f2223dd](https://github.com/espressif/esp-protocols/commit/f2223dd))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed OTA test to gracefully fail with no verification ([1dc4299](https://github.com/espressif/esp-protocols/commit/1dc4299))
|
||||
- Added C-API to configure APN ([ce7dadd](https://github.com/espressif/esp-protocols/commit/ce7dadd), [#485](https://github.com/espressif/esp-protocols/issues/485))
|
||||
- Fixed AT commands to copy strings to prevent overrides ([741d166](https://github.com/espressif/esp-protocols/commit/741d166), [#463](https://github.com/espressif/esp-protocols/issues/463))
|
||||
- Fixed incorrect dial command format ([0998f3d](https://github.com/espressif/esp-protocols/commit/0998f3d), [#433](https://github.com/espressif/esp-protocols/issues/433))
|
||||
- Fixed documentation and example on creating custom device ([577de67](https://github.com/espressif/esp-protocols/commit/577de67), [#452](https://github.com/espressif/esp-protocols/issues/452))
|
||||
- Removed CI jobs for IDF v4.2 ([d88cd61](https://github.com/espressif/esp-protocols/commit/d88cd61))
|
||||
- Fixed OAT test to verify server cert and CN ([edc3e72](https://github.com/espressif/esp-protocols/commit/edc3e72))
|
||||
- Fixed set_pdp_context() command timeout ([1d80cbc](https://github.com/espressif/esp-protocols/commit/1d80cbc), [#455](https://github.com/espressif/esp-protocols/issues/455))
|
||||
|
||||
### Updated
|
||||
|
||||
- docs(modem): Added description of manual test procedure ([68ce794](https://github.com/espressif/esp-protocols/commit/68ce794))
|
||||
|
||||
## [1.0.5](https://github.com/espressif/esp-protocols/commits/modem-v1.0.5)
|
||||
|
||||
### Major changes
|
||||
|
@ -45,8 +45,3 @@ set_target_properties(${COMPONENT_LIB} PROPERTIES
|
||||
if(CONFIG_ESP_MODEM_ADD_CUSTOM_MODULE)
|
||||
idf_component_optional_requires(PUBLIC main)
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
# This is needed for ESP_LOGx() macros, as integer formats differ on ESP32(..) and x64
|
||||
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_FLAGS -Wno-format)
|
||||
endif()
|
||||
|
@ -22,8 +22,7 @@ using namespace esp_modem;
|
||||
|
||||
[[maybe_unused]] constexpr auto TAG = "linux_modem_main";
|
||||
|
||||
|
||||
int main()
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
// init the DTE
|
||||
esp_modem_dte_config_t dte_config = {
|
||||
|
@ -16,9 +16,9 @@ class.
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
|
@ -10,7 +10,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -36,6 +36,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -160,6 +160,9 @@ extern "C" void app_main(void)
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
@ -180,7 +183,7 @@ extern "C" void app_main(void)
|
||||
});
|
||||
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
|
||||
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif);
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_A7670 == 1 || CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
|
||||
#else
|
||||
#error USB modem not selected
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS mbedtls_wrap.cpp
|
||||
tls_transport.cpp
|
||||
idf_component_register(SRCS tls_transport.cpp
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES tcp_transport)
|
||||
REQUIRES tcp_transport
|
||||
PRIV_REQUIRES mbedtls_cxx)
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
static const char *TAG = "tls_transport";
|
||||
|
||||
using namespace idf::mbedtls_cxx;
|
||||
|
||||
class TlsTransport: public Tls {
|
||||
public:
|
||||
explicit TlsTransport(esp_transport_handle_t parent) : Tls(), transport_(parent) {}
|
||||
|
@ -2,3 +2,6 @@ dependencies:
|
||||
espressif/esp_modem:
|
||||
version: "^1.0.1"
|
||||
override_path: "../../../"
|
||||
espressif/mbedtls_cxx:
|
||||
version: "*"
|
||||
override_path: "../../../../mbedtls_cxx"
|
||||
|
@ -11,9 +11,9 @@ See the README.md file in the upper level `pppos` directory for more information
|
||||
|
||||
### USB DTE support
|
||||
|
||||
For USB enabled targets (ESP32-S2 and ESP32-S3), it is possible to connect to the modem device via USB.
|
||||
For USB enabled targets (ESP32-S2, ESP32-S3, or ESP32-P4), it is possible to connect to the modem device via USB.
|
||||
1. In menuconfig, navigate to `Example Configuration->Type of serial connection to the modem` and choose `USB`.
|
||||
2. Connect the modem USB signals to pin 19 (DATA-) and 20 (DATA+) on your ESP chip.
|
||||
2. Connect the modem USB signals to your ESP chip (pin 19 (DATA-) and 20 (DATA+) for ESP32-S2/S3).
|
||||
|
||||
USB example uses Quactel BG96 modem device. BG96 needs a positive pulse on its PWK pin to boot-up.
|
||||
|
||||
|
@ -9,7 +9,7 @@ menu "Example Configuration"
|
||||
Connect to modem via UART.
|
||||
config EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "USB"
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4
|
||||
help
|
||||
Connect to modem via USB (CDC-ACM class). For IDF version >= 4.4.
|
||||
endchoice
|
||||
@ -29,6 +29,11 @@ menu "Example Configuration"
|
||||
bool "BG96"
|
||||
help
|
||||
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
|
||||
config EXAMPLE_MODEM_DEVICE_EC20
|
||||
depends on EXAMPLE_SERIAL_CONFIG_USB
|
||||
bool "EC20"
|
||||
help
|
||||
Quectel EC20 is a series of LTE Cat M4 module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7000
|
||||
depends on EXAMPLE_SERIAL_CONFIG_UART
|
||||
bool "SIM7000"
|
||||
@ -63,26 +68,6 @@ menu "Example Configuration"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_USERNAME
|
||||
string "Set username for authentication"
|
||||
default "espressif"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set username for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_PASSWORD
|
||||
string "Set password for authentication"
|
||||
default "esp32"
|
||||
depends on !EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
help
|
||||
Set password for PPP Authentication.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_AUTH_NONE
|
||||
bool "Skip PPP authentication"
|
||||
default n
|
||||
help
|
||||
Set to true for the PPP client to skip authentication
|
||||
|
||||
config EXAMPLE_SEND_MSG
|
||||
bool "Short message (SMS)"
|
||||
default n
|
||||
|
@ -6,7 +6,7 @@ dependencies:
|
||||
version: "^1.0.0"
|
||||
override_path: "../../../"
|
||||
espressif/esp_modem_usb_dte:
|
||||
version: "^1.1.0"
|
||||
version: "^1.2.0"
|
||||
rules:
|
||||
- if: "idf_version >=4.4"
|
||||
- if: "target in [esp32s2, esp32s3]"
|
||||
- if: "target in [esp32s2, esp32s3, esp32p4]"
|
||||
|
@ -219,6 +219,10 @@ void app_main(void)
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the BG96 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_BG96_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_BG96;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_EC20 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the EC20 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_EC20_USB_CONFIG();
|
||||
esp_modem_dce_device_t usb_dev_type = ESP_MODEM_DCE_EC20;
|
||||
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_SIM7600_USB_CONFIG();
|
||||
|
@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_EXAMPLE_SERIAL_CONFIG_USB=y
|
@ -49,7 +49,7 @@ std::unique_ptr<DCE_gnss> create_SIM7070_GNSS_dce(const esp_modem::dce_config *c
|
||||
return gnss_factory::LocalFactory::create(config, std::move(dte), netif);
|
||||
}
|
||||
|
||||
esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::CommandableIf *t, esp_modem_gps_t &gps)
|
||||
esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::CommandableIf *t, sim70xx_gps_t &gps)
|
||||
{
|
||||
|
||||
ESP_LOGV(TAG, "%s", __func__ );
|
||||
@ -67,24 +67,26 @@ esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::Commandabl
|
||||
}
|
||||
/**
|
||||
* Parsing +CGNSINF:
|
||||
* <GNSS run status>,
|
||||
* <Fix status>,
|
||||
* <UTC date & Time>,
|
||||
* <Latitude>,
|
||||
* <Longitude>,
|
||||
* <MSL Altitude>,
|
||||
* <Speed Over Ground>,
|
||||
* <Course Over Ground>,
|
||||
* <Fix Mode>,
|
||||
* <Reserved1>,
|
||||
* <HDOP>,
|
||||
* <PDOP>,
|
||||
* <VDOP>,
|
||||
* <Reserved2>,
|
||||
* <GNSS Satellites in View>,
|
||||
* <Reserved3>,
|
||||
* <HPA>,
|
||||
* <VPA>
|
||||
| **Index** | **Parameter** | **Unit** | **Range** | **Length** |
|
||||
|-----------|------------------------|--------------------|--------------------------------------------------------------------------------------|------------|
|
||||
| 1 | GNSS run status | -- | 0-1 | 1 |
|
||||
| 2 | Fix status | -- | 0-1 | 1 |
|
||||
| 3 | UTC date & Time | yyyyMMddhhmmss.sss | yyyy: [1980,2039] MM : [1,12] dd: [1,31] hh: [0,23] mm: [0,59] ss.sss:[0.000,60.999] | 18 |
|
||||
| 4 | Latitude | ±dd.dddddd | [-90.000000,90.000000] | 10 |
|
||||
| 5 | Longitude | ±dd.dddddd | -180.000000,180.000000] | 11 |
|
||||
| 6 | MSL Altitude | meters | [0,999.99] | 8 |
|
||||
| 7 | Speed Over Ground | Km/hour | [0,360.00] | 6 |
|
||||
| 8 | Course Over Ground | degrees | 0,1,2[1] | 6 |
|
||||
| 9 | Fix Mode | -- | | 1 |
|
||||
| 10 | Reserved1 | | | 0 |
|
||||
| 11 | HDOP | -- | [0,99.9] | 4 |
|
||||
| 12 | PDOP | -- | [0,99.9] | 4 |
|
||||
| 13 | VDOP | -- | [0,99.9] | 4 |
|
||||
| 14 | Reserved2 | | | 0 |
|
||||
| 15 | GPS Satellites in View | -- | -- [0,99] | 2 |
|
||||
| 16 | Reserved3 | | | 0 |
|
||||
| 17 | HPA[2] | meters | [0,9999.9] | 6 |
|
||||
| 18 | VPA[2] | meters | [0,9999.9] | 6 |
|
||||
*/
|
||||
out = out.substr(pattern.size());
|
||||
int pos = 0;
|
||||
@ -291,11 +293,11 @@ esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::Commandabl
|
||||
{
|
||||
std::string_view sats_in_view = out.substr(0, pos);
|
||||
if (sats_in_view.length() > 1) {
|
||||
if (std::from_chars(out.data(), out.data() + pos, gps.sats_in_view).ec == std::errc::invalid_argument) {
|
||||
if (std::from_chars(out.data(), out.data() + pos, gps.sat.num).ec == std::errc::invalid_argument) {
|
||||
return esp_modem::command_result::FAIL;
|
||||
}
|
||||
} else {
|
||||
gps.sats_in_view = 0;
|
||||
gps.sat.num = 0;
|
||||
}
|
||||
} //clean up sats_in_view
|
||||
|
||||
@ -330,12 +332,12 @@ esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::Commandabl
|
||||
return esp_modem::command_result::OK;
|
||||
}
|
||||
|
||||
esp_modem::command_result SIM7070_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps)
|
||||
esp_modem::command_result SIM7070_gnss::get_gnss_information_sim70xx(sim70xx_gps_t &gps)
|
||||
{
|
||||
return get_gnss_information_sim70xx_lib(dte.get(), gps);
|
||||
}
|
||||
|
||||
esp_modem::command_result DCE_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps)
|
||||
esp_modem::command_result DCE_gnss::get_gnss_information_sim70xx(sim70xx_gps_t &gps)
|
||||
{
|
||||
return device->get_gnss_information_sim70xx(gps);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "cxx_include/esp_modem_dce_factory.hpp"
|
||||
#include "cxx_include/esp_modem_dce_module.hpp"
|
||||
#include "nmea_parser.h"
|
||||
#include "sim70xx_gps.h"
|
||||
|
||||
/**
|
||||
* @brief Definition of a custom SIM7070 class with GNSS capabilities.
|
||||
@ -23,7 +23,7 @@
|
||||
class SIM7070_gnss: public esp_modem::SIM7070 {
|
||||
using SIM7070::SIM7070;
|
||||
public:
|
||||
esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps);
|
||||
esp_modem::command_result get_gnss_information_sim70xx(sim70xx_gps_t &gps);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -47,7 +47,7 @@ public:
|
||||
|
||||
#undef ESP_MODEM_DECLARE_DCE_COMMAND
|
||||
|
||||
esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps);
|
||||
esp_modem::command_result get_gnss_information_sim70xx(sim70xx_gps_t &gps);
|
||||
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user