mirror of
https://github.com/micropython/micropython.git
synced 2025-08-17 08:00:36 +02:00
Compare commits
310 Commits
v1.21.0
...
v1.22-rele
Author | SHA1 | Date | |
---|---|---|---|
|
8cd15829e2 | ||
|
ee3c9ccb54 | ||
|
e72d03855e | ||
|
02df2b09d4 | ||
|
e7ff724a87 | ||
|
cc7cfc7e8d | ||
|
b979c5a92a | ||
|
f53ee9f12b | ||
|
2531a15200 | ||
|
8b6e89a8ca | ||
|
a2e9ab362b | ||
|
1e8cc6c503 | ||
|
4c7d955a62 | ||
|
068aa28fc5 | ||
|
d5f3fcd935 | ||
|
9b8c64c9ce | ||
|
ac5e0b9f62 | ||
|
61b8361f5f | ||
|
4b4f6011e8 | ||
|
9feb0689ee | ||
|
d014c82826 | ||
|
0b2676db5c | ||
|
cfc212b108 | ||
|
e4d3ab3304 | ||
|
d69e69adb6 | ||
|
ce42c9ee16 | ||
|
3bca93b2d0 | ||
|
91ee8ac894 | ||
|
5d28bb4adb | ||
|
5552896ca8 | ||
|
b31eef6094 | ||
|
74fd7b3d32 | ||
|
8b24aa36ba | ||
|
e9bcd49b3e | ||
|
49d0c22b11 | ||
|
859f219690 | ||
|
7cf1118831 | ||
|
f46269a1d1 | ||
|
f6d630877c | ||
|
97b13132b1 | ||
|
3270d856fd | ||
|
c51081c604 | ||
|
fbf079d773 | ||
|
a78ec4ef7b | ||
|
1f2ec4583d | ||
|
395886caa3 | ||
|
0e706a62b1 | ||
|
2e101a8e44 | ||
|
06df3b2925 | ||
|
de3e83aa4d | ||
|
be64641210 | ||
|
d506b53377 | ||
|
f22e88611d | ||
|
0d93392f10 | ||
|
85c02166ca | ||
|
05d3b22301 | ||
|
bfd6ad94ff | ||
|
f33dfb966a | ||
|
bba8a673d5 | ||
|
ef996d15b9 | ||
|
c9eb6bc601 | ||
|
58e75264c1 | ||
|
f3f215e9bd | ||
|
4365edb810 | ||
|
d0758d8a33 | ||
|
b4b77c17b5 | ||
|
3069fee386 | ||
|
a427117d03 | ||
|
e423b3c0ba | ||
|
495be71d56 | ||
|
3106ee4885 | ||
|
88778be73a | ||
|
c393cd7e48 | ||
|
e1a7aa23fd | ||
|
241dbac928 | ||
|
2c828a8815 | ||
|
73879734d9 | ||
|
c393f5c123 | ||
|
393938b3e6 | ||
|
28529351ae | ||
|
df3948d3c2 | ||
|
f5be0128e4 | ||
|
66be82da7c | ||
|
0960d64d3b | ||
|
50f31cc902 | ||
|
d30d5c99af | ||
|
b796f1e3f1 | ||
|
3f2c423686 | ||
|
1323a71823 | ||
|
78b3fe5689 | ||
|
d3595fed2b | ||
|
69089a532e | ||
|
527c4b0497 | ||
|
731a1f5233 | ||
|
b6df8f8452 | ||
|
9f620d2819 | ||
|
58112fc49a | ||
|
f3889db265 | ||
|
20af857f52 | ||
|
d422b68d10 | ||
|
30b0ee34d3 | ||
|
b5449b0f09 | ||
|
20ffbe1a41 | ||
|
ad806df857 | ||
|
bfdf500ea5 | ||
|
7d784e5385 | ||
|
7a6489aaa5 | ||
|
49fa3ce65d | ||
|
1c0e4644c7 | ||
|
22d9116c8c | ||
|
e3c4c32c64 | ||
|
cc8fc450a6 | ||
|
39d4153a8d | ||
|
4bf7987f0a | ||
|
f523b86541 | ||
|
e1ec6af654 | ||
|
48b5a7b060 | ||
|
e68aa40d2a | ||
|
30a63a204d | ||
|
7d39db2503 | ||
|
14432b5da0 | ||
|
7b2f13fb69 | ||
|
e120c00c95 | ||
|
b4d288ae44 | ||
|
911662cc10 | ||
|
c554df57f6 | ||
|
6ba57f760c | ||
|
e182f3862e | ||
|
12ef8a5ba2 | ||
|
fc94399ffe | ||
|
633c604722 | ||
|
c9a9b2e682 | ||
|
516cc280e0 | ||
|
9c7067d9ad | ||
|
cfcd0c4022 | ||
|
992cd64555 | ||
|
094b52b8ad | ||
|
d6154925d5 | ||
|
960eef70e8 | ||
|
92f0469711 | ||
|
f72a7dde18 | ||
|
a85c3c45a6 | ||
|
a800ed5ae3 | ||
|
917b56137f | ||
|
f397a3ec31 | ||
|
fce8d9fd55 | ||
|
57cce79a46 | ||
|
6117aa686f | ||
|
6f0193335a | ||
|
a968888f69 | ||
|
92741a3438 | ||
|
c34941109f | ||
|
0cc100be2c | ||
|
70feb123bf | ||
|
36e162f116 | ||
|
a23dbdca79 | ||
|
1879db7105 | ||
|
37c1c5fa49 | ||
|
8b1980ad45 | ||
|
f567a9255a | ||
|
5e3f0e7f85 | ||
|
033361da4a | ||
|
a00c9d56db | ||
|
d46dc5e173 | ||
|
365913953a | ||
|
3b954698fa | ||
|
af52e1ff24 | ||
|
2888c5b230 | ||
|
fbb7c32040 | ||
|
f07f90f1ab | ||
|
4679a90097 | ||
|
26d5032980 | ||
|
bcbdee2357 | ||
|
2d363a23cb | ||
|
bbc5a18d09 | ||
|
4cf741062b | ||
|
dff293840e | ||
|
958c6d917d | ||
|
03eae48847 | ||
|
4212799fd8 | ||
|
9be0623d4c | ||
|
bea6ff82fa | ||
|
c35cc63366 | ||
|
59afeb056a | ||
|
2c1f238205 | ||
|
6866d17d8f | ||
|
47ed06bda2 | ||
|
e63d7189bc | ||
|
ae3b1cfab1 | ||
|
09c9c8ac30 | ||
|
c028f956fc | ||
|
841422817e | ||
|
8c432ea2d4 | ||
|
b41055a5a3 | ||
|
d95f5aa011 | ||
|
47ea831c0e | ||
|
e5014a4d79 | ||
|
b6a9778484 | ||
|
c85db05244 | ||
|
9a4d4db3a1 | ||
|
6ef9b29f88 | ||
|
1f804e03f6 | ||
|
c0b64a3f23 | ||
|
4d568a5bd7 | ||
|
ff6c2adfd7 | ||
|
724ebb9916 | ||
|
b4236c7368 | ||
|
286b1b3ed9 | ||
|
98dff07bb4 | ||
|
4bd6ec9ae4 | ||
|
b0aec6a0ff | ||
|
9cabee8252 | ||
|
1ee5731122 | ||
|
59f3c7facb | ||
|
cb37b7bba7 | ||
|
df28aa1a59 | ||
|
3f99dbd634 | ||
|
fc54d25a45 | ||
|
c3c7c602da | ||
|
2eda513870 | ||
|
aa329d11ea | ||
|
bbd8760bd9 | ||
|
303ccca7c6 | ||
|
7ad84e0422 | ||
|
06a7bf967c | ||
|
d8a263435f | ||
|
95ce61d0ad | ||
|
4cffa848f6 | ||
|
a614c1d501 | ||
|
e579ebb11b | ||
|
a8dd69f206 | ||
|
bbbd484f5b | ||
|
9c244134fb | ||
|
c4e63ace66 | ||
|
b2f220dff8 | ||
|
a1d20e0747 | ||
|
f1d6af9819 | ||
|
e676edac79 | ||
|
f74131134c | ||
|
1cf3085c57 | ||
|
c146017f8a | ||
|
bdae847082 | ||
|
64c79a5423 | ||
|
e910533012 | ||
|
78f4f30cb1 | ||
|
1a017511d0 | ||
|
2fda94c286 | ||
|
b6c369a396 | ||
|
6cd99910cd | ||
|
3bf70f16e9 | ||
|
3e2706a18d | ||
|
6989aba93b | ||
|
d336c1b79b | ||
|
90023b4dcf | ||
|
5b4a2baff6 | ||
|
95d8b5fd55 | ||
|
48e0986666 | ||
|
bb4be837c3 | ||
|
91a3f18391 | ||
|
46ae3b5a34 | ||
|
676f9bb78c | ||
|
1477986815 | ||
|
cdd9ad8d62 | ||
|
a2d7e0da0b | ||
|
f2f3ef162d | ||
|
7e7af71527 | ||
|
60929ec7e2 | ||
|
2590a34ed7 | ||
|
5e52389f99 | ||
|
4358faab0c | ||
|
7bbf7910fe | ||
|
9ed39553f2 | ||
|
7be16e0540 | ||
|
be28829ae8 | ||
|
0c4fb16871 | ||
|
5f7065f57a | ||
|
e3ba6f952b | ||
|
86c7b957a8 | ||
|
3883f29485 | ||
|
e78471416b | ||
|
433158076f | ||
|
64ad676424 | ||
|
c2361328e1 | ||
|
971f1cf987 | ||
|
e15882ad2b | ||
|
51da8cc28b | ||
|
8b12923da2 | ||
|
f84b4617cb | ||
|
4074f828dd | ||
|
ac4f79592b | ||
|
8eb7721b4a | ||
|
03a9fa227d | ||
|
d040478d8a | ||
|
a1be5e1439 | ||
|
6967ff3c58 | ||
|
9b63421fb3 | ||
|
9c7ea9b14a | ||
|
516385c4cc | ||
|
66c62353ce | ||
|
4f5e165d0b | ||
|
5f0bd33b73 | ||
|
05cb1406ad | ||
|
5015779a6f | ||
|
480659b1ac | ||
|
d2a9d70c09 | ||
|
9f835df35e | ||
|
a06f4c8df4 | ||
|
3fb1bb131f | ||
|
5232847771 | ||
|
69e34b6b6b |
@@ -1,3 +1,6 @@
|
||||
# all: Update Python formatting to ruff-format.
|
||||
bbd8760bd9a2302e5abee29db279102bb11d7732
|
||||
|
||||
# all: Fix various spelling mistakes found by codespell 2.2.6.
|
||||
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7
|
||||
|
||||
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -8,10 +8,12 @@
|
||||
|
||||
# These are binary so should never be modified by git.
|
||||
*.a binary
|
||||
*.ico binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.dxf binary
|
||||
*.mpy binary
|
||||
*.der binary
|
||||
|
||||
# These should also not be modified by git.
|
||||
tests/basics/string_cr_conversion.py -text
|
||||
|
8
.github/workflows/code_formatting.yml
vendored
8
.github/workflows/code_formatting.yml
vendored
@@ -11,11 +11,11 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_code_formatting_setup
|
||||
run: source tools/ci.sh && ci_c_code_formatting_setup
|
||||
- name: Run code formatting
|
||||
run: source tools/ci.sh && ci_code_formatting_run
|
||||
run: source tools/ci.sh && ci_c_code_formatting_run
|
||||
- name: Check code formatting
|
||||
run: git diff --exit-code
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_code_spell_setup
|
||||
- name: Run spell checker
|
||||
|
2
.github/workflows/code_size.yml
vendored
2
.github/workflows/code_size.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
run: echo $PR_NUMBER > pr_number
|
||||
- name: Upload diff
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: code-size-report
|
||||
path: |
|
||||
|
4
.github/workflows/code_size_comment.yml
vendored
4
.github/workflows/code_size_comment.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- name: 'Download artifact'
|
||||
id: download-artifact
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: unzip code-size-report.zip
|
||||
- name: Post comment to pull request
|
||||
if: steps.download-artifact.outputs.result == 'ok'
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
|
2
.github/workflows/commit_formatting.yml
vendored
2
.github/workflows/commit_formatting.yml
vendored
@@ -13,6 +13,6 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: '100'
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Check commit message formatting
|
||||
run: source tools/ci.sh && ci_commit_formatting_run
|
||||
|
3
.github/workflows/docs.yml
vendored
3
.github/workflows/docs.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Build docs
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
@@ -15,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install Python packages
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: Build docs
|
||||
|
4
.github/workflows/mpremote.yml
vendored
4
.github/workflows/mpremote.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
# Setting this to zero means fetch all history and tags,
|
||||
# which hatch-vcs can use to discover the version tag.
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install build tools
|
||||
run: pip install build
|
||||
- name: Build mpremote wheel
|
||||
run: cd tools/mpremote && python -m build --wheel
|
||||
- name: Archive mpremote wheel
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mpremote
|
||||
path: |
|
||||
|
39
.github/workflows/ports_esp32.yml
vendored
39
.github/workflows/ports_esp32.yml
vendored
@@ -18,11 +18,40 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_idf50:
|
||||
build_idf:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- esp32_build_cmod_spiram_s2
|
||||
- esp32_build_s3_c3
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_esp32_idf50_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_esp32_build
|
||||
|
||||
- id: idf_ver
|
||||
name: Read the ESP-IDF version
|
||||
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cached ESP-IDF install
|
||||
id: cache_esp_idf
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./esp-idf/
|
||||
~/.espressif/
|
||||
!~/.espressif/dist/
|
||||
~/.cache/pip/
|
||||
key: esp-idf-${{ steps.idf_ver.outputs.IDF_VER }}
|
||||
|
||||
- name: Install ESP-IDF packages
|
||||
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
|
||||
run: source tools/ci.sh && ci_esp32_idf_setup
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: esp32-${{ matrix.ci_func }}
|
||||
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
||||
|
20
.github/workflows/ports_stm32.yml
vendored
20
.github/workflows/ports_stm32.yml
vendored
@@ -18,20 +18,18 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_pyb:
|
||||
build_stm32:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- stm32_pyb_build
|
||||
- stm32_nucleo_build
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_stm32_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_stm32_pyb_build
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
||||
|
||||
build_nucleo:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_stm32_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_stm32_nucleo_build
|
||||
|
28
.github/workflows/ports_teensy.yml
vendored
28
.github/workflows/ports_teensy.yml
vendored
@@ -1,28 +0,0 @@
|
||||
name: teensy port
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'tools/**'
|
||||
- 'py/**'
|
||||
- 'extmod/**'
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/teensy/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_teensy_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_teensy_build
|
14
.github/workflows/ports_unix.yml
vendored
14
.github/workflows/ports_unix.yml
vendored
@@ -55,6 +55,18 @@ jobs:
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
standard_v2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -184,7 +196,7 @@ jobs:
|
||||
runs-on: macos-11.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.8'
|
||||
- name: Build
|
||||
|
7
.github/workflows/ruff.yml
vendored
7
.github/workflows/ruff.yml
vendored
@@ -1,10 +1,11 @@
|
||||
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
||||
name: Python code lint with ruff
|
||||
name: Python code lint and formatting with ruff
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
ruff:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: pip install --user ruff
|
||||
- run: ruff --format=github .
|
||||
- run: pip install --user ruff==0.1.3
|
||||
- run: ruff check --output-format=github .
|
||||
- run: ruff format --diff .
|
||||
|
@@ -2,8 +2,8 @@ repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: codeformat
|
||||
name: MicroPython codeformat.py for changed files
|
||||
entry: tools/codeformat.py -v -f
|
||||
name: MicroPython codeformat.py for changed C files
|
||||
entry: tools/codeformat.py -v -c -f
|
||||
language: python
|
||||
- id: verifygitlog
|
||||
name: MicroPython git commit message format checker
|
||||
@@ -12,6 +12,7 @@ repos:
|
||||
verbose: true
|
||||
stages: [commit-msg]
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.265
|
||||
rev: v0.1.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-format
|
||||
|
@@ -53,13 +53,16 @@ are then certifying and signing off against the following:
|
||||
Code auto-formatting
|
||||
====================
|
||||
|
||||
Both C and Python code are auto-formatted using the `tools/codeformat.py`
|
||||
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
|
||||
format C code and [black](https://github.com/psf/black) to format Python code.
|
||||
After making changes, and before committing, run this tool to reformat your
|
||||
changes to the correct style. Without arguments this tool will reformat all
|
||||
source code (and may take some time to run). Otherwise pass as arguments to
|
||||
the tool the files that changed and it will only reformat those.
|
||||
Both C and Python code formatting are controlled for consistency across the
|
||||
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
|
||||
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
|
||||
Python code is linted and formatted using
|
||||
[ruff & ruff format](https://github.com/astral-sh/ruff).
|
||||
After making changes, and before committing, run `tools/codeformat.py` to
|
||||
reformat your C code and `ruff format` for any Python code. Without
|
||||
arguments this tool will reformat all source code (and may take some time
|
||||
to run). Otherwise pass as arguments to the tool the files that changed,
|
||||
and it will only reformat those.
|
||||
|
||||
uncrustify
|
||||
==========
|
||||
@@ -151,12 +154,22 @@ Tips:
|
||||
* To ignore the pre-commit message format check temporarily, start the commit
|
||||
message subject line with "WIP" (for "Work In Progress").
|
||||
|
||||
Running pre-commit manually
|
||||
===========================
|
||||
|
||||
Once pre-commit is installed as per the previous section it can be manually
|
||||
run against the MicroPython python codebase to update file formatting on
|
||||
demand, with either:
|
||||
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
|
||||
* `pre-commit run --file ./path/to/my/file` to fix just one file
|
||||
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
|
||||
|
||||
Python code conventions
|
||||
=======================
|
||||
|
||||
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
|
||||
is auto-formatted using [black](https://github.com/psf/black) with a line-length
|
||||
of 99 characters.
|
||||
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
|
||||
with a line-length of 99 characters.
|
||||
|
||||
Naming conventions:
|
||||
- Module names are short and all lowercase; eg pyb, stm.
|
||||
|
4
LICENSE
4
LICENSE
@@ -69,6 +69,8 @@ used during the build process and is not part of the compiled source code.
|
||||
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
|
||||
/esp32
|
||||
/ppp_set_auth.* (Apache-2.0)
|
||||
/rp2
|
||||
/mutex_extra.c (BSD-3-clause)
|
||||
/stm32
|
||||
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
|
||||
/stm32_it.* (MIT + BSD-3-clause)
|
||||
@@ -78,8 +80,6 @@ used during the build process and is not part of the compiled source code.
|
||||
/*/stm32*.h (BSD-3-clause)
|
||||
/usbdev (MCD-ST Liberty SW License Agreement V2)
|
||||
/usbhost (MCD-ST Liberty SW License Agreement V2)
|
||||
/teensy
|
||||
/core (PJRC.COM)
|
||||
/zephyr
|
||||
/src (Apache-2.0)
|
||||
/tools
|
||||
|
@@ -1,4 +1,4 @@
|
||||
[](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [](https://codecov.io/gh/micropython/micropython)
|
||||
[](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [](https://docs.micropython.org/) [](https://codecov.io/gh/micropython/micropython)
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
@@ -119,7 +119,6 @@ In addition, the following ports are provided in this repository:
|
||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
||||
- [teensy](ports/teensy) -- Teensy 3.x.
|
||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
||||
|
||||
|
195
docs/conf.py
195
docs/conf.py
@@ -19,56 +19,56 @@ import os
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
sys.path.insert(0, os.path.abspath("."))
|
||||
|
||||
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
|
||||
micropy_version = os.getenv("MICROPY_VERSION") or "latest"
|
||||
micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",")
|
||||
url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",)
|
||||
|
||||
# The members of the html_context dict are available inside topindex.html
|
||||
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
|
||||
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
|
||||
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
|
||||
html_context = {
|
||||
'cur_version':micropy_version,
|
||||
'all_versions':[
|
||||
(ver, url_pattern % ver) for ver in micropy_all_versions
|
||||
"cur_version": micropy_version,
|
||||
"all_versions": [(ver, url_pattern % ver) for ver in micropy_all_versions],
|
||||
"downloads": [
|
||||
("PDF", url_pattern % micropy_version + "/micropython-docs.pdf"),
|
||||
],
|
||||
'downloads':[
|
||||
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'),
|
||||
],
|
||||
'is_release': micropy_version != 'latest',
|
||||
"is_release": micropy_version != "latest",
|
||||
}
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinxcontrib.jquery',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinxcontrib.jquery",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates']
|
||||
templates_path = ["templates"]
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = 'MicroPython'
|
||||
copyright = '- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors'
|
||||
project = "MicroPython"
|
||||
copyright = "- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -80,41 +80,41 @@ version = release = micropy_version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['build', '.venv']
|
||||
exclude_patterns = ["build", ".venv"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
default_role = 'any'
|
||||
default_role = "any"
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
# keep_warnings = False
|
||||
|
||||
# Global include files. Sphinx docs suggest using rst_epilog in preference
|
||||
# of rst_prolog, so we follow. Absolute paths below mean "from the base
|
||||
@@ -126,144 +126,148 @@ rst_epilog = """
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# on_rtd is whether we are on readthedocs.org
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
html_theme = "default"
|
||||
html_theme_path = ["."]
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
html_theme_path = ["."]
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = ['.']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = '../../logo/trans-logo.png'
|
||||
# html_logo = '../../logo/trans-logo.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
html_favicon = 'static/favicon.ico'
|
||||
html_favicon = "static/favicon.ico"
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['static']
|
||||
html_static_path = ["static"]
|
||||
|
||||
# Add a custom CSS file for HTML generation
|
||||
html_css_files = [
|
||||
'custom.css',
|
||||
"custom.css",
|
||||
]
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
# html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%d %b %Y'
|
||||
html_last_updated_fmt = "%d %b %Y"
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
html_additional_pages = {"index": "topindex.html"}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'MicroPythondoc'
|
||||
htmlhelp_basename = "MicroPythondoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Include 3 levels of headers in PDF ToC
|
||||
'preamble': r'\setcounter{tocdepth}{2}',
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# Include 3 levels of headers in PDF ToC
|
||||
"preamble": r"\setcounter{tocdepth}{2}",
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
|
||||
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
|
||||
(
|
||||
master_doc,
|
||||
"MicroPython.tex",
|
||||
"MicroPython Documentation",
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
# latex_domain_indices = True
|
||||
|
||||
# Enable better Unicode support so that `make latexpdf` doesn't fail
|
||||
latex_engine = "xelatex"
|
||||
@@ -273,12 +277,17 @@ latex_engine = "xelatex"
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'micropython', 'MicroPython Documentation',
|
||||
['Damien P. George, Paul Sokolovsky, and contributors'], 1),
|
||||
(
|
||||
"index",
|
||||
"micropython",
|
||||
"MicroPython Documentation",
|
||||
["Damien P. George, Paul Sokolovsky, and contributors"],
|
||||
1,
|
||||
),
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
@@ -287,23 +296,29 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'MicroPython', 'MicroPython Documentation',
|
||||
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"MicroPython",
|
||||
"MicroPython Documentation",
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"MicroPython",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
# texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)}
|
||||
intersphinx_mapping = {"python": ("https://docs.python.org/3.5", None)}
|
||||
|
@@ -141,7 +141,7 @@ These are working configurations for LAN interfaces of popular boards::
|
||||
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
|
||||
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
|
||||
|
||||
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
|
||||
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
|
||||
phy_type=network.PHY_LAN8720, phy_addr=0,
|
||||
ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT)
|
||||
|
||||
@@ -330,6 +330,19 @@ possible at the same frequency.
|
||||
|
||||
See more examples in the :ref:`esp32_pwm` tutorial.
|
||||
|
||||
DAC (digital to analog conversion)
|
||||
----------------------------------
|
||||
|
||||
On the ESP32, DAC functionality is available on pins 25, 26.
|
||||
On the ESP32S2, DAC functionality is available on pins 17, 18.
|
||||
|
||||
Use the DAC::
|
||||
|
||||
from machine import DAC, Pin
|
||||
|
||||
dac = DAC(Pin(25)) # create an DAC object acting on a pin
|
||||
dac.write(128) # set a raw analog value in the range 0-255, 50% now
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
|
||||
|
@@ -201,10 +201,12 @@ class Lock
|
||||
TCP stream connections
|
||||
----------------------
|
||||
|
||||
.. function:: open_connection(host, port)
|
||||
.. function:: open_connection(host, port, ssl=None)
|
||||
|
||||
Open a TCP connection to the given *host* and *port*. The *host* address will be
|
||||
resolved using `socket.getaddrinfo`, which is currently a blocking call.
|
||||
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport;
|
||||
if *ssl* is ``True``, a default context is used.
|
||||
|
||||
Returns a pair of streams: a reader and a writer stream.
|
||||
Will raise a socket-specific ``OSError`` if the host could not be resolved or if
|
||||
@@ -212,12 +214,14 @@ TCP stream connections
|
||||
|
||||
This is a coroutine.
|
||||
|
||||
.. function:: start_server(callback, host, port, backlog=5)
|
||||
.. function:: start_server(callback, host, port, backlog=5, ssl=None)
|
||||
|
||||
Start a TCP server on the given *host* and *port*. The *callback* will be
|
||||
called with incoming, accepted connections, and be passed 2 arguments: reader
|
||||
and writer streams for the connection.
|
||||
|
||||
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport.
|
||||
|
||||
Returns a `Server` object.
|
||||
|
||||
This is a coroutine.
|
||||
|
@@ -62,12 +62,35 @@ Functions
|
||||
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
.. function:: osdebug(level)
|
||||
.. function:: osdebug(uart_no)
|
||||
|
||||
Turn esp os debugging messages on or off.
|
||||
.. note:: This is the ESP8266 form of this function.
|
||||
|
||||
The *level* parameter sets the threshold for the log messages for all esp components.
|
||||
The log levels are defined as constants:
|
||||
Change the level of OS serial debug log messages. On boot,
|
||||
OS serial debug log messages are disabled.
|
||||
|
||||
``uart_no`` is the number of the UART peripheral which should receive
|
||||
OS-level output, or ``None`` to disable OS serial debug log messages.
|
||||
|
||||
.. function:: osdebug(uart_no, [level])
|
||||
:no-index:
|
||||
|
||||
.. note:: This is the ESP32 form of this function.
|
||||
|
||||
Change the level of OS serial debug log messages. On boot, OS
|
||||
serial debug log messages are limited to Error output only.
|
||||
|
||||
The behaviour of this function depends on the arguments passed to it. The
|
||||
following combinations are supported:
|
||||
|
||||
``osdebug(None)`` restores the default OS debug log message level
|
||||
(``LOG_ERROR``).
|
||||
|
||||
``osdebug(0)`` enables all available OS debug log messages (in the
|
||||
default build configuration this is ``LOG_INFO``).
|
||||
|
||||
``osdebug(0, level)`` sets the OS debug log message level to the
|
||||
specified value. The log levels are defined as constants:
|
||||
|
||||
* ``LOG_NONE`` -- No log output
|
||||
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
|
||||
@@ -77,6 +100,15 @@ Functions
|
||||
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
|
||||
which can potentially flood the output
|
||||
|
||||
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
|
||||
MicroPython binary by default, to save size. A custom build with a
|
||||
modified "``sdkconfig``" source file is needed to see any output
|
||||
at these log levels.
|
||||
|
||||
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
|
||||
to prevent communications issues. This means OS level logging is never
|
||||
seen when using ``mpremote run`` and similar tools.
|
||||
|
||||
.. function:: set_native_code_location(start, length)
|
||||
|
||||
**Note**: ESP8266 only
|
||||
|
@@ -193,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
|
||||
define the pulses.
|
||||
|
||||
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
|
||||
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
|
||||
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
|
||||
channels (0-7) and each can have a different clock divider.
|
||||
|
||||
So, in the example above, the 80MHz clock is divided by 8. Thus the
|
||||
@@ -226,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
``100``) and the output level to apply the carrier to (a boolean as per
|
||||
*idle_level*).
|
||||
|
||||
.. method:: RMT.source_freq()
|
||||
.. classmethod:: RMT.source_freq()
|
||||
|
||||
Returns the source clock frequency. Currently the source clock is not
|
||||
configurable so this will always return 80MHz.
|
||||
@@ -264,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
|
||||
specifying individual durations and the output level for each.
|
||||
|
||||
Durations are in integer units of the channel resolution (as described
|
||||
above), between 1 and 32767 units. Output levels are any value that can
|
||||
be converted to a boolean, with ``True`` representing high voltage and
|
||||
``False`` representing low.
|
||||
Durations are in integer units of the channel resolution (as
|
||||
described above), between 1 and ``PULSE_MAX`` units. Output levels
|
||||
are any value that can be converted to a boolean, with ``True``
|
||||
representing high voltage and ``False`` representing low.
|
||||
|
||||
If transmission of an earlier sequence is in progress then this method will
|
||||
block until that transmission is complete before beginning the new sequence.
|
||||
@@ -290,6 +290,13 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
Passing in no argument will not change the channel. This function returns
|
||||
the current channel number.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: RMT.PULSE_MAX
|
||||
|
||||
Maximum integer that can be set for a pulse duration.
|
||||
|
||||
Ultra-Low-Power co-processor
|
||||
----------------------------
|
||||
|
||||
|
@@ -86,16 +86,6 @@ Functions
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: FileIO(...)
|
||||
|
||||
This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: TextIOWrapper(...)
|
||||
|
||||
This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: StringIO([string])
|
||||
.. class:: BytesIO([string])
|
||||
|
||||
|
@@ -39,9 +39,9 @@ Methods
|
||||
Configure the ADC peripheral. *bits* will set the resolution of the
|
||||
conversion process.
|
||||
|
||||
.. method:: ADCBlock.connect(channel)
|
||||
ADCBlock.connect(source)
|
||||
ADCBlock.connect(channel, source)
|
||||
.. method:: ADCBlock.connect(channel, *, ...)
|
||||
ADCBlock.connect(source, *, ...)
|
||||
ADCBlock.connect(channel, source, *, ...)
|
||||
|
||||
Connect up a channel on the ADC peripheral so it is ready for sampling,
|
||||
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
|
||||
@@ -56,3 +56,6 @@ Methods
|
||||
|
||||
If both *channel* and *source* are given then they are connected together
|
||||
and made ready for sampling.
|
||||
|
||||
Any additional keyword arguments are used to configure the returned ADC object,
|
||||
via its :meth:`init <machine.ADC.init>` method.
|
||||
|
@@ -39,6 +39,33 @@ class SSLContext
|
||||
Create a new SSLContext instance. The *protocol* argument must be one of the ``PROTOCOL_*``
|
||||
constants.
|
||||
|
||||
.. method:: SSLContext.load_cert_chain(certfile, keyfile)
|
||||
|
||||
Load a private key and the corresponding certificate. The *certfile* is a string
|
||||
with the file path of the certificate. The *keyfile* is a string with the file path
|
||||
of the private key.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
MicroPython extension: *certfile* and *keyfile* can be bytes objects instead of
|
||||
strings, in which case they are interpreted as the actual certificate/key data.
|
||||
|
||||
.. method:: SSLContext.load_verify_locations(cafile=None, cadata=None)
|
||||
|
||||
Load the CA certificate chain that will validate the peer's certificate.
|
||||
*cafile* is the file path of the CA certificates. *cadata* is a bytes object
|
||||
containing the CA certificates. Only one of these arguments should be provided.
|
||||
|
||||
.. method:: SSLContext.get_ciphers()
|
||||
|
||||
Get a list of enabled ciphers, returned as a list of strings.
|
||||
|
||||
.. method:: SSLContext.set_ciphers(ciphers)
|
||||
|
||||
Set the available ciphers for sockets created with this context. *ciphers* should be
|
||||
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
|
||||
|
||||
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
|
||||
|
||||
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
|
||||
@@ -77,6 +104,12 @@ class SSLContext
|
||||
Set or get the behaviour for verification of peer certificates. Must be one of the
|
||||
``CERT_*`` constants.
|
||||
|
||||
.. note::
|
||||
|
||||
``ssl.CERT_REQUIRED`` requires the device's date/time to be properly set, e.g. using
|
||||
`mpremote rtc --set <mpremote_command_rtc>` or ``ntptime``, and ``server_hostname``
|
||||
must be specified when on the client side.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
|
@@ -28,7 +28,7 @@ MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9
|
||||
MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9
|
||||
MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13
|
||||
Adafruit Metro M7 - D0/D1 D7/D3 A1/A0
|
||||
Olimex RT1010Py - RxD/TxD D5/D6 -
|
||||
Olimex RT1010Py - RxD/TxD D7/D8 D5/D6
|
||||
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
|
||||
================= =========== =========== =========== ===========
|
||||
|
||||
|
@@ -92,9 +92,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
|
||||
|
||||
Available Pins follow the ranges and labelling of the respective board, like:
|
||||
|
||||
- 0-33 for Teensy 4.0,
|
||||
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
|
||||
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
|
||||
- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
|
||||
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
|
||||
|
||||
or the pin names of the Pin.board or Pin.cpu classes.
|
||||
@@ -106,9 +104,9 @@ Notes:
|
||||
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
|
||||
default not connected to the MCU. For details refer to the schematics.
|
||||
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
|
||||
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
|
||||
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
|
||||
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
|
||||
- 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected.
|
||||
- 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
|
||||
- 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected.
|
||||
|
||||
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
|
||||
which can be used to invert a pin. Useful for illuminating active-low LEDs
|
||||
@@ -146,22 +144,22 @@ handling signal groups. ::
|
||||
from machine import Pin, PWM
|
||||
|
||||
# create PWM object from a pin and set the frequency and duty cycle
|
||||
pwm2 = PWM(Pin(2), freq=2000, duty_u16=32768)
|
||||
pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768)
|
||||
pwm2.freq() # get the current frequency
|
||||
pwm2.freq(1000) # set/change the frequency
|
||||
pwm2.duty_u16() # get the current duty cycle, range 0-65535
|
||||
pwm2.duty_u16(200) # set the duty cycle, range 0-65535
|
||||
pwm2.deinit() # turn off PWM on the pin
|
||||
# create a complementary signal pair on Pin 2 and 3
|
||||
pwm2 = PWM((2, 3), freq=2000, duty_ns=20000)
|
||||
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
|
||||
|
||||
# Create a group of four synchronized signals.
|
||||
# Start with Pin(4) at submodule 0, which creates the sync pulse.
|
||||
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
|
||||
# Pins 5, 6, and 9 are pins at the same module
|
||||
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
|
||||
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
|
||||
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
|
||||
# Start with Pin('D4') at submodule 0, which creates the sync pulse.
|
||||
pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD)
|
||||
# Pins D5, D6, and D9 are pins at the same module
|
||||
pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
|
||||
pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
|
||||
pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
|
||||
|
||||
pwm3 # show the PWM objects properties
|
||||
|
||||
@@ -256,7 +254,7 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
|
||||
|
||||
from machine import ADC
|
||||
|
||||
adc = ADC(Pin(32)) # create ADC object on ADC pin
|
||||
adc = ADC(Pin('A2')) # create ADC object on ADC pin
|
||||
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
|
||||
|
||||
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
|
||||
@@ -274,7 +272,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the
|
||||
# construct a SoftSPI bus on the given pins
|
||||
# polarity is the idle state of SCK
|
||||
# phase=0 means sample on the first edge of SCK, phase=1 means the second
|
||||
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4'))
|
||||
|
||||
spi.init(baudrate=200000) # set the baudrate
|
||||
|
||||
@@ -303,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
|
||||
from machine import SPI, Pin
|
||||
|
||||
spi = SPI(0, 10000000)
|
||||
cs_pin = Pin(6, Pin.OUT, value=1)
|
||||
cs_pin = Pin('D6', Pin.OUT, value=1)
|
||||
cs_pin(0)
|
||||
spi.write('Hello World')
|
||||
cs_pin(1)
|
||||
@@ -331,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
|
||||
|
||||
from machine import Pin, SoftI2C
|
||||
|
||||
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
|
||||
i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000)
|
||||
|
||||
i2c.scan() # scan for devices
|
||||
|
||||
@@ -365,7 +363,7 @@ See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a si
|
||||
external Codec like UDA1334.::
|
||||
|
||||
from machine import I2S, Pin
|
||||
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
|
||||
i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'),
|
||||
mode=I2S.TX, bts=16,format=I2S.STEREO,
|
||||
rate=44100,ibuf=40000)
|
||||
i2s.write(buf) # write buffer of audio samples to I2S device
|
||||
@@ -397,7 +395,7 @@ Example using the Teensy audio shield::
|
||||
|
||||
from machine import I2C, I2S, Pin
|
||||
from sgtl5000 import CODEC
|
||||
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
|
||||
i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'),
|
||||
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
|
||||
ibuf=40000,
|
||||
)
|
||||
@@ -475,7 +473,7 @@ The OneWire driver is implemented in software and works on all pins::
|
||||
from machine import Pin
|
||||
import onewire
|
||||
|
||||
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
|
||||
ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12
|
||||
ow.scan() # return a list of devices on the bus
|
||||
ow.reset() # reset the bus
|
||||
ow.readbyte() # read a byte
|
||||
@@ -505,12 +503,12 @@ The DHT driver is implemented in software and works on all pins::
|
||||
import dht
|
||||
import machine
|
||||
|
||||
d = dht.DHT11(machine.Pin(4))
|
||||
d = dht.DHT11(machine.Pin('D4'))
|
||||
d.measure()
|
||||
d.temperature() # eg. 23 (°C)
|
||||
d.humidity() # eg. 41 (% RH)
|
||||
|
||||
d = dht.DHT22(machine.Pin(4))
|
||||
d = dht.DHT22(machine.Pin('D4'))
|
||||
d.measure()
|
||||
d.temperature() # eg. 23.6 (°C)
|
||||
d.humidity() # eg. 41.3 (% RH)
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import os
|
||||
|
||||
# Directory that the project lives in, aka ../..
|
||||
SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2])
|
||||
SITE_ROOT = "/".join(os.path.dirname(__file__).split("/")[0:-2])
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
"%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it.
|
||||
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
|
||||
"%s/templates/"
|
||||
% SITE_ROOT, # Your custom template directory, before the RTD one to override it.
|
||||
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
|
||||
)
|
||||
|
@@ -31,3 +31,4 @@ implementation and the best practices to use them.
|
||||
asm_thumb2_index.rst
|
||||
filesystem.rst
|
||||
pyboard.py.rst
|
||||
micropython2_migration.rst
|
||||
|
74
docs/reference/micropython2_migration.rst
Normal file
74
docs/reference/micropython2_migration.rst
Normal file
@@ -0,0 +1,74 @@
|
||||
.. _micropython2_migration:
|
||||
|
||||
MicroPython 2.0 Migration Guide
|
||||
===============================
|
||||
|
||||
MicroPython 2.0 is the (currently in development, not yet available) next major
|
||||
release of MicroPython.
|
||||
|
||||
After maintaining API compatibility for almost a decade with the ``1.x`` series, in
|
||||
order to unblock some project-wide improvements MicroPython 2.0 will introduce a
|
||||
small number of breaking API changes that will require some programs to be
|
||||
updated. This guide explains how to update your Python code to accommodate these
|
||||
changes.
|
||||
|
||||
This document is a work-in-progress. As more work is done on MicroPython 2.0,
|
||||
more items will be added to the lists below.
|
||||
|
||||
**Note:** There are currently no MicroPython 2.0 firmware builds available for
|
||||
download. You can build it yourself by enabling the ``MICROPY_PREVIEW_VERSION_2``
|
||||
config option. As it gets closer to being ready for release, builds will be
|
||||
provided for both ``1.x.y`` and ``2.0.0-preview``.
|
||||
|
||||
Hardware and peripherals
|
||||
------------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The goal is to improve consistency in the :mod:`machine` APIs across different
|
||||
ports, making it easier to write code, documentation, and tutorials that work on
|
||||
any supported microcontroller.
|
||||
|
||||
This means that some ports' APIs need to change to match other ports.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
||||
|
||||
OS & filesystem
|
||||
---------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The primary goal is to support the ability to execute :term:`.mpy files <.mpy
|
||||
file>` directly from the filesystem without first copying them into RAM. This
|
||||
improves code deployment time and reduces memory overhead and fragmentation.
|
||||
|
||||
Additionally, a further goal is to support a more flexible way of configuring
|
||||
partitions, filesystem types, and options like USB mass storage.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
||||
|
||||
CPython compatibility
|
||||
---------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The goal is to improve compatibility with CPython by removing MicroPython
|
||||
extensions from CPython APIs. In most cases this means moving existing
|
||||
MicroPython-specific functions or classes to new modules.
|
||||
|
||||
This makes it easier to write code that works on both CPython and MicroPython,
|
||||
which is useful for development and testing.
|
||||
|
||||
Changes
|
||||
~~~~~~~
|
||||
|
||||
*None yet*
|
@@ -86,7 +86,8 @@ and .mpy version.
|
||||
=================== ============
|
||||
MicroPython release .mpy version
|
||||
=================== ============
|
||||
v1.20 and up 6.1
|
||||
v1.22.0 and up 6.2
|
||||
v1.20 - v1.21.0 6.1
|
||||
v1.19.x 6
|
||||
v1.12 - v1.18 5
|
||||
v1.11 4
|
||||
@@ -101,6 +102,7 @@ MicroPython repository at which the .mpy version was changed.
|
||||
=================== ========================================
|
||||
.mpy version change Git commit
|
||||
=================== ========================================
|
||||
6.1 to 6.2 6967ff3c581a66f73e9f3d78975f47528db39980
|
||||
6 to 6.1 d94141e1473aebae0d3c63aeaa8397651ad6fa01
|
||||
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
|
||||
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517
|
||||
|
@@ -17,44 +17,53 @@ Adafruit ItsyBitsy M0 Express pin assignment table
|
||||
=== ==== ============ ==== ==== ====== ====== ====== ======
|
||||
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
|
||||
=== ==== ============ ==== ==== ====== ====== ====== ======
|
||||
0 PA11 D0 11 19 0/3 2/3 1/1 0/3
|
||||
1 PA10 D1 10 18 0/2 2/2 1/0 0/2
|
||||
2 PA14 D2 14 - 2/2 4/2 3/0 0/4
|
||||
3 PA09 D3 9 17 0/1 2/1 0/1 1/3
|
||||
4 PA08 D4 - 16 0/0 2/0 0/0 1/2
|
||||
5 PA15 D5 15 - 2/3 4/3 3/1 0/5
|
||||
7 PA21 D7 5 - 5/3 3/3 7/1 0/7
|
||||
9 PA07 D9 7 7 - 0/3 1/1 -
|
||||
10 PA18 D10 2 - 1/2 3/2 3/0 0/2
|
||||
11 PA16 D11 0 - 1/0 3/0 2/0 0/6
|
||||
12 PA19 D12 3 - 1/3 3/3 3/1 0/3
|
||||
13 PA17 D13 1 - 1/1 3/1 2/1 0/7
|
||||
14 PA02 A0 2 0 - - - -
|
||||
15 PB08 A1 8 2 - 4/0 4/0 -
|
||||
16 PB09 A2 9 3 - 4/1 4/1 -
|
||||
17 PA04 A3 4 4 - 0/0 0/0 -
|
||||
18 PA05 A4 5 5 - 0/1 0/1 -
|
||||
19 PB02 A5 2 - - 5/0 6/0 -
|
||||
20 PA22 SDA 6 - 3/0 5/0 4/0 0/4
|
||||
21 PA23 SCL 7 - 3/1 5/1 4/1 0/5
|
||||
22 PB10 MOSI 10 - - 4/2 5/0 0/4
|
||||
23 PA12 MISO 12 - 2/0 4/0 2/0 0/6
|
||||
24 PB11 SCK 11 - - 4/3 5/1 0/5
|
||||
25 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
|
||||
26 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
|
||||
27 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
|
||||
28 PB03 FLASH_MISO 3 - - 5/1 6/1 -
|
||||
29 PB23 FLASH_SCK 7 - - 5/3 7/1 -
|
||||
2 PA02 A0 2 0 - - - -
|
||||
40 PB08 A1 8 2 - 4/0 4/0 -
|
||||
41 PB09 A2 9 3 - 4/1 4/1 -
|
||||
4 PA04 A3 4 4 - 0/0 0/0 -
|
||||
5 PA05 A4 5 5 - 0/1 0/1 -
|
||||
34 PB02 A5 2 10 - 5/0 6/0 -
|
||||
11 PA11 D0 11 19 0/3 2/3 1/1 0/3
|
||||
10 PA10 D1 10 18 0/2 2/2 1/0 0/2
|
||||
14 PA14 D2 14 - 2/2 4/2 3/0 0/4
|
||||
9 PA09 D3 9 17 0/1 2/1 0/1 1/3
|
||||
8 PA08 D4 - 16 0/0 2/0 0/0 1/2
|
||||
15 PA15 D5 15 - 2/3 4/3 3/1 0/5
|
||||
21 PA21 D7 5 - 5/3 3/3 7/1 0/7
|
||||
7 PA07 D9 7 7 - 0/3 1/1 -
|
||||
18 PA18 D10 2 - 1/2 3/2 3/0 0/2
|
||||
16 PA16 D11 0 - 1/0 3/0 2/0 0/6
|
||||
19 PA19 D12 3 - 1/3 3/3 3/1 0/3
|
||||
17 PA17 D13 1 - 1/1 3/1 2/1 0/7
|
||||
0 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
|
||||
1 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
|
||||
27 PA27 FLASH_CS 15 - - - - -
|
||||
35 PB03 FLASH_MISO 3 11 - 5/1 6/1 -
|
||||
54 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
|
||||
55 PB23 FLASH_SCK 7 - - 5/3 7/1 -
|
||||
12 PA12 MISO 12 - 2/0 4/0 2/0 0/6
|
||||
42 PB10 MOSI 10 - - 4/2 5/0 0/4
|
||||
43 PB11 SCK 11 - - 4/3 5/1 0/5
|
||||
23 PA23 SCL 7 - 3/1 5/1 4/1 0/5
|
||||
22 PA22 SDA 6 - 3/0 5/0 4/0 0/4
|
||||
30 PA30 SWCLK 10 - - 1/2 1/0 -
|
||||
31 PA31 SWDIO 11 - - 1/3 1/1 -
|
||||
24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2
|
||||
25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3
|
||||
3 PA03 3 1 - - - -
|
||||
6 PA06 6 6 - 0/2 1/0 -
|
||||
13 PA13 13 - 2/1 4/1 2/0 0/7
|
||||
20 PA20 4 - 5/2 3/2 7/0 0/4
|
||||
28 PA28 8 - - - - -
|
||||
=== ==== ============ ==== ==== ====== ====== ====== ======
|
||||
|
||||
|
||||
Description of the columns:
|
||||
|
||||
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
|
||||
as a number. This is NOT the GPIO number, but the board pin number, as
|
||||
given in the board specific definition file.
|
||||
- *GPIO* - The GPIO number.
|
||||
- *Pin Name* - The name of a Pin which is expected argument to ``machine.Pin("name")``.
|
||||
as a number.
|
||||
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
|
||||
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
|
||||
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
|
||||
using ``Pin.irq()``, different pins must use different IRQs
|
||||
- *ADC* - The ADC channel assigned to the pin. When using ADC, different pins must
|
||||
@@ -183,10 +192,9 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
|
||||
Description of the columns:
|
||||
|
||||
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
|
||||
as a number. This is NOT the GPIO number, but the board pin number, as
|
||||
given in the board specific definition file.
|
||||
- *GPIO* - The GPIO number.
|
||||
- *Pin Name* The name of a Pin which is expected argument to ``machine.Pin("name")``.
|
||||
as a number.
|
||||
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
|
||||
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
|
||||
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
|
||||
using ``Pin.irq()``, different pins must use different IRQs
|
||||
- *ADC* - The ADC0/1 channel assigned to the pin. When using ADC, different pins must
|
||||
|
2
docs/templates/layout.html
vendored
2
docs/templates/layout.html
vendored
@@ -9,7 +9,7 @@
|
||||
{% if is_release %}
|
||||
<div class="wy-alert wy-alert-danger">
|
||||
<p>
|
||||
This is the v{{ release }} version of the MicroPython
|
||||
This is the {{ release }} version of the MicroPython
|
||||
documentation. The <a href="/en/latest/{{ pagename }}.html">latest
|
||||
development version</a> of this page may be more current.
|
||||
</p>
|
||||
|
@@ -49,7 +49,7 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
|
||||
#include "uart.h"
|
||||
|
||||
// Provided by the port.
|
||||
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
|
||||
extern machine_uart_obj_t mp_bluetooth_hci_uart_obj;
|
||||
|
||||
STATIC void cywbt_wait_cts_low(void) {
|
||||
mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
|
||||
@@ -68,7 +68,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
|
||||
mp_bluetooth_hci_uart_write((void *)buf, len);
|
||||
for (int c, i = 0; i < 6; ++i) {
|
||||
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
buf[i] = c;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
|
||||
int sz = buf[2] - 3;
|
||||
for (int c, i = 0; i < sz; ++i) {
|
||||
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
buf[i] = c;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#include "drivers/dht/dht.h"
|
||||
|
||||
// Allow the open-drain-high call to be DHT specific for ports that need it
|
||||
|
@@ -34,9 +34,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "mpconfigboard.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#ifdef MICROPY_HW_WIFI_LED
|
||||
#include "led.h"
|
||||
#endif
|
||||
|
@@ -42,9 +42,13 @@
|
||||
|
||||
#define NINA_GPIO_MODE (0x50)
|
||||
#define NINA_GPIO_READ (0x53)
|
||||
#define NINA_GPIO_READ_ANALOG (0x54)
|
||||
#define NINA_GPIO_WRITE (0x51)
|
||||
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 34 && p <= 36) || (p == 39))
|
||||
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 3 && p <= 6))
|
||||
#define NINA_GPIO_IS_ADC_CHANNEL(p) ((p >= 3 && p <= 6))
|
||||
|
||||
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
|
||||
// physical pins on the Nina module.
|
||||
static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
|
||||
27, // LEDR
|
||||
25, // LEDG
|
||||
@@ -55,10 +59,30 @@ static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
|
||||
35, // A7
|
||||
};
|
||||
|
||||
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
|
||||
// ADC channel numbers on the Nina module.
|
||||
static uint8_t adc_map[MICROPY_HW_PIN_EXT_COUNT] = {
|
||||
-1, // LEDR
|
||||
-1, // LEDG
|
||||
-1, // LEDB
|
||||
6, // A4
|
||||
3, // A5
|
||||
0, // A6
|
||||
7, // A7
|
||||
};
|
||||
|
||||
void machine_pin_ext_init(void) {
|
||||
nina_init();
|
||||
}
|
||||
|
||||
bool machine_pin_ext_is_adc_channel(const machine_pin_obj_t *self) {
|
||||
return NINA_GPIO_IS_ADC_CHANNEL(self->id);
|
||||
}
|
||||
|
||||
uint32_t machine_pin_ext_to_adc_channel(const machine_pin_obj_t *self) {
|
||||
return adc_map[self->id];
|
||||
}
|
||||
|
||||
void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
|
||||
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
|
||||
uint8_t buf[] = {pin_map[self->id], value};
|
||||
@@ -76,8 +100,14 @@ bool machine_pin_ext_get(machine_pin_obj_t *self) {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t machine_pin_ext_read_u16(uint32_t channel) {
|
||||
uint16_t buf = channel;
|
||||
nina_ioctl(NINA_GPIO_READ_ANALOG, sizeof(buf), (uint8_t *)&buf, 0);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
|
||||
if (mode == MACHINE_PIN_MODE_IN) {
|
||||
if (mode == MACHINE_PIN_MODE_IN || mode == MACHINE_PIN_MODE_ANALOG) {
|
||||
mode = NINA_GPIO_INPUT;
|
||||
self->is_output = false;
|
||||
} else if (mode == MACHINE_PIN_MODE_OUT) {
|
||||
@@ -89,7 +119,7 @@ void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
|
||||
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
|
||||
uint8_t buf[] = {pin_map[self->id], mode};
|
||||
if (mode == NINA_GPIO_OUTPUT) {
|
||||
if (NINA_GPIO_IS_INPUT_ONLY(buf[0])) {
|
||||
if (NINA_GPIO_IS_INPUT_ONLY(self->id)) {
|
||||
mp_raise_ValueError("only Pin.IN is supported for this pin");
|
||||
}
|
||||
machine_pin_ext_set(self, value);
|
||||
|
@@ -75,12 +75,13 @@ static int nina_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param
|
||||
// Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen).
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) {
|
||||
while (!mp_bluetooth_hci_uart_any()) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_uint_t elapsed = mp_hal_ticks_ms() - start;
|
||||
// Timeout.
|
||||
if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) {
|
||||
if (elapsed > HCI_COMMAND_TIMEOUT) {
|
||||
error_printf("timeout waiting for HCI packet\n");
|
||||
return -1;
|
||||
}
|
||||
mp_event_wait_ms(HCI_COMMAND_TIMEOUT - elapsed);
|
||||
}
|
||||
|
||||
buf[i] = mp_bluetooth_hci_uart_readchar();
|
||||
|
@@ -35,9 +35,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "mpconfigboard.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#include "nina_bsp.h"
|
||||
#include "nina_wifi_drv.h"
|
||||
|
@@ -684,6 +684,14 @@ int nina_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case NINA_CMD_GET_ANALOG_READ: {
|
||||
if (len != 2 || nina_send_command_read_vals(NINA_CMD_GET_ANALOG_READ,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(buf[0])),
|
||||
1, ARG_8BITS, NINA_VALS({(uint16_t *)&len, buf})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@@ -36,7 +36,6 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
|
||||
MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2);
|
||||
|
||||
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
|
||||
mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
|
||||
mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
|
||||
mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
|
||||
mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
|
||||
|
@@ -1,60 +0,0 @@
|
||||
# Print a nice list of pins, their current settings, and available afs.
|
||||
# Requires pins_af.py from ports/stm32/build-PYBV10/ directory.
|
||||
|
||||
import pyb
|
||||
import pins_af
|
||||
|
||||
|
||||
def af():
|
||||
max_name_width = 0
|
||||
max_af_width = 0
|
||||
for pin_entry in pins_af.PINS_AF:
|
||||
max_name_width = max(max_name_width, len(pin_entry[0]))
|
||||
for af_entry in pin_entry[1:]:
|
||||
max_af_width = max(max_af_width, len(af_entry[1]))
|
||||
for pin_entry in pins_af.PINS_AF:
|
||||
pin_name = pin_entry[0]
|
||||
print("%-*s " % (max_name_width, pin_name), end="")
|
||||
for af_entry in pin_entry[1:]:
|
||||
print("%2d: %-*s " % (af_entry[0], max_af_width, af_entry[1]), end="")
|
||||
print("")
|
||||
|
||||
|
||||
def pins():
|
||||
mode_str = {
|
||||
pyb.Pin.IN: "IN",
|
||||
pyb.Pin.OUT_PP: "OUT_PP",
|
||||
pyb.Pin.OUT_OD: "OUT_OD",
|
||||
pyb.Pin.AF_PP: "AF_PP",
|
||||
pyb.Pin.AF_OD: "AF_OD",
|
||||
pyb.Pin.ANALOG: "ANALOG",
|
||||
}
|
||||
pull_str = {pyb.Pin.PULL_NONE: "", pyb.Pin.PULL_UP: "PULL_UP", pyb.Pin.PULL_DOWN: "PULL_DOWN"}
|
||||
width = [0, 0, 0, 0]
|
||||
rows = []
|
||||
for pin_entry in pins_af.PINS_AF:
|
||||
row = []
|
||||
pin_name = pin_entry[0]
|
||||
pin = pyb.Pin(pin_name)
|
||||
pin_mode = pin.mode()
|
||||
row.append(pin_name)
|
||||
row.append(mode_str[pin_mode])
|
||||
row.append(pull_str[pin.pull()])
|
||||
if pin_mode == pyb.Pin.AF_PP or pin_mode == pyb.Pin.AF_OD:
|
||||
pin_af = pin.af()
|
||||
for af_entry in pin_entry[1:]:
|
||||
if pin_af == af_entry[0]:
|
||||
af_str = "%d: %s" % (pin_af, af_entry[1])
|
||||
break
|
||||
else:
|
||||
af_str = "%d" % pin_af
|
||||
else:
|
||||
af_str = ""
|
||||
row.append(af_str)
|
||||
for col in range(len(width)):
|
||||
width[col] = max(width[col], len(row[col]))
|
||||
rows.append(row)
|
||||
for row in rows:
|
||||
for col in range(len(width)):
|
||||
print("%-*s " % (width[col], row[col]), end="")
|
||||
print("")
|
@@ -1,9 +1,16 @@
|
||||
extern "C" {
|
||||
#include <examplemodule.h>
|
||||
#include <py/objstr.h>
|
||||
|
||||
// Here we implement the function using C++ code, but since it's
|
||||
// declaration has to be compatible with C everything goes in extern "C" scope.
|
||||
mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj) {
|
||||
// The following no-ops are just here to verify the static assertions used in
|
||||
// the public API all compile with C++.
|
||||
MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE;
|
||||
if (mp_obj_is_type(a_obj, &mp_type_BaseException)) {
|
||||
}
|
||||
|
||||
// Prove we have (at least) C++11 features.
|
||||
const auto a = mp_obj_get_int(a_obj);
|
||||
const auto b = mp_obj_get_int(b_obj);
|
||||
|
@@ -219,6 +219,11 @@ def run_until_complete(main_task=None):
|
||||
elif t.state is None:
|
||||
# Task is already finished and nothing await'ed on the task,
|
||||
# so call the exception handler.
|
||||
|
||||
# Save exception raised by the coro for later use.
|
||||
t.data = exc
|
||||
|
||||
# Create exception context and call the exception handler.
|
||||
_exc_context["exception"] = exc
|
||||
_exc_context["future"] = t
|
||||
Loop.call_exception_handler(_exc_context)
|
||||
@@ -272,9 +277,9 @@ class Loop:
|
||||
return Loop._exc_handler
|
||||
|
||||
def default_exception_handler(loop, context):
|
||||
print(context["message"])
|
||||
print("future:", context["future"], "coro=", context["future"].coro)
|
||||
sys.print_exception(context["exception"])
|
||||
print(context["message"], file=sys.stderr)
|
||||
print("future:", context["future"], "coro=", context["future"].coro, file=sys.stderr)
|
||||
sys.print_exception(context["exception"], sys.stderr)
|
||||
|
||||
def call_exception_handler(context):
|
||||
(Loop._exc_handler or Loop.default_exception_handler)(Loop, context)
|
||||
|
@@ -63,9 +63,6 @@ class _Remove:
|
||||
|
||||
# async
|
||||
def gather(*aws, return_exceptions=False):
|
||||
if not aws:
|
||||
return []
|
||||
|
||||
def done(t, er):
|
||||
# Sub-task "t" has finished, with exception "er".
|
||||
nonlocal state
|
||||
@@ -86,26 +83,39 @@ def gather(*aws, return_exceptions=False):
|
||||
# Gather waiting is done, schedule the main gather task.
|
||||
core._task_queue.push(gather_task)
|
||||
|
||||
# Prepare the sub-tasks for the gather.
|
||||
# The `state` variable counts the number of tasks to wait for, and can be negative
|
||||
# if the gather should not run at all (because a task already had an exception).
|
||||
ts = [core._promote_to_task(aw) for aw in aws]
|
||||
state = 0
|
||||
for i in range(len(ts)):
|
||||
if ts[i].state is not True:
|
||||
# Task is not running, gather not currently supported for this case.
|
||||
if ts[i].state is True:
|
||||
# Task is running, register the callback to call when the task is done.
|
||||
ts[i].state = done
|
||||
state += 1
|
||||
elif not ts[i].state:
|
||||
# Task finished already.
|
||||
if not isinstance(ts[i].data, StopIteration):
|
||||
# Task finished by raising an exception.
|
||||
if not return_exceptions:
|
||||
# Do not run this gather at all.
|
||||
state = -len(ts)
|
||||
else:
|
||||
# Task being waited on, gather not currently supported for this case.
|
||||
raise RuntimeError("can't gather")
|
||||
# Register the callback to call when the task is done.
|
||||
ts[i].state = done
|
||||
|
||||
# Set the state for execution of the gather.
|
||||
gather_task = core.cur_task
|
||||
state = len(ts)
|
||||
cancel_all = False
|
||||
|
||||
# Wait for the a sub-task to need attention.
|
||||
gather_task.data = _Remove
|
||||
try:
|
||||
yield
|
||||
except core.CancelledError as er:
|
||||
cancel_all = True
|
||||
state = er
|
||||
# Wait for a sub-task to need attention (if there are any to wait for).
|
||||
if state > 0:
|
||||
gather_task.data = _Remove
|
||||
try:
|
||||
yield
|
||||
except core.CancelledError as er:
|
||||
cancel_all = True
|
||||
state = er
|
||||
|
||||
# Clean up tasks.
|
||||
for i in range(len(ts)):
|
||||
@@ -118,8 +128,13 @@ def gather(*aws, return_exceptions=False):
|
||||
# Sub-task ran to completion, get its return value.
|
||||
ts[i] = ts[i].data.value
|
||||
else:
|
||||
# Sub-task had an exception with return_exceptions==True, so get its exception.
|
||||
ts[i] = ts[i].data
|
||||
# Sub-task had an exception.
|
||||
if return_exceptions:
|
||||
# Get the sub-task exception to return in the list of return values.
|
||||
ts[i] = ts[i].data
|
||||
elif isinstance(state, int):
|
||||
# Raise the sub-task exception, if there is not already an exception to raise.
|
||||
state = ts[i].data
|
||||
|
||||
# Either this gather was cancelled, or one of the sub-tasks raised an exception with
|
||||
# return_exceptions==False, so reraise the exception here.
|
||||
|
@@ -13,12 +13,6 @@ class Stream:
|
||||
def get_extra_info(self, v):
|
||||
return self.e[v]
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
await self.close()
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
@@ -63,6 +57,8 @@ class Stream:
|
||||
while True:
|
||||
yield core._io_queue.queue_read(self.s)
|
||||
l2 = self.s.readline() # may do multiple reads but won't block
|
||||
if l2 is None:
|
||||
continue
|
||||
l += l2
|
||||
if not l2 or l[-1] == 10: # \n (check l in case l2 is str)
|
||||
return l
|
||||
@@ -100,19 +96,29 @@ StreamWriter = Stream
|
||||
# Create a TCP stream connection to a remote host
|
||||
#
|
||||
# async
|
||||
def open_connection(host, port):
|
||||
def open_connection(host, port, ssl=None, server_hostname=None):
|
||||
from errno import EINPROGRESS
|
||||
import socket
|
||||
|
||||
ai = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] # TODO this is blocking!
|
||||
s = socket.socket(ai[0], ai[1], ai[2])
|
||||
s.setblocking(False)
|
||||
ss = Stream(s)
|
||||
try:
|
||||
s.connect(ai[-1])
|
||||
except OSError as er:
|
||||
if er.errno != EINPROGRESS:
|
||||
raise er
|
||||
# wrap with SSL, if requested
|
||||
if ssl:
|
||||
if ssl is True:
|
||||
import ssl as _ssl
|
||||
|
||||
ssl = _ssl.SSLContext(_ssl.PROTOCOL_TLS_CLIENT)
|
||||
if not server_hostname:
|
||||
server_hostname = host
|
||||
s = ssl.wrap_socket(s, server_hostname=server_hostname, do_handshake_on_connect=False)
|
||||
s.setblocking(False)
|
||||
ss = Stream(s)
|
||||
yield core._io_queue.queue_write(s)
|
||||
return ss, ss
|
||||
|
||||
@@ -135,7 +141,7 @@ class Server:
|
||||
async def wait_closed(self):
|
||||
await self.task
|
||||
|
||||
async def _serve(self, s, cb):
|
||||
async def _serve(self, s, cb, ssl):
|
||||
self.state = False
|
||||
# Accept incoming connections
|
||||
while True:
|
||||
@@ -156,6 +162,13 @@ class Server:
|
||||
except:
|
||||
# Ignore a failed accept
|
||||
continue
|
||||
if ssl:
|
||||
try:
|
||||
s2 = ssl.wrap_socket(s2, server_side=True, do_handshake_on_connect=False)
|
||||
except OSError as e:
|
||||
core.sys.print_exception(e)
|
||||
s2.close()
|
||||
continue
|
||||
s2.setblocking(False)
|
||||
s2s = Stream(s2, {"peername": addr})
|
||||
core.create_task(cb(s2s, s2s))
|
||||
@@ -163,7 +176,7 @@ class Server:
|
||||
|
||||
# Helper function to start a TCP stream server, running as a new task
|
||||
# TODO could use an accept-callback on socket read activity instead of creating a task
|
||||
async def start_server(cb, host, port, backlog=5):
|
||||
async def start_server(cb, host, port, backlog=5, ssl=None):
|
||||
import socket
|
||||
|
||||
# Create and bind server socket.
|
||||
@@ -176,7 +189,7 @@ async def start_server(cb, host, port, backlog=5):
|
||||
|
||||
# Create and return server object and task.
|
||||
srv = Server()
|
||||
srv.task = core.create_task(srv._serve(s, cb))
|
||||
srv.task = core.create_task(srv._serve(s, cb, ssl))
|
||||
try:
|
||||
# Ensure that the _serve task has been scheduled so that it gets to
|
||||
# handle cancellation.
|
||||
|
@@ -462,8 +462,9 @@ STATIC void btstack_packet_handler_read(uint8_t packet_type, uint16_t channel, u
|
||||
if (!conn) {
|
||||
return;
|
||||
}
|
||||
mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_READ_DONE, conn_handle, conn->pending_value_handle, status);
|
||||
uint16_t value_handle = conn->pending_value_handle;
|
||||
conn->pending_value_handle = 0xffff;
|
||||
mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_READ_DONE, conn_handle, value_handle, status);
|
||||
} else if (event_type == GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT) {
|
||||
DEBUG_printf(" --> gatt characteristic value query result\n");
|
||||
uint16_t conn_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
|
||||
@@ -490,11 +491,12 @@ STATIC void btstack_packet_handler_write_with_response(uint8_t packet_type, uint
|
||||
if (!conn) {
|
||||
return;
|
||||
}
|
||||
mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE, conn_handle, conn->pending_value_handle, status);
|
||||
uint16_t value_handle = conn->pending_value_handle;
|
||||
conn->pending_value_handle = 0xffff;
|
||||
m_del(uint8_t, conn->pending_write_value, conn->pending_write_value_len);
|
||||
conn->pending_write_value = NULL;
|
||||
conn->pending_write_value_len = 0;
|
||||
mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE, conn_handle, value_handle, status);
|
||||
}
|
||||
}
|
||||
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
|
||||
@@ -552,7 +554,7 @@ STATIC void set_random_address(void) {
|
||||
volatile bool ready = false;
|
||||
btstack_crypto_random_generate(&sm_crypto_random_request, static_addr, 6, &btstack_static_address_ready, (void *)&ready);
|
||||
while (!ready) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
|
||||
#endif // MICROPY_BLUETOOTH_USE_MP_HAL_GET_MAC_STATIC_ADDRESS
|
||||
@@ -574,7 +576,7 @@ STATIC void set_random_address(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
DEBUG_printf("set_random_address: Address loaded by controller\n");
|
||||
}
|
||||
@@ -654,7 +656,7 @@ int mp_bluetooth_init(void) {
|
||||
// Either the HCI event will set state to ACTIVE, or the timeout will set it to TIMEOUT.
|
||||
mp_bluetooth_btstack_port_start();
|
||||
while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_STARTING) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
|
||||
|
||||
@@ -727,7 +729,7 @@ void mp_bluetooth_deinit(void) {
|
||||
// either timeout or clean shutdown.
|
||||
mp_bluetooth_btstack_port_deinit();
|
||||
while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
|
||||
|
||||
|
@@ -7,16 +7,22 @@ set(MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_DIR}/shared/libc/abort_.c
|
||||
${MICROPY_DIR}/shared/libc/printf.c
|
||||
${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_adc.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_adc_block.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_i2c.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_i2s.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_mem.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_pulse.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_pwm.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_signal.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_spi.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_uart.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_wdt.c
|
||||
${MICROPY_EXTMOD_DIR}/modbluetooth.c
|
||||
${MICROPY_EXTMOD_DIR}/modframebuf.c
|
||||
${MICROPY_EXTMOD_DIR}/modlwip.c
|
||||
${MICROPY_EXTMOD_DIR}/modmachine.c
|
||||
${MICROPY_EXTMOD_DIR}/modnetwork.c
|
||||
${MICROPY_EXTMOD_DIR}/modonewire.c
|
||||
${MICROPY_EXTMOD_DIR}/modasyncio.c
|
||||
@@ -56,6 +62,41 @@ set(MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_EXTMOD_DIR}/nimble/modbluetooth_nimble.c
|
||||
)
|
||||
|
||||
# Single-precision libm math library.
|
||||
|
||||
set(MICROPY_SOURCE_LIB_LIBM
|
||||
${MICROPY_DIR}/lib/libm/acoshf.c
|
||||
${MICROPY_DIR}/lib/libm/asinfacosf.c
|
||||
${MICROPY_DIR}/lib/libm/asinhf.c
|
||||
${MICROPY_DIR}/lib/libm/atan2f.c
|
||||
${MICROPY_DIR}/lib/libm/atanf.c
|
||||
${MICROPY_DIR}/lib/libm/atanhf.c
|
||||
${MICROPY_DIR}/lib/libm/ef_rem_pio2.c
|
||||
${MICROPY_DIR}/lib/libm/erf_lgamma.c
|
||||
${MICROPY_DIR}/lib/libm/fmodf.c
|
||||
${MICROPY_DIR}/lib/libm/kf_cos.c
|
||||
${MICROPY_DIR}/lib/libm/kf_rem_pio2.c
|
||||
${MICROPY_DIR}/lib/libm/kf_sin.c
|
||||
${MICROPY_DIR}/lib/libm/kf_tan.c
|
||||
${MICROPY_DIR}/lib/libm/log1pf.c
|
||||
${MICROPY_DIR}/lib/libm/math.c
|
||||
${MICROPY_DIR}/lib/libm/nearbyintf.c
|
||||
${MICROPY_DIR}/lib/libm/roundf.c
|
||||
${MICROPY_DIR}/lib/libm/sf_cos.c
|
||||
${MICROPY_DIR}/lib/libm/sf_erf.c
|
||||
${MICROPY_DIR}/lib/libm/sf_frexp.c
|
||||
${MICROPY_DIR}/lib/libm/sf_ldexp.c
|
||||
${MICROPY_DIR}/lib/libm/sf_modf.c
|
||||
${MICROPY_DIR}/lib/libm/sf_sin.c
|
||||
${MICROPY_DIR}/lib/libm/sf_tan.c
|
||||
${MICROPY_DIR}/lib/libm/wf_lgamma.c
|
||||
${MICROPY_DIR}/lib/libm/wf_tgamma.c
|
||||
)
|
||||
|
||||
# Choose only one of these sqrt implementations, software or hardware.
|
||||
set(MICROPY_SOURCE_LIB_LIBM_SQRT_SW ${MICROPY_DIR}/lib/libm/ef_sqrt.c)
|
||||
set(MICROPY_SOURCE_LIB_LIBM_SQRT_HW ${MICROPY_DIR}/lib/libm/thumb_vfp_sqrtf.c)
|
||||
|
||||
# Library for btree module and associated code
|
||||
|
||||
if(MICROPY_PY_BTREE)
|
||||
|
101
extmod/extmod.mk
101
extmod/extmod.mk
@@ -2,8 +2,11 @@
|
||||
# and provides rules to build 3rd-party components for extmod modules.
|
||||
|
||||
SRC_EXTMOD_C += \
|
||||
extmod/machine_adc.c \
|
||||
extmod/machine_adc_block.c \
|
||||
extmod/machine_bitstream.c \
|
||||
extmod/machine_i2c.c \
|
||||
extmod/machine_i2s.c \
|
||||
extmod/machine_mem.c \
|
||||
extmod/machine_pinbase.c \
|
||||
extmod/machine_pulse.c \
|
||||
@@ -11,6 +14,8 @@ SRC_EXTMOD_C += \
|
||||
extmod/machine_signal.c \
|
||||
extmod/machine_spi.c \
|
||||
extmod/machine_timer.c \
|
||||
extmod/machine_uart.c \
|
||||
extmod/machine_wdt.c \
|
||||
extmod/modasyncio.c \
|
||||
extmod/modbinascii.c \
|
||||
extmod/modbluetooth.c \
|
||||
@@ -22,6 +27,7 @@ SRC_EXTMOD_C += \
|
||||
extmod/modheapq.c \
|
||||
extmod/modjson.c \
|
||||
extmod/modlwip.c \
|
||||
extmod/modmachine.c \
|
||||
extmod/modnetwork.c \
|
||||
extmod/modonewire.c \
|
||||
extmod/modos.c \
|
||||
@@ -64,6 +70,96 @@ SRC_QSTR += $(SRC_EXTMOD_C)
|
||||
CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY)
|
||||
LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY)
|
||||
|
||||
################################################################################
|
||||
# libm/libm_dbl math library
|
||||
|
||||
# Single-precision math library.
|
||||
SRC_LIB_LIBM_C += $(addprefix lib/libm/,\
|
||||
acoshf.c \
|
||||
asinfacosf.c \
|
||||
asinhf.c \
|
||||
atan2f.c \
|
||||
atanf.c \
|
||||
atanhf.c \
|
||||
ef_rem_pio2.c \
|
||||
erf_lgamma.c \
|
||||
fmodf.c \
|
||||
kf_cos.c \
|
||||
kf_rem_pio2.c \
|
||||
kf_sin.c \
|
||||
kf_tan.c \
|
||||
log1pf.c \
|
||||
math.c \
|
||||
nearbyintf.c \
|
||||
roundf.c \
|
||||
sf_cos.c \
|
||||
sf_erf.c \
|
||||
sf_frexp.c \
|
||||
sf_ldexp.c \
|
||||
sf_modf.c \
|
||||
sf_sin.c \
|
||||
sf_tan.c \
|
||||
wf_lgamma.c \
|
||||
wf_tgamma.c \
|
||||
)
|
||||
|
||||
# Choose only one of these sqrt implementations, software or hardware.
|
||||
SRC_LIB_LIBM_SQRT_SW_C += lib/libm/ef_sqrt.c
|
||||
SRC_LIB_LIBM_SQRT_HW_C += lib/libm/thumb_vfp_sqrtf.c
|
||||
|
||||
# Double-precision math library.
|
||||
SRC_LIB_LIBM_DBL_C += $(addprefix lib/libm_dbl/,\
|
||||
__cos.c \
|
||||
__expo2.c \
|
||||
__fpclassify.c \
|
||||
__rem_pio2.c \
|
||||
__rem_pio2_large.c \
|
||||
__signbit.c \
|
||||
__sin.c \
|
||||
__tan.c \
|
||||
acos.c \
|
||||
acosh.c \
|
||||
asin.c \
|
||||
asinh.c \
|
||||
atan.c \
|
||||
atan2.c \
|
||||
atanh.c \
|
||||
ceil.c \
|
||||
cos.c \
|
||||
cosh.c \
|
||||
copysign.c \
|
||||
erf.c \
|
||||
exp.c \
|
||||
expm1.c \
|
||||
floor.c \
|
||||
fmod.c \
|
||||
frexp.c \
|
||||
ldexp.c \
|
||||
lgamma.c \
|
||||
log.c \
|
||||
log10.c \
|
||||
log1p.c \
|
||||
modf.c \
|
||||
nearbyint.c \
|
||||
pow.c \
|
||||
rint.c \
|
||||
round.c \
|
||||
scalbn.c \
|
||||
sin.c \
|
||||
sinh.c \
|
||||
tan.c \
|
||||
tanh.c \
|
||||
tgamma.c \
|
||||
trunc.c \
|
||||
)
|
||||
|
||||
# Choose only one of these sqrt implementations, software or hardware.
|
||||
SRC_LIB_LIBM_DBL_SQRT_SW_C += lib/libm_dbl/sqrt.c
|
||||
SRC_LIB_LIBM_DBL_SQRT_HW_C += lib/libm_dbl/thumb_vfp_sqrt.c
|
||||
|
||||
# Too many warnings in libm_dbl, disable for now.
|
||||
$(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion
|
||||
|
||||
################################################################################
|
||||
# VFS FAT FS
|
||||
|
||||
@@ -102,7 +198,7 @@ SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
|
||||
lfs2_util.c \
|
||||
)
|
||||
|
||||
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-missing-field-initializers
|
||||
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-shadow
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
@@ -262,6 +358,9 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
|
||||
core/ipv6/nd6.c \
|
||||
netif/ethernet.c \
|
||||
)
|
||||
ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1)
|
||||
CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1
|
||||
endif
|
||||
ifeq ($(MICROPY_PY_LWIP_SLIP),1)
|
||||
CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1
|
||||
SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c
|
||||
|
183
extmod/machine_adc.c
Normal file
183
extmod/machine_adc.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
// The port must provide implementations of these low-level ADC functions.
|
||||
|
||||
STATIC void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
STATIC mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
STATIC mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self);
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_INIT
|
||||
STATIC void mp_machine_adc_init_helper(machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_DEINIT
|
||||
STATIC void mp_machine_adc_deinit(machine_adc_obj_t *self);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
STATIC mp_obj_t mp_machine_adc_block(machine_adc_obj_t *self);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_READ_UV
|
||||
STATIC mp_int_t mp_machine_adc_read_uv(machine_adc_obj_t *self);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
|
||||
STATIC void mp_machine_adc_atten_set(machine_adc_obj_t *self, mp_int_t atten);
|
||||
STATIC void mp_machine_adc_width_set(machine_adc_obj_t *self, mp_int_t width);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_READ
|
||||
STATIC mp_int_t mp_machine_adc_read(machine_adc_obj_t *self);
|
||||
#endif
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_ADC_INCLUDEFILE
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_INIT
|
||||
// ADC.init(...)
|
||||
STATIC mp_obj_t machine_adc_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_machine_adc_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_init_obj, 1, machine_adc_init);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_DEINIT
|
||||
// ADC.deinit()
|
||||
STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_adc_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
// ADC.block()
|
||||
STATIC mp_obj_t machine_adc_block(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_machine_adc_block(self);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_block_obj, machine_adc_block);
|
||||
#endif
|
||||
|
||||
// ADC.read_u16()
|
||||
STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read_u16(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_READ_UV
|
||||
// ADC.read_uv()
|
||||
STATIC mp_obj_t machine_adc_read_uv(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read_uv(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_uv_obj, machine_adc_read_uv);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
|
||||
|
||||
// ADC.atten(value) -- this is a legacy method.
|
||||
STATIC mp_obj_t machine_adc_atten(mp_obj_t self_in, mp_obj_t atten_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_int_t atten = mp_obj_get_int(atten_in);
|
||||
mp_machine_adc_atten_set(self, atten);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_adc_atten_obj, machine_adc_atten);
|
||||
|
||||
// ADC.width(value) -- this is a legacy method.
|
||||
STATIC mp_obj_t machine_adc_width(mp_obj_t self_in, mp_obj_t width_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_int_t width = mp_obj_get_int(width_in);
|
||||
mp_machine_adc_width_set(self, width);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_adc_width_obj, machine_adc_width);
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_READ
|
||||
// ADC.read() -- this is a legacy method.
|
||||
STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) {
|
||||
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
|
||||
#if MICROPY_PY_MACHINE_ADC_INIT
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_init_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC_DEINIT
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
{ MP_ROM_QSTR(MP_QSTR_block), MP_ROM_PTR(&machine_adc_block_obj) },
|
||||
#endif
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) },
|
||||
#if MICROPY_PY_MACHINE_ADC_READ_UV
|
||||
{ MP_ROM_QSTR(MP_QSTR_read_uv), MP_ROM_PTR(&machine_adc_read_uv_obj) },
|
||||
#endif
|
||||
|
||||
// Legacy methods.
|
||||
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
|
||||
{ MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&machine_adc_atten_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&machine_adc_width_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC_READ
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) },
|
||||
#endif
|
||||
|
||||
// A port must add ADC class constants defining the following macro.
|
||||
// It can be defined to nothing if there are no constants.
|
||||
MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_adc_type,
|
||||
MP_QSTR_ADC,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, mp_machine_adc_make_new,
|
||||
print, mp_machine_adc_print,
|
||||
locals_dict, &machine_adc_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_ADC
|
128
extmod/machine_adc_block.c
Normal file
128
extmod/machine_adc_block.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jonathan Hogg
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
// The port must provide implementations of these low-level ADCBlock functions.
|
||||
STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self);
|
||||
STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit);
|
||||
STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits);
|
||||
STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t pin, mp_map_t *kw_args);
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE
|
||||
|
||||
STATIC void machine_adc_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_adc_block_print(print, self);
|
||||
}
|
||||
|
||||
STATIC void machine_adc_block_init_helper(machine_adc_block_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum {
|
||||
ARG_bits,
|
||||
};
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_int_t bits = args[ARG_bits].u_int;
|
||||
mp_machine_adc_block_bits_set(self, bits);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_block_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
mp_int_t unit = mp_obj_get_int(args[0]);
|
||||
machine_adc_block_obj_t *self = mp_machine_adc_block_get(unit);
|
||||
if (self == NULL) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid block id"));
|
||||
}
|
||||
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
|
||||
machine_adc_block_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_adc_block_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_adc_block_obj_t *self = pos_args[0];
|
||||
machine_adc_block_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_block_init);
|
||||
|
||||
STATIC mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_int_t channel_id = -1;
|
||||
mp_hal_pin_obj_t pin = -1;
|
||||
if (n_pos_args == 2) {
|
||||
if (mp_obj_is_int(pos_args[1])) {
|
||||
channel_id = mp_obj_get_int(pos_args[1]);
|
||||
} else {
|
||||
pin = mp_hal_get_pin_obj(pos_args[1]);
|
||||
}
|
||||
} else if (n_pos_args == 3) {
|
||||
channel_id = mp_obj_get_int(pos_args[1]);
|
||||
pin = mp_hal_get_pin_obj(pos_args[2]);
|
||||
} else {
|
||||
mp_raise_TypeError(MP_ERROR_TEXT("too many positional args"));
|
||||
}
|
||||
|
||||
machine_adc_obj_t *adc = mp_machine_adc_block_connect(self, channel_id, pin, kw_args);
|
||||
if (adc == NULL) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC"));
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(adc);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_connect_obj, 2, machine_adc_block_connect);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_adc_block_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_block_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adc_block_connect_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_adc_block_locals_dict, machine_adc_block_locals_dict_table);
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_adc_block_type,
|
||||
MP_QSTR_ADCBlock,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, machine_adc_block_make_new,
|
||||
print, machine_adc_block_print,
|
||||
locals_dict, &machine_adc_block_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_ADC_BLOCK
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_bitstream.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_BITSTREAM
|
||||
|
||||
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jim Mussared
|
||||
* Copyright (c) 2021 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H
|
@@ -31,7 +31,7 @@
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#define SOFT_I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
|
||||
|
||||
@@ -328,9 +328,10 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
|
||||
if (ret == 0) {
|
||||
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
|
||||
}
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
#endif
|
||||
// This scan loop may run for some time, so process any pending events/exceptions,
|
||||
// or allow the port to run any necessary background tasks. But do it as fast as
|
||||
// possible, in particular we are not waiting on any events.
|
||||
mp_event_handle_nowait();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
// Temporary support for legacy construction of SoftI2C via I2C type.
|
||||
#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \
|
||||
do { \
|
||||
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
|
||||
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \
|
||||
if (n_args != 0) { \
|
||||
--n_args; \
|
||||
++all_args; \
|
||||
} \
|
||||
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write
|
||||
#define MP_MACHINE_I2C_FLAG_STOP (0x02)
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
|
||||
// If set, the first mp_machine_i2c_buf_t in a transfer is a write.
|
||||
#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04)
|
||||
#endif
|
||||
|
||||
typedef struct _mp_machine_i2c_buf_t {
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
} mp_machine_i2c_buf_t;
|
||||
|
||||
// I2C protocol
|
||||
// - init must be non-NULL
|
||||
// - start/stop/read/write can be NULL, meaning operation is not supported
|
||||
// - transfer must be non-NULL
|
||||
// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor
|
||||
typedef struct _mp_machine_i2c_p_t {
|
||||
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
|
||||
bool transfer_supports_write1;
|
||||
#endif
|
||||
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
int (*start)(mp_obj_base_t *obj);
|
||||
int (*stop)(mp_obj_base_t *obj);
|
||||
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
|
||||
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
|
||||
int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags);
|
||||
} mp_machine_i2c_p_t;
|
||||
|
||||
typedef struct _mp_machine_soft_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t us_delay;
|
||||
uint32_t us_timeout;
|
||||
mp_hal_pin_obj_t scl;
|
||||
mp_hal_pin_obj_t sda;
|
||||
} mp_machine_soft_i2c_obj_t;
|
||||
|
||||
extern const mp_obj_type_t mp_machine_soft_i2c_type;
|
||||
extern const mp_obj_dict_t mp_machine_i2c_locals_dict;
|
||||
|
||||
int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
|
698
extmod/machine_i2s.c
Normal file
698
extmod/machine_i2s.c
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Mike Teachman
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2S
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
// The I2S class has 3 modes of operation:
|
||||
//
|
||||
// Mode1: Blocking
|
||||
// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write)
|
||||
// - this is the default mode of operation
|
||||
//
|
||||
// Mode2: Non-Blocking
|
||||
// - readinto() and write() methods return immediately
|
||||
// - buffer filling and emptying happens asynchronously to the main MicroPython task
|
||||
// - a callback function is called when the supplied buffer has been filled (read) or emptied (write)
|
||||
// - non-blocking mode is enabled when a callback is set with the irq() method
|
||||
// - implementation of asynchronous background operations is port specific
|
||||
//
|
||||
// Mode3: Asyncio
|
||||
// - implements the stream protocol
|
||||
// - asyncio mode is enabled when the ioctl() function is called
|
||||
// - the state of the internal ring buffer is used to detect that I2S samples can be read or written
|
||||
//
|
||||
// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention:
|
||||
// Mono: little endian format
|
||||
// Stereo: little endian format, left channel first
|
||||
//
|
||||
// I2S terms:
|
||||
// "frame": consists of two audio samples (Left audio sample + Right audio sample)
|
||||
//
|
||||
// Misc:
|
||||
// - for Mono configuration:
|
||||
// - readinto method: samples are gathered from the L channel only
|
||||
// - write method: every sample is output to both the L and R channels
|
||||
// - for readinto method the I2S hardware is read using 8-byte frames
|
||||
// (this is standard for almost all I2S hardware, such as MEMS microphones)
|
||||
|
||||
#define NUM_I2S_USER_FORMATS (4)
|
||||
#define I2S_RX_FRAME_SIZE_IN_BYTES (8)
|
||||
|
||||
typedef enum {
|
||||
MONO,
|
||||
STEREO
|
||||
} format_t;
|
||||
|
||||
typedef enum {
|
||||
BLOCKING,
|
||||
NON_BLOCKING,
|
||||
ASYNCIO
|
||||
} io_mode_t;
|
||||
|
||||
// Arguments for I2S() constructor and I2S.init().
|
||||
enum {
|
||||
ARG_sck,
|
||||
ARG_ws,
|
||||
ARG_sd,
|
||||
#if MICROPY_PY_MACHINE_I2S_MCK
|
||||
ARG_mck,
|
||||
#endif
|
||||
ARG_mode,
|
||||
ARG_bits,
|
||||
ARG_format,
|
||||
ARG_rate,
|
||||
ARG_ibuf,
|
||||
};
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
|
||||
typedef struct _ring_buf_t {
|
||||
uint8_t *buffer;
|
||||
size_t head;
|
||||
size_t tail;
|
||||
size_t size;
|
||||
} ring_buf_t;
|
||||
|
||||
typedef struct _non_blocking_descriptor_t {
|
||||
mp_buffer_info_t appbuf;
|
||||
uint32_t index;
|
||||
bool copy_in_progress;
|
||||
} non_blocking_descriptor_t;
|
||||
|
||||
STATIC void ringbuf_init(ring_buf_t *rbuf, uint8_t *buffer, size_t size);
|
||||
STATIC bool ringbuf_push(ring_buf_t *rbuf, uint8_t data);
|
||||
STATIC bool ringbuf_pop(ring_buf_t *rbuf, uint8_t *data);
|
||||
STATIC size_t ringbuf_available_data(ring_buf_t *rbuf);
|
||||
STATIC size_t ringbuf_available_space(ring_buf_t *rbuf);
|
||||
STATIC void fill_appbuf_from_ringbuf_non_blocking(machine_i2s_obj_t *self);
|
||||
STATIC void copy_appbuf_to_ringbuf_non_blocking(machine_i2s_obj_t *self);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
|
||||
// The port must provide implementations of these low-level I2S functions.
|
||||
STATIC void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *args);
|
||||
STATIC machine_i2s_obj_t *mp_machine_i2s_make_new_instance(mp_int_t i2s_id);
|
||||
STATIC void mp_machine_i2s_deinit(machine_i2s_obj_t *self);
|
||||
STATIC void mp_machine_i2s_irq_update(machine_i2s_obj_t *self);
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_I2S_INCLUDEFILE
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
|
||||
// Ring Buffer
|
||||
// Thread safe when used with these constraints:
|
||||
// - Single Producer, Single Consumer
|
||||
// - Sequential atomic operations
|
||||
// One byte of capacity is used to detect buffer empty/full
|
||||
|
||||
STATIC void ringbuf_init(ring_buf_t *rbuf, uint8_t *buffer, size_t size) {
|
||||
rbuf->buffer = buffer;
|
||||
rbuf->size = size;
|
||||
rbuf->head = 0;
|
||||
rbuf->tail = 0;
|
||||
}
|
||||
|
||||
STATIC bool ringbuf_push(ring_buf_t *rbuf, uint8_t data) {
|
||||
size_t next_tail = (rbuf->tail + 1) % rbuf->size;
|
||||
|
||||
if (next_tail != rbuf->head) {
|
||||
rbuf->buffer[rbuf->tail] = data;
|
||||
rbuf->tail = next_tail;
|
||||
return true;
|
||||
}
|
||||
|
||||
// full
|
||||
return false;
|
||||
}
|
||||
|
||||
STATIC bool ringbuf_pop(ring_buf_t *rbuf, uint8_t *data) {
|
||||
if (rbuf->head == rbuf->tail) {
|
||||
// empty
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = rbuf->buffer[rbuf->head];
|
||||
rbuf->head = (rbuf->head + 1) % rbuf->size;
|
||||
return true;
|
||||
}
|
||||
|
||||
STATIC bool ringbuf_is_empty(ring_buf_t *rbuf) {
|
||||
return rbuf->head == rbuf->tail;
|
||||
}
|
||||
|
||||
STATIC bool ringbuf_is_full(ring_buf_t *rbuf) {
|
||||
return ((rbuf->tail + 1) % rbuf->size) == rbuf->head;
|
||||
}
|
||||
|
||||
STATIC size_t ringbuf_available_data(ring_buf_t *rbuf) {
|
||||
return (rbuf->tail - rbuf->head + rbuf->size) % rbuf->size;
|
||||
}
|
||||
|
||||
STATIC size_t ringbuf_available_space(ring_buf_t *rbuf) {
|
||||
return rbuf->size - ringbuf_available_data(rbuf) - 1;
|
||||
}
|
||||
|
||||
STATIC uint32_t fill_appbuf_from_ringbuf(machine_i2s_obj_t *self, mp_buffer_info_t *appbuf) {
|
||||
|
||||
// copy audio samples from the ring buffer to the app buffer
|
||||
// loop, copying samples until the app buffer is filled
|
||||
// For asyncio mode, the loop will make an early exit if the ring buffer becomes empty
|
||||
// Example:
|
||||
// a MicroPython I2S object is configured for 16-bit mono (2 bytes per audio sample).
|
||||
// For every frame coming from the ring buffer (8 bytes), 2 bytes are "cherry picked" and
|
||||
// copied to the supplied app buffer.
|
||||
// Thus, for every 1 byte copied to the app buffer, 4 bytes are read from the ring buffer.
|
||||
// If a 8kB app buffer is supplied, 32kB of audio samples is read from the ring buffer.
|
||||
|
||||
uint32_t num_bytes_copied_to_appbuf = 0;
|
||||
uint8_t *app_p = (uint8_t *)appbuf->buf;
|
||||
uint8_t appbuf_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
|
||||
uint32_t num_bytes_needed_from_ringbuf = appbuf->len * (I2S_RX_FRAME_SIZE_IN_BYTES / appbuf_sample_size_in_bytes);
|
||||
uint8_t discard_byte;
|
||||
while (num_bytes_needed_from_ringbuf) {
|
||||
|
||||
uint8_t f_index = get_frame_mapping_index(self->bits, self->format);
|
||||
|
||||
for (uint8_t i = 0; i < I2S_RX_FRAME_SIZE_IN_BYTES; i++) {
|
||||
int8_t r_to_a_mapping = i2s_frame_map[f_index][i];
|
||||
if (r_to_a_mapping != -1) {
|
||||
if (self->io_mode == BLOCKING) {
|
||||
// poll the ringbuf until a sample becomes available, copy into appbuf using the mapping transform
|
||||
while (ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping) == false) {
|
||||
;
|
||||
}
|
||||
num_bytes_copied_to_appbuf++;
|
||||
} else if (self->io_mode == ASYNCIO) {
|
||||
if (ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping) == false) {
|
||||
// ring buffer is empty, exit
|
||||
goto exit;
|
||||
} else {
|
||||
num_bytes_copied_to_appbuf++;
|
||||
}
|
||||
} else {
|
||||
return 0; // should never get here (non-blocking mode does not use this function)
|
||||
}
|
||||
} else { // r_a_mapping == -1
|
||||
// discard unused byte from ring buffer
|
||||
if (self->io_mode == BLOCKING) {
|
||||
// poll the ringbuf until a sample becomes available
|
||||
while (ringbuf_pop(&self->ring_buffer, &discard_byte) == false) {
|
||||
;
|
||||
}
|
||||
} else if (self->io_mode == ASYNCIO) {
|
||||
if (ringbuf_pop(&self->ring_buffer, &discard_byte) == false) {
|
||||
// ring buffer is empty, exit
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
return 0; // should never get here (non-blocking mode does not use this function)
|
||||
}
|
||||
}
|
||||
num_bytes_needed_from_ringbuf--;
|
||||
}
|
||||
app_p += appbuf_sample_size_in_bytes;
|
||||
}
|
||||
exit:
|
||||
return num_bytes_copied_to_appbuf;
|
||||
}
|
||||
|
||||
// function is used in IRQ context
|
||||
STATIC void fill_appbuf_from_ringbuf_non_blocking(machine_i2s_obj_t *self) {
|
||||
|
||||
// attempt to copy a block of audio samples from the ring buffer to the supplied app buffer.
|
||||
// audio samples will be formatted as part of the copy operation
|
||||
|
||||
uint32_t num_bytes_copied_to_appbuf = 0;
|
||||
uint8_t *app_p = &(((uint8_t *)self->non_blocking_descriptor.appbuf.buf)[self->non_blocking_descriptor.index]);
|
||||
|
||||
uint8_t appbuf_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
|
||||
uint32_t num_bytes_remaining_to_copy_to_appbuf = self->non_blocking_descriptor.appbuf.len - self->non_blocking_descriptor.index;
|
||||
uint32_t num_bytes_remaining_to_copy_from_ring_buffer = num_bytes_remaining_to_copy_to_appbuf *
|
||||
(I2S_RX_FRAME_SIZE_IN_BYTES / appbuf_sample_size_in_bytes);
|
||||
uint32_t num_bytes_needed_from_ringbuf = MIN(SIZEOF_NON_BLOCKING_COPY_IN_BYTES, num_bytes_remaining_to_copy_from_ring_buffer);
|
||||
uint8_t discard_byte;
|
||||
if (ringbuf_available_data(&self->ring_buffer) >= num_bytes_needed_from_ringbuf) {
|
||||
while (num_bytes_needed_from_ringbuf) {
|
||||
|
||||
uint8_t f_index = get_frame_mapping_index(self->bits, self->format);
|
||||
|
||||
for (uint8_t i = 0; i < I2S_RX_FRAME_SIZE_IN_BYTES; i++) {
|
||||
int8_t r_to_a_mapping = i2s_frame_map[f_index][i];
|
||||
if (r_to_a_mapping != -1) {
|
||||
ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping);
|
||||
num_bytes_copied_to_appbuf++;
|
||||
} else { // r_a_mapping == -1
|
||||
// discard unused byte from ring buffer
|
||||
ringbuf_pop(&self->ring_buffer, &discard_byte);
|
||||
}
|
||||
num_bytes_needed_from_ringbuf--;
|
||||
}
|
||||
app_p += appbuf_sample_size_in_bytes;
|
||||
}
|
||||
self->non_blocking_descriptor.index += num_bytes_copied_to_appbuf;
|
||||
|
||||
if (self->non_blocking_descriptor.index >= self->non_blocking_descriptor.appbuf.len) {
|
||||
self->non_blocking_descriptor.copy_in_progress = false;
|
||||
mp_sched_schedule(self->callback_for_non_blocking, MP_OBJ_FROM_PTR(self));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC uint32_t copy_appbuf_to_ringbuf(machine_i2s_obj_t *self, mp_buffer_info_t *appbuf) {
|
||||
|
||||
// copy audio samples from the app buffer to the ring buffer
|
||||
// loop, reading samples until the app buffer is emptied
|
||||
// for asyncio mode, the loop will make an early exit if the ring buffer becomes full
|
||||
|
||||
uint32_t a_index = 0;
|
||||
|
||||
while (a_index < appbuf->len) {
|
||||
if (self->io_mode == BLOCKING) {
|
||||
// copy a byte to the ringbuf when space becomes available
|
||||
while (ringbuf_push(&self->ring_buffer, ((uint8_t *)appbuf->buf)[a_index]) == false) {
|
||||
;
|
||||
}
|
||||
a_index++;
|
||||
} else if (self->io_mode == ASYNCIO) {
|
||||
if (ringbuf_push(&self->ring_buffer, ((uint8_t *)appbuf->buf)[a_index]) == false) {
|
||||
// ring buffer is full, exit
|
||||
break;
|
||||
} else {
|
||||
a_index++;
|
||||
}
|
||||
} else {
|
||||
return 0; // should never get here (non-blocking mode does not use this function)
|
||||
}
|
||||
}
|
||||
|
||||
return a_index;
|
||||
}
|
||||
|
||||
// function is used in IRQ context
|
||||
STATIC void copy_appbuf_to_ringbuf_non_blocking(machine_i2s_obj_t *self) {
|
||||
|
||||
// copy audio samples from app buffer into ring buffer
|
||||
uint32_t num_bytes_remaining_to_copy = self->non_blocking_descriptor.appbuf.len - self->non_blocking_descriptor.index;
|
||||
uint32_t num_bytes_to_copy = MIN(SIZEOF_NON_BLOCKING_COPY_IN_BYTES, num_bytes_remaining_to_copy);
|
||||
|
||||
if (ringbuf_available_space(&self->ring_buffer) >= num_bytes_to_copy) {
|
||||
for (uint32_t i = 0; i < num_bytes_to_copy; i++) {
|
||||
ringbuf_push(&self->ring_buffer,
|
||||
((uint8_t *)self->non_blocking_descriptor.appbuf.buf)[self->non_blocking_descriptor.index + i]);
|
||||
}
|
||||
|
||||
self->non_blocking_descriptor.index += num_bytes_to_copy;
|
||||
if (self->non_blocking_descriptor.index >= self->non_blocking_descriptor.appbuf.len) {
|
||||
self->non_blocking_descriptor.copy_in_progress = false;
|
||||
mp_sched_schedule(self->callback_for_non_blocking, MP_OBJ_FROM_PTR(self));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
|
||||
MP_NOINLINE STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_ws, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_sd, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
#if MICROPY_PY_MACHINE_I2S_MCK
|
||||
{ MP_QSTR_mck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
#endif
|
||||
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_format, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_ibuf, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_machine_i2s_init_helper(self, args);
|
||||
}
|
||||
|
||||
STATIC void machine_i2s_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "I2S(id=%u,\n"
|
||||
"sck="MP_HAL_PIN_FMT ",\n"
|
||||
"ws="MP_HAL_PIN_FMT ",\n"
|
||||
"sd="MP_HAL_PIN_FMT ",\n"
|
||||
#if MICROPY_PY_MACHINE_I2S_MCK
|
||||
"mck="MP_HAL_PIN_FMT ",\n"
|
||||
#endif
|
||||
"mode=%u,\n"
|
||||
"bits=%u, format=%u,\n"
|
||||
"rate=%d, ibuf=%d)",
|
||||
self->i2s_id,
|
||||
mp_hal_pin_name(self->sck),
|
||||
mp_hal_pin_name(self->ws),
|
||||
mp_hal_pin_name(self->sd),
|
||||
#if MICROPY_PY_MACHINE_I2S_MCK
|
||||
mp_hal_pin_name(self->mck),
|
||||
#endif
|
||||
self->mode,
|
||||
self->bits, self->format,
|
||||
self->rate, self->ibuf
|
||||
);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
mp_int_t i2s_id = mp_obj_get_int(args[0]);
|
||||
|
||||
machine_i2s_obj_t *self = mp_machine_i2s_make_new_instance(i2s_id);
|
||||
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
|
||||
machine_i2s_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
// I2S.init(...)
|
||||
STATIC mp_obj_t machine_i2s_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_machine_i2s_deinit(self);
|
||||
machine_i2s_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_init_obj, 1, machine_i2s_init);
|
||||
|
||||
// I2S.deinit()
|
||||
STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_i2s_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2s_deinit_obj, machine_i2s_deinit);
|
||||
|
||||
// I2S.irq(handler)
|
||||
STATIC mp_obj_t machine_i2s_irq(mp_obj_t self_in, mp_obj_t handler) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (handler != mp_const_none && !mp_obj_is_callable(handler)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid callback"));
|
||||
}
|
||||
|
||||
if (handler != mp_const_none) {
|
||||
self->io_mode = NON_BLOCKING;
|
||||
} else {
|
||||
self->io_mode = BLOCKING;
|
||||
}
|
||||
|
||||
self->callback_for_non_blocking = handler;
|
||||
|
||||
mp_machine_i2s_irq_update(self);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_irq_obj, machine_i2s_irq);
|
||||
|
||||
// Shift() is typically used as a volume control.
|
||||
// shift=1 increases volume by 6dB, shift=-1 decreases volume by 6dB
|
||||
STATIC mp_obj_t machine_i2s_shift(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_buf, ARG_bits, ARG_shift};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_bits, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_shift, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_RW);
|
||||
|
||||
int16_t *buf_16 = bufinfo.buf;
|
||||
int32_t *buf_32 = bufinfo.buf;
|
||||
|
||||
uint8_t bits = args[ARG_bits].u_int;
|
||||
int8_t shift = args[ARG_shift].u_int;
|
||||
|
||||
uint32_t num_audio_samples;
|
||||
switch (bits) {
|
||||
case 16:
|
||||
num_audio_samples = bufinfo.len / sizeof(uint16_t);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
num_audio_samples = bufinfo.len / sizeof(uint32_t);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < num_audio_samples; i++) {
|
||||
switch (bits) {
|
||||
case 16:
|
||||
if (shift >= 0) {
|
||||
buf_16[i] = buf_16[i] << shift;
|
||||
} else {
|
||||
buf_16[i] = buf_16[i] >> abs(shift);
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if (shift >= 0) {
|
||||
buf_32[i] = buf_32[i] << shift;
|
||||
} else {
|
||||
buf_32[i] = buf_32[i] >> abs(shift);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_shift_fun_obj, 0, machine_i2s_shift);
|
||||
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_i2s_shift_obj, MP_ROM_PTR(&machine_i2s_shift_fun_obj));
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
|
||||
// Methods
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2s_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },
|
||||
#if MICROPY_PY_MACHINE_I2S_FINALISER
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2s_deinit_obj) },
|
||||
#endif
|
||||
|
||||
// Static method
|
||||
{ MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },
|
||||
|
||||
// Constants
|
||||
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_INT(MICROPY_PY_MACHINE_I2S_CONSTANT_RX) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_INT(MICROPY_PY_MACHINE_I2S_CONSTANT_TX) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_STEREO), MP_ROM_INT(STEREO) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO), MP_ROM_INT(MONO) },
|
||||
};
|
||||
MP_DEFINE_CONST_DICT(machine_i2s_locals_dict, machine_i2s_locals_dict_table);
|
||||
|
||||
STATIC mp_uint_t machine_i2s_stream_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_RX) {
|
||||
*errcode = MP_EPERM;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
uint8_t appbuf_sample_size_in_bytes = (self->bits / 8) * (self->format == STEREO ? 2: 1);
|
||||
if (size % appbuf_sample_size_in_bytes != 0) {
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->io_mode == NON_BLOCKING) {
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
self->non_blocking_descriptor.appbuf.buf = (void *)buf_in;
|
||||
self->non_blocking_descriptor.appbuf.len = size;
|
||||
self->non_blocking_descriptor.index = 0;
|
||||
self->non_blocking_descriptor.copy_in_progress = true;
|
||||
#else
|
||||
non_blocking_descriptor_t descriptor;
|
||||
descriptor.appbuf.buf = (void *)buf_in;
|
||||
descriptor.appbuf.len = size;
|
||||
descriptor.callback = self->callback_for_non_blocking;
|
||||
descriptor.direction = I2S_RX_TRANSFER;
|
||||
// send the descriptor to the task that handles non-blocking mode
|
||||
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
} else { // blocking or asyncio mode
|
||||
mp_buffer_info_t appbuf;
|
||||
appbuf.buf = (void *)buf_in;
|
||||
appbuf.len = size;
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
uint32_t num_bytes_read = fill_appbuf_from_ringbuf(self, &appbuf);
|
||||
#else
|
||||
uint32_t num_bytes_read = fill_appbuf_from_dma(self, &appbuf);
|
||||
#endif
|
||||
return num_bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_i2s_stream_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_TX) {
|
||||
*errcode = MP_EPERM;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->io_mode == NON_BLOCKING) {
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
self->non_blocking_descriptor.appbuf.buf = (void *)buf_in;
|
||||
self->non_blocking_descriptor.appbuf.len = size;
|
||||
self->non_blocking_descriptor.index = 0;
|
||||
self->non_blocking_descriptor.copy_in_progress = true;
|
||||
#else
|
||||
non_blocking_descriptor_t descriptor;
|
||||
descriptor.appbuf.buf = (void *)buf_in;
|
||||
descriptor.appbuf.len = size;
|
||||
descriptor.callback = self->callback_for_non_blocking;
|
||||
descriptor.direction = I2S_TX_TRANSFER;
|
||||
// send the descriptor to the task that handles non-blocking mode
|
||||
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
} else { // blocking or asyncio mode
|
||||
mp_buffer_info_t appbuf;
|
||||
appbuf.buf = (void *)buf_in;
|
||||
appbuf.len = size;
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
uint32_t num_bytes_written = copy_appbuf_to_ringbuf(self, &appbuf);
|
||||
#else
|
||||
uint32_t num_bytes_written = copy_appbuf_to_dma(self, &appbuf);
|
||||
#endif
|
||||
return num_bytes_written;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t machine_i2s_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_uint_t ret;
|
||||
uintptr_t flags = arg;
|
||||
self->io_mode = ASYNCIO; // a call to ioctl() is an indication that asyncio is being used
|
||||
|
||||
if (request == MP_STREAM_POLL) {
|
||||
ret = 0;
|
||||
|
||||
if (flags & MP_STREAM_POLL_RD) {
|
||||
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_RX) {
|
||||
*errcode = MP_EPERM;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
if (!ringbuf_is_empty(&self->ring_buffer)) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
#else
|
||||
// check event queue to determine if a DMA buffer has been filled
|
||||
// (which is an indication that at least one DMA buffer is available to be read)
|
||||
// note: timeout = 0 so the call is non-blocking
|
||||
i2s_event_t i2s_event;
|
||||
if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) {
|
||||
if (i2s_event.type == I2S_EVENT_RX_DONE) {
|
||||
// getting here means that at least one DMA buffer is now full
|
||||
// indicating that audio samples can be read from the I2S object
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (flags & MP_STREAM_POLL_WR) {
|
||||
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_TX) {
|
||||
*errcode = MP_EPERM;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2S_RING_BUF
|
||||
if (!ringbuf_is_full(&self->ring_buffer)) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
#else
|
||||
// check event queue to determine if a DMA buffer has been emptied
|
||||
// (which is an indication that at least one DMA buffer is available to be written)
|
||||
// note: timeout = 0 so the call is non-blocking
|
||||
i2s_event_t i2s_event;
|
||||
if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) {
|
||||
if (i2s_event.type == I2S_EVENT_TX_DONE) {
|
||||
// getting here means that at least one DMA buffer is now empty
|
||||
// indicating that audio samples can be written to the I2S object
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
*errcode = MP_EINVAL;
|
||||
ret = MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t i2s_stream_p = {
|
||||
.read = machine_i2s_stream_read,
|
||||
.write = machine_i2s_stream_write,
|
||||
.ioctl = machine_i2s_ioctl,
|
||||
.is_text = false,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_i2s_type,
|
||||
MP_QSTR_I2S,
|
||||
MP_TYPE_FLAG_ITER_IS_STREAM,
|
||||
make_new, machine_i2s_make_new,
|
||||
print, machine_i2s_print,
|
||||
protocol, &i2s_stream_p,
|
||||
locals_dict, &machine_i2s_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_I2S
|
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct _machine_mem_obj_t {
|
||||
mp_obj_base_t base;
|
||||
unsigned elem_size; // in bytes
|
||||
} machine_mem_obj_t;
|
||||
|
||||
extern const mp_obj_type_t machine_mem_type;
|
||||
|
||||
extern const machine_mem_obj_t machine_mem8_obj;
|
||||
extern const machine_mem_obj_t machine_mem16_obj;
|
||||
extern const machine_mem_obj_t machine_mem32_obj;
|
||||
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
|
@@ -24,13 +24,12 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_PIN_BASE
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
#include "extmod/virtpin.h"
|
||||
#include "extmod/machine_pinbase.h"
|
||||
|
||||
// PinBase class
|
||||
|
||||
@@ -85,4 +84,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
||||
protocol, &pinbase_pin_p
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
||||
#endif // MICROPY_PY_MACHINE_PIN_BASE
|
||||
|
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
extern const mp_obj_type_t machine_pinbase_type;
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
|
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_PULSE
|
||||
|
||||
|
@@ -28,11 +28,26 @@
|
||||
|
||||
#if MICROPY_PY_MACHINE_PWM
|
||||
|
||||
#include "extmod/machine_pwm.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
#ifdef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
|
||||
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
|
||||
// The port must provide implementations of these low-level PWM functions.
|
||||
STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
|
||||
STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
|
||||
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
|
||||
#if MICROPY_PY_MACHINE_PWM_DUTY
|
||||
STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
|
||||
STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
|
||||
#endif
|
||||
STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
|
||||
STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
|
||||
STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
|
||||
STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
|
||||
|
||||
STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
|
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
// A port must provide this type, but it's otherwise opaque.
|
||||
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
|
||||
|
||||
// This PWM class is implemented by machine_pwm.c.
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
|
||||
// A port must provide implementations of these low-level PWM functions, either as global
|
||||
// linker symbols, or included directly if MICROPY_PY_MACHINE_PWM_INCLUDEFILE is defined.
|
||||
#ifndef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
|
||||
void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
|
||||
mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
|
||||
void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
|
||||
mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
|
||||
void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
|
||||
mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
|
||||
void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
|
||||
mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
|
||||
void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
|
@@ -29,10 +29,9 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#include "extmod/virtpin.h"
|
||||
#include "extmod/machine_signal.h"
|
||||
|
||||
// Signal class
|
||||
|
||||
|
@@ -31,7 +31,7 @@
|
||||
|
||||
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
|
||||
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
// if a port didn't define MSB/LSB constants then provide them
|
||||
#ifndef MICROPY_PY_MACHINE_SPI_MSB
|
||||
|
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "drivers/bus/spi.h"
|
||||
|
||||
// Temporary support for legacy construction of SoftSPI via SPI type.
|
||||
#define MP_MACHINE_SPI_CHECK_FOR_LEGACY_SOFTSPI_CONSTRUCTION(n_args, n_kw, all_args) \
|
||||
do { \
|
||||
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
|
||||
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead\n"); \
|
||||
if (n_args != 0) { \
|
||||
--n_args; \
|
||||
++all_args; \
|
||||
} \
|
||||
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// SPI protocol
|
||||
typedef struct _mp_machine_spi_p_t {
|
||||
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
void (*deinit)(mp_obj_base_t *obj); // can be NULL
|
||||
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
} mp_machine_spi_p_t;
|
||||
|
||||
typedef struct _mp_machine_soft_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_soft_spi_obj_t spi;
|
||||
} mp_machine_soft_spi_obj_t;
|
||||
|
||||
extern const mp_machine_spi_p_t mp_machine_soft_spi_p;
|
||||
extern const mp_obj_type_t mp_machine_soft_spi_type;
|
||||
extern const mp_obj_dict_t mp_machine_spi_locals_dict;
|
||||
|
||||
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
187
extmod/machine_uart.c
Normal file
187
extmod/machine_uart.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
#include "shared/runtime/mpirq.h"
|
||||
|
||||
// The port must provide implementations of these low-level UART functions.
|
||||
|
||||
STATIC void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
STATIC void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
STATIC mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self);
|
||||
STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self);
|
||||
STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self);
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_SENDBREAK
|
||||
STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
|
||||
STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self);
|
||||
STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_IRQ
|
||||
STATIC mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args);
|
||||
#endif
|
||||
|
||||
STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode);
|
||||
STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode);
|
||||
STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_UART_INCLUDEFILE
|
||||
|
||||
// UART.init(...)
|
||||
STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_machine_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
|
||||
|
||||
// UART.deinit()
|
||||
STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_uart_deinit(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
|
||||
|
||||
// UART.any()
|
||||
STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_any(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
|
||||
|
||||
// UART.txdone()
|
||||
STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_bool(mp_machine_uart_txdone(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_SENDBREAK
|
||||
|
||||
// UART.sendbreak()
|
||||
STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_uart_sendbreak(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
|
||||
|
||||
// UART.readchar()
|
||||
STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_readchar(self));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar);
|
||||
|
||||
// UART.writechar(char)
|
||||
STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_uart_writechar(self, mp_obj_get_int(char_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar);
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_IRQ
|
||||
|
||||
// UART.irq(handler, trigger, hard)
|
||||
STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args);
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
bool any_args = n_args > 1 || kw_args->used != 0;
|
||||
return MP_OBJ_FROM_PTR(mp_machine_uart_irq(self, any_args, args));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_irq_obj, 1, machine_uart_irq);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_SENDBREAK
|
||||
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
|
||||
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_UART_IRQ
|
||||
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_uart_irq_obj) },
|
||||
#endif
|
||||
|
||||
// A port must add UART class constants defining the following macro.
|
||||
// It can be defined to nothing if there are no constants.
|
||||
MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
|
||||
|
||||
STATIC const mp_stream_p_t uart_stream_p = {
|
||||
.read = mp_machine_uart_read,
|
||||
.write = mp_machine_uart_write,
|
||||
.ioctl = mp_machine_uart_ioctl,
|
||||
.is_text = false,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_uart_type,
|
||||
MP_QSTR_UART,
|
||||
MP_TYPE_FLAG_ITER_IS_STREAM,
|
||||
make_new, mp_machine_uart_make_new,
|
||||
print, mp_machine_uart_print,
|
||||
protocol, &uart_stream_p,
|
||||
locals_dict, &machine_uart_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_UART
|
95
extmod/machine_wdt.c
Normal file
95
extmod/machine_wdt.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020-2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_WDT
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
|
||||
// The port must provide implementations of these low-level WDT functions.
|
||||
STATIC machine_wdt_obj_t *mp_machine_wdt_make_new_instance(mp_int_t id, mp_int_t timeout_ms);
|
||||
STATIC void mp_machine_wdt_feed(machine_wdt_obj_t *self);
|
||||
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
|
||||
STATIC void mp_machine_wdt_timeout_ms_set(machine_wdt_obj_t *self_in, mp_int_t timeout_ms);
|
||||
#endif
|
||||
|
||||
// The port provides implementations of the above in this file.
|
||||
#include MICROPY_PY_MACHINE_WDT_INCLUDEFILE
|
||||
|
||||
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
enum { ARG_id, ARG_timeout };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} },
|
||||
};
|
||||
|
||||
// Parse the arguments.
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// Create WDT instance.
|
||||
machine_wdt_obj_t *self = mp_machine_wdt_make_new_instance(args[ARG_id].u_int, args[ARG_timeout].u_int);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
// WDT.feed()
|
||||
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
|
||||
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_machine_wdt_feed(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
|
||||
|
||||
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
|
||||
// WDT.timeout_ms(timeout)
|
||||
STATIC mp_obj_t machine_wdt_timeout_ms(mp_obj_t self_in, mp_obj_t timeout_in) {
|
||||
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_int_t timeout_ms = mp_obj_get_int(timeout_in);
|
||||
mp_machine_wdt_timeout_ms_set(self, timeout_ms);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_wdt_timeout_ms_obj, machine_wdt_timeout_ms);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
|
||||
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
|
||||
{ MP_ROM_QSTR(MP_QSTR_timeout_ms), MP_ROM_PTR(&machine_wdt_timeout_ms_obj) },
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
machine_wdt_type,
|
||||
MP_QSTR_WDT,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, machine_wdt_make_new,
|
||||
locals_dict, &machine_wdt_locals_dict
|
||||
);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_WDT
|
@@ -31,6 +31,8 @@
|
||||
// #define MBEDTLS_DEBUG_C
|
||||
|
||||
// Set mbedtls configuration.
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
#define MBEDTLS_HAVE_TIME_DATE
|
||||
#define MBEDTLS_DEPRECATED_REMOVED
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
|
@@ -39,10 +39,12 @@ bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream);
|
||||
void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
|
||||
uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags);
|
||||
int mp_os_dupterm_rx_chr(void);
|
||||
void mp_os_dupterm_tx_strn(const char *str, size_t len);
|
||||
int mp_os_dupterm_tx_strn(const char *str, size_t len);
|
||||
void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
|
||||
#else
|
||||
#define mp_os_dupterm_tx_strn(s, l)
|
||||
static inline int mp_os_dupterm_tx_strn(const char *s, size_t l) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MISC_H
|
||||
|
@@ -1274,8 +1274,9 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
||||
if (ts_orig == NULL) {
|
||||
mp_thread_set_state(&ts);
|
||||
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
|
||||
mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024);
|
||||
mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE);
|
||||
ts.gc_lock_depth = 0;
|
||||
ts.nlr_jump_callback_top = NULL;
|
||||
ts.mp_pending_exception = MP_OBJ_NULL;
|
||||
mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context
|
||||
mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context
|
||||
|
@@ -273,42 +273,59 @@ STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u
|
||||
STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
|
||||
mp_arg_check_num(n_args, n_kw, 4, 5, false);
|
||||
|
||||
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
|
||||
o->buf_obj = args_in[0];
|
||||
mp_int_t width = mp_obj_get_int(args_in[1]);
|
||||
mp_int_t height = mp_obj_get_int(args_in[2]);
|
||||
mp_int_t format = mp_obj_get_int(args_in[3]);
|
||||
mp_int_t stride = n_args >= 5 ? mp_obj_get_int(args_in[4]) : width;
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
|
||||
o->buf = bufinfo.buf;
|
||||
|
||||
o->width = mp_obj_get_int(args_in[1]);
|
||||
o->height = mp_obj_get_int(args_in[2]);
|
||||
o->format = mp_obj_get_int(args_in[3]);
|
||||
if (n_args >= 5) {
|
||||
o->stride = mp_obj_get_int(args_in[4]);
|
||||
} else {
|
||||
o->stride = o->width;
|
||||
if (width < 1 || height < 1 || width > 0xffff || height > 0xffff || stride > 0xffff || stride < width) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
|
||||
switch (o->format) {
|
||||
size_t height_required = height;
|
||||
size_t bpp = 1;
|
||||
|
||||
switch (format) {
|
||||
case FRAMEBUF_MVLSB:
|
||||
case FRAMEBUF_RGB565:
|
||||
height_required = (height + 7) & ~7;
|
||||
break;
|
||||
case FRAMEBUF_MHLSB:
|
||||
case FRAMEBUF_MHMSB:
|
||||
o->stride = (o->stride + 7) & ~7;
|
||||
stride = (stride + 7) & ~7;
|
||||
break;
|
||||
case FRAMEBUF_GS2_HMSB:
|
||||
o->stride = (o->stride + 3) & ~3;
|
||||
stride = (stride + 3) & ~3;
|
||||
bpp = 2;
|
||||
break;
|
||||
case FRAMEBUF_GS4_HMSB:
|
||||
o->stride = (o->stride + 1) & ~1;
|
||||
stride = (stride + 1) & ~1;
|
||||
bpp = 4;
|
||||
break;
|
||||
case FRAMEBUF_GS8:
|
||||
bpp = 8;
|
||||
break;
|
||||
case FRAMEBUF_RGB565:
|
||||
bpp = 16;
|
||||
break;
|
||||
default:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
|
||||
}
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
if (height_required * stride * bpp / 8 > bufinfo.len) {
|
||||
mp_raise_ValueError(NULL);
|
||||
}
|
||||
|
||||
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
|
||||
o->buf_obj = args_in[0];
|
||||
o->buf = bufinfo.buf;
|
||||
o->width = width;
|
||||
o->height = height;
|
||||
o->format = format;
|
||||
o->stride = stride;
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
@@ -319,12 +336,8 @@ STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) {
|
||||
}
|
||||
|
||||
STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
(void)flags;
|
||||
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
bufinfo->buf = self->buf;
|
||||
bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1);
|
||||
bufinfo->typecode = 'B'; // view framebuf as bytes
|
||||
return 0;
|
||||
return mp_get_buffer(self->buf_obj, bufinfo, flags) ? 0 : 1;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
|
||||
@@ -851,28 +864,15 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
);
|
||||
#endif
|
||||
|
||||
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
// This factory function is provided for backwards compatibility with the old
|
||||
// FrameBuffer1 class which did not support a format argument.
|
||||
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) {
|
||||
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, (mp_obj_type_t *)&mp_type_framebuf);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
|
||||
o->buf = bufinfo.buf;
|
||||
|
||||
o->width = mp_obj_get_int(args_in[1]);
|
||||
o->height = mp_obj_get_int(args_in[2]);
|
||||
o->format = FRAMEBUF_MVLSB;
|
||||
if (n_args >= 4) {
|
||||
o->stride = mp_obj_get_int(args_in[3]);
|
||||
} else {
|
||||
o->stride = o->width;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
mp_obj_t args[] = {args_in[0], args_in[1], args_in[2], MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB), n_args >= 4 ? args_in[3] : args_in[1] };
|
||||
return framebuf_make_new(&mp_type_framebuf, 5, 0, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1);
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
|
||||
|
@@ -297,7 +297,7 @@ STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
|
||||
|
||||
#if MICROPY_SSL_MBEDTLS
|
||||
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000
|
||||
#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
#define mbedtls_md5_starts_ret mbedtls_md5_starts
|
||||
#define mbedtls_md5_update_ret mbedtls_md5_update
|
||||
#define mbedtls_md5_finish_ret mbedtls_md5_finish
|
||||
|
@@ -318,11 +318,7 @@ typedef struct _lwip_socket_obj_t {
|
||||
} lwip_socket_obj_t;
|
||||
|
||||
static inline void poll_sockets(void) {
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK;
|
||||
#else
|
||||
mp_hal_delay_ms(1);
|
||||
#endif
|
||||
mp_event_wait_ms(1);
|
||||
}
|
||||
|
||||
STATIC struct tcp_pcb *volatile *lwip_socket_incoming_array(lwip_socket_obj_t *socket) {
|
||||
|
242
extmod/modmachine.c
Normal file
242
extmod/modmachine.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
#include "extmod/modmachine.h"
|
||||
#include "shared/runtime/pyexec.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_DHT_READINTO
|
||||
#include "drivers/dht/dht.h"
|
||||
#endif
|
||||
|
||||
// The port must provide implementations of these low-level machine functions.
|
||||
|
||||
STATIC void mp_machine_idle(void);
|
||||
|
||||
#if MICROPY_PY_MACHINE_BOOTLOADER
|
||||
NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
|
||||
STATIC mp_obj_t mp_machine_unique_id(void);
|
||||
NORETURN STATIC void mp_machine_reset(void);
|
||||
STATIC mp_int_t mp_machine_reset_cause(void);
|
||||
STATIC mp_obj_t mp_machine_get_freq(void);
|
||||
STATIC void mp_machine_set_freq(size_t n_args, const mp_obj_t *args);
|
||||
STATIC void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args);
|
||||
NORETURN STATIC void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
|
||||
#endif
|
||||
|
||||
// The port can provide additional machine-module implementation in this file.
|
||||
#ifdef MICROPY_PY_MACHINE_INCLUDEFILE
|
||||
#include MICROPY_PY_MACHINE_INCLUDEFILE
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t machine_soft_reset(void) {
|
||||
pyexec_system_exit = PYEXEC_FORCED_EXIT;
|
||||
mp_raise_type(&mp_type_SystemExit);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
|
||||
|
||||
#if MICROPY_PY_MACHINE_BOOTLOADER
|
||||
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
|
||||
mp_machine_bootloader(n_args, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t machine_idle(void) {
|
||||
mp_machine_idle();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
|
||||
|
||||
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
|
||||
|
||||
STATIC mp_obj_t machine_unique_id(void) {
|
||||
return mp_machine_unique_id();
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
NORETURN STATIC mp_obj_t machine_reset(void) {
|
||||
mp_machine_reset();
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
|
||||
|
||||
STATIC mp_obj_t machine_reset_cause(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_machine_reset_cause());
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
|
||||
|
||||
STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
return mp_machine_get_freq();
|
||||
} else {
|
||||
mp_machine_set_freq(n_args, args);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
|
||||
|
||||
STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
||||
mp_machine_lightsleep(n_args, args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);
|
||||
|
||||
NORETURN STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) {
|
||||
mp_machine_deepsleep(n_args, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep);
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ
|
||||
|
||||
STATIC mp_obj_t machine_disable_irq(void) {
|
||||
uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
|
||||
return mp_obj_new_int(state);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
|
||||
|
||||
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
|
||||
uint32_t state = mp_obj_get_int(state_in);
|
||||
MICROPY_END_ATOMIC_SECTION(state);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
|
||||
|
||||
// Memory access objects.
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
|
||||
|
||||
// Miscellaneous functions.
|
||||
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
#endif
|
||||
|
||||
// Reset related functions.
|
||||
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
|
||||
#if MICROPY_PY_MACHINE_BOOTLOADER
|
||||
{ MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
|
||||
#endif
|
||||
|
||||
// Power related functions.
|
||||
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
|
||||
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
#endif
|
||||
|
||||
// Interrupt related functions.
|
||||
#if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
|
||||
#endif
|
||||
|
||||
// Functions for bit protocols.
|
||||
#if MICROPY_PY_MACHINE_BITSTREAM
|
||||
{ MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_DHT_READINTO
|
||||
{ MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_PULSE
|
||||
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
|
||||
#endif
|
||||
|
||||
// Classes for PinBase and Signal.
|
||||
#if MICROPY_PY_MACHINE_PIN_BASE
|
||||
{ MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
|
||||
|
||||
// Classes for software bus protocols.
|
||||
#if MICROPY_PY_MACHINE_SOFTI2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_SOFTSPI
|
||||
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
|
||||
#endif
|
||||
|
||||
// Classes for hardware peripherals.
|
||||
#if MICROPY_PY_MACHINE_ADC
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adc_block_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_DAC
|
||||
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_I2C
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_I2S
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_PWM
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_SPI
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_UART
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_WDT
|
||||
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
|
||||
#endif
|
||||
|
||||
// A port can add extra entries to the module by defining the following macro.
|
||||
#ifdef MICROPY_PY_MACHINE_EXTRA_GLOBALS
|
||||
MICROPY_PY_MACHINE_EXTRA_GLOBALS
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_machine = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&machine_module_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
269
extmod/modmachine.h
Normal file
269
extmod/modmachine.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MODMACHINE_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MODMACHINE_H
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
#include "drivers/bus/spi.h"
|
||||
|
||||
// Whether to enable the ADC.init() method.
|
||||
// Requires a port to implement mp_machine_adc_init_helper().
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_INIT
|
||||
#define MICROPY_PY_MACHINE_ADC_INIT (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the ADC.deinit() method.
|
||||
// Requires a port to implement mp_machine_adc_deinit().
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_DEINIT
|
||||
#define MICROPY_PY_MACHINE_ADC_DEINIT (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the ADC.block() method.
|
||||
// Requires a port to implement mp_machine_adc_block().
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_BLOCK
|
||||
#define MICROPY_PY_MACHINE_ADC_BLOCK (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the ADC.read_uv() method.
|
||||
// Requires a port to implement mp_machine_adc_read_uv().
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_READ_UV
|
||||
#define MICROPY_PY_MACHINE_ADC_READ_UV (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the ADC.atten() and ADC.width() methods.
|
||||
// Note: these are legacy and should not be used on new ports.
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
|
||||
#define MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the ADC.read() method.
|
||||
// Note: this is legacy and should not be used on new ports.
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_READ
|
||||
#define MICROPY_PY_MACHINE_ADC_READ (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the UART.sendbreak() method.
|
||||
// Requires a port to implement mp_machine_uart_sendbreak().
|
||||
#ifndef MICROPY_PY_MACHINE_UART_SENDBREAK
|
||||
#define MICROPY_PY_MACHINE_UART_SENDBREAK (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the UART.readchar() and UART.writechar() methods.
|
||||
// Requires a port to implement mp_machine_uart_readchar() and mp_machine_uart_writechar().
|
||||
#ifndef MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
|
||||
#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (0)
|
||||
#endif
|
||||
|
||||
// Whether to enable the UART.irq() method.
|
||||
// Requires a port to implement mp_machine_uart_irq().
|
||||
#ifndef MICROPY_PY_MACHINE_UART_IRQ
|
||||
#define MICROPY_PY_MACHINE_UART_IRQ (0)
|
||||
#endif
|
||||
|
||||
// Temporary support for legacy construction of SoftI2C via I2C type.
|
||||
#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \
|
||||
do { \
|
||||
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
|
||||
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \
|
||||
if (n_args != 0) { \
|
||||
--n_args; \
|
||||
++all_args; \
|
||||
} \
|
||||
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Temporary support for legacy construction of SoftSPI via SPI type.
|
||||
#define MP_MACHINE_SPI_CHECK_FOR_LEGACY_SOFTSPI_CONSTRUCTION(n_args, n_kw, all_args) \
|
||||
do { \
|
||||
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
|
||||
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead\n"); \
|
||||
if (n_args != 0) { \
|
||||
--n_args; \
|
||||
++all_args; \
|
||||
} \
|
||||
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
|
||||
|
||||
#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write
|
||||
#define MP_MACHINE_I2C_FLAG_STOP (0x02)
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
|
||||
// If set, the first mp_machine_i2c_buf_t in a transfer is a write.
|
||||
#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// A port must provide these types, but they are otherwise opaque.
|
||||
typedef struct _machine_adc_obj_t machine_adc_obj_t;
|
||||
typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t;
|
||||
typedef struct _machine_i2s_obj_t machine_i2s_obj_t;
|
||||
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
|
||||
typedef struct _machine_uart_obj_t machine_uart_obj_t;
|
||||
typedef struct _machine_wdt_obj_t machine_wdt_obj_t;
|
||||
|
||||
typedef struct _machine_mem_obj_t {
|
||||
mp_obj_base_t base;
|
||||
unsigned elem_size; // in bytes
|
||||
} machine_mem_obj_t;
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
|
||||
|
||||
typedef struct _mp_machine_i2c_buf_t {
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
} mp_machine_i2c_buf_t;
|
||||
|
||||
// I2C protocol:
|
||||
// - init must be non-NULL
|
||||
// - start/stop/read/write can be NULL, meaning operation is not supported
|
||||
// - transfer must be non-NULL
|
||||
// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor
|
||||
typedef struct _mp_machine_i2c_p_t {
|
||||
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
|
||||
bool transfer_supports_write1;
|
||||
#endif
|
||||
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
int (*start)(mp_obj_base_t *obj);
|
||||
int (*stop)(mp_obj_base_t *obj);
|
||||
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
|
||||
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
|
||||
int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags);
|
||||
} mp_machine_i2c_p_t;
|
||||
|
||||
// SoftI2C object.
|
||||
typedef struct _mp_machine_soft_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t us_delay;
|
||||
uint32_t us_timeout;
|
||||
mp_hal_pin_obj_t scl;
|
||||
mp_hal_pin_obj_t sda;
|
||||
} mp_machine_soft_i2c_obj_t;
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
|
||||
|
||||
// SPI protocol.
|
||||
typedef struct _mp_machine_spi_p_t {
|
||||
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
void (*deinit)(mp_obj_base_t *obj); // can be NULL
|
||||
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
} mp_machine_spi_p_t;
|
||||
|
||||
// SoftSPI object.
|
||||
typedef struct _mp_machine_soft_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
mp_soft_spi_obj_t spi;
|
||||
} mp_machine_soft_spi_obj_t;
|
||||
|
||||
#endif
|
||||
|
||||
// Objects for machine.mem8, machine.mem16 and machine.mem32.
|
||||
extern const machine_mem_obj_t machine_mem8_obj;
|
||||
extern const machine_mem_obj_t machine_mem16_obj;
|
||||
extern const machine_mem_obj_t machine_mem32_obj;
|
||||
|
||||
// These classes correspond to machine.Type entries in the machine module.
|
||||
// Their Python bindings are implemented in extmod, and their implementation
|
||||
// is provided by a port.
|
||||
extern const mp_obj_type_t machine_adc_type;
|
||||
extern const mp_obj_type_t machine_adc_block_type;
|
||||
extern const mp_obj_type_t machine_i2c_type;
|
||||
extern const mp_obj_type_t machine_i2s_type;
|
||||
extern const mp_obj_type_t machine_mem_type;
|
||||
extern const mp_obj_type_t machine_pin_type;
|
||||
extern const mp_obj_type_t machine_pinbase_type;
|
||||
extern const mp_obj_type_t machine_pwm_type;
|
||||
extern const mp_obj_type_t machine_rtc_type;
|
||||
extern const mp_obj_type_t machine_signal_type;
|
||||
extern const mp_obj_type_t machine_spi_type;
|
||||
extern const mp_obj_type_t machine_timer_type;
|
||||
extern const mp_obj_type_t machine_uart_type;
|
||||
extern const mp_obj_type_t machine_wdt_type;
|
||||
|
||||
#if MICROPY_PY_MACHINE_SOFTI2C
|
||||
extern const mp_obj_type_t mp_machine_soft_i2c_type;
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
|
||||
extern const mp_obj_dict_t mp_machine_i2c_locals_dict;
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_SOFTSPI
|
||||
extern const mp_obj_type_t mp_machine_soft_spi_type;
|
||||
extern const mp_machine_spi_p_t mp_machine_soft_spi_p;
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
|
||||
extern const mp_obj_dict_t mp_machine_spi_locals_dict;
|
||||
#endif
|
||||
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
|
||||
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
|
||||
#endif
|
||||
|
||||
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
|
||||
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len);
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_cause_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C
|
||||
int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_SPI
|
||||
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_MACHINE
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MODMACHINE_H
|
@@ -65,6 +65,15 @@ void mod_network_init(void) {
|
||||
}
|
||||
|
||||
void mod_network_deinit(void) {
|
||||
#if !MICROPY_PY_LWIP
|
||||
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
|
||||
mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
|
||||
const mod_network_nic_protocol_t *nic_protocol = MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
|
||||
if (nic_protocol->deinit) {
|
||||
nic_protocol->deinit();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void mod_network_register_nic(mp_obj_t nic) {
|
||||
|
@@ -80,6 +80,7 @@ struct _mod_network_socket_obj_t;
|
||||
typedef struct _mod_network_nic_protocol_t {
|
||||
// API for non-socket operations
|
||||
int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
|
||||
void (*deinit)(void);
|
||||
|
||||
// API for socket operations; return -1 on error
|
||||
int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno);
|
||||
|
@@ -38,11 +38,11 @@
|
||||
#define TIMING_RESET1 (480)
|
||||
#define TIMING_RESET2 (70)
|
||||
#define TIMING_RESET3 (410)
|
||||
#define TIMING_READ1 (5)
|
||||
#define TIMING_READ2 (5)
|
||||
#define TIMING_READ3 (40)
|
||||
#define TIMING_WRITE1 (10)
|
||||
#define TIMING_WRITE2 (50)
|
||||
#define TIMING_READ1 (6)
|
||||
#define TIMING_READ2 (9)
|
||||
#define TIMING_READ3 (55)
|
||||
#define TIMING_WRITE1 (6)
|
||||
#define TIMING_WRITE2 (54)
|
||||
#define TIMING_WRITE3 (10)
|
||||
|
||||
STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) {
|
||||
|
@@ -24,6 +24,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
@@ -48,6 +49,13 @@
|
||||
#include "extmod/vfs_posix.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_MBFS
|
||||
#if MICROPY_VFS
|
||||
#error "MICROPY_MBFS requires MICROPY_VFS to be disabled"
|
||||
#endif
|
||||
#include "ports/nrf/modules/os/microbitfs.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_OS_UNAME
|
||||
#include "genhdr/mpversion.h"
|
||||
#endif
|
||||
@@ -121,6 +129,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname);
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM_NOTIFY
|
||||
STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) {
|
||||
(void)obj_in;
|
||||
for (;;) {
|
||||
int c = mp_os_dupterm_rx_chr();
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
ringbuf_put(&stdin_ringbuf, c);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
|
||||
|
||||
@@ -187,6 +210,14 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MICROPY_MBFS
|
||||
// For special micro:bit filesystem only.
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_mbfs_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&os_mbfs_ilistdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_mbfs_stat_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_mbfs_remove_obj) },
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||
|
||||
|
@@ -207,12 +207,12 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
int caps_num = (self->re.sub + 1) * 2;
|
||||
mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num);
|
||||
mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num);
|
||||
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
|
||||
memset((char *)match->caps, 0, caps_num * sizeof(char *));
|
||||
int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored);
|
||||
if (res == 0) {
|
||||
m_del_var(mp_obj_match_t, char *, caps_num, match);
|
||||
m_del_var(mp_obj_match_t, caps, char *, caps_num, match);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
|
||||
#if !((MP_STREAM_POLL_RD) == (POLLIN) && \
|
||||
@@ -142,14 +143,47 @@ STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) {
|
||||
}
|
||||
}
|
||||
|
||||
// How much (in pollfds) to grow the allocation for poll_set->pollfds by.
|
||||
#define POLL_SET_ALLOC_INCREMENT (4)
|
||||
|
||||
STATIC struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) {
|
||||
struct pollfd *free_slot = NULL;
|
||||
|
||||
if (poll_set->used == poll_set->max_used) {
|
||||
// No free slots below max_used, so expand max_used (and possibly allocate).
|
||||
if (poll_set->max_used >= poll_set->alloc) {
|
||||
poll_set->pollfds = m_renew(struct pollfd, poll_set->pollfds, poll_set->alloc, poll_set->alloc + 4);
|
||||
poll_set->alloc += 4;
|
||||
size_t new_alloc = poll_set->alloc + POLL_SET_ALLOC_INCREMENT;
|
||||
// Try to grow in-place.
|
||||
struct pollfd *new_fds = m_renew_maybe(struct pollfd, poll_set->pollfds, poll_set->alloc, new_alloc, false);
|
||||
if (!new_fds) {
|
||||
// Failed to grow in-place. Do a new allocation and copy over the pollfd values.
|
||||
new_fds = m_new(struct pollfd, new_alloc);
|
||||
memcpy(new_fds, poll_set->pollfds, sizeof(struct pollfd) * poll_set->alloc);
|
||||
|
||||
// Update existing poll_obj_t to update their pollfd field to
|
||||
// point to the same offset inside the new allocation.
|
||||
for (mp_uint_t i = 0; i < poll_set->map.alloc; ++i) {
|
||||
if (!mp_map_slot_is_filled(&poll_set->map, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set->map.table[i].value);
|
||||
if (!poll_obj) {
|
||||
// This is the one we're currently adding,
|
||||
// poll_set_add_obj doesn't assign elem->value until
|
||||
// afterwards.
|
||||
continue;
|
||||
}
|
||||
|
||||
poll_obj->pollfd = new_fds + (poll_obj->pollfd - poll_set->pollfds);
|
||||
}
|
||||
|
||||
// Delete the old allocation.
|
||||
m_del(struct pollfd, poll_set->pollfds, poll_set->alloc);
|
||||
}
|
||||
|
||||
poll_set->pollfds = new_fds;
|
||||
poll_set->alloc = new_alloc;
|
||||
}
|
||||
free_slot = &poll_set->pollfds[poll_set->max_used++];
|
||||
} else {
|
||||
@@ -306,6 +340,7 @@ STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) {
|
||||
|
||||
STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) {
|
||||
mp_uint_t start_ticks = mp_hal_ticks_ms();
|
||||
bool has_timeout = timeout != (mp_uint_t)-1;
|
||||
|
||||
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
|
||||
|
||||
@@ -350,12 +385,12 @@ STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size
|
||||
}
|
||||
|
||||
// Return if an object is ready, or if the timeout expired.
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
|
||||
if (n_ready > 0 || (has_timeout && mp_hal_ticks_ms() - start_ticks >= timeout)) {
|
||||
return n_ready;
|
||||
}
|
||||
|
||||
// This would be MICROPY_EVENT_POLL_HOOK but the call to poll() above already includes a delay.
|
||||
mp_handle_pending(true);
|
||||
// This would be mp_event_wait_ms() but the call to poll() above already includes a delay.
|
||||
mp_event_handle_nowait();
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -363,10 +398,15 @@ STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size
|
||||
for (;;) {
|
||||
// poll the objects
|
||||
mp_uint_t n_ready = poll_set_poll_once(poll_set, rwx_num);
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
|
||||
uint32_t elapsed = mp_hal_ticks_ms() - start_ticks;
|
||||
if (n_ready > 0 || (has_timeout && elapsed >= timeout)) {
|
||||
return n_ready;
|
||||
}
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
if (has_timeout) {
|
||||
mp_event_wait_ms(timeout - elapsed);
|
||||
} else {
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -36,6 +36,8 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/reader.h"
|
||||
#include "extmod/vfs.h"
|
||||
|
||||
// mbedtls_time_t
|
||||
#include "mbedtls/platform.h"
|
||||
@@ -46,6 +48,11 @@
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/error.h"
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
#include "mbedtls/build_info.h"
|
||||
#else
|
||||
#include "mbedtls/version.h"
|
||||
#endif
|
||||
|
||||
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
|
||||
|
||||
@@ -59,6 +66,7 @@ typedef struct _mp_obj_ssl_context_t {
|
||||
mbedtls_x509_crt cert;
|
||||
mbedtls_pk_context pkey;
|
||||
int authmode;
|
||||
int *ciphersuites;
|
||||
} mp_obj_ssl_context_t;
|
||||
|
||||
// This corresponds to an SSLSocket object.
|
||||
@@ -75,12 +83,32 @@ typedef struct _mp_obj_ssl_socket_t {
|
||||
STATIC const mp_obj_type_t ssl_context_type;
|
||||
STATIC const mp_obj_type_t ssl_socket_type;
|
||||
|
||||
STATIC const MP_DEFINE_STR_OBJ(mbedtls_version_obj, MBEDTLS_VERSION_STRING_FULL);
|
||||
|
||||
STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
|
||||
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
|
||||
|
||||
/******************************************************************************/
|
||||
// Helper functions.
|
||||
|
||||
STATIC mp_obj_t read_file(mp_obj_t self_in) {
|
||||
// file = open(args[0], "rb")
|
||||
mp_obj_t f_args[2] = {
|
||||
self_in,
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
|
||||
};
|
||||
mp_obj_t file = mp_vfs_open(2, &f_args[0], (mp_map_t *)&mp_const_empty_map);
|
||||
|
||||
// data = file.read()
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(file, MP_QSTR_read, dest);
|
||||
mp_obj_t data = mp_call_method_n_kw(0, 0, dest);
|
||||
|
||||
// file.close()
|
||||
mp_stream_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
|
||||
(void)ctx;
|
||||
@@ -138,6 +166,46 @@ STATIC NORETURN void mbedtls_raise_error(int err) {
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) {
|
||||
if (
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
(*errcode < 0) && (mbedtls_ssl_is_handshake_over(&sslsock->ssl) == 0) && (*errcode != MBEDTLS_ERR_SSL_CONN_EOF)
|
||||
#else
|
||||
(*errcode < 0) && (*errcode != MBEDTLS_ERR_SSL_CONN_EOF)
|
||||
#endif
|
||||
) {
|
||||
// Asynchronous handshake is done by mbdetls_ssl_read/write. If the return code is
|
||||
// MBEDTLS_ERR_XX (i.e < 0) and the handshake is not done due to a handshake failure,
|
||||
// then notify peer with proper error code and raise local error with mbedtls_raise_error.
|
||||
|
||||
if (*errcode == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) {
|
||||
// Check if TLSv1.3 and use proper alert for this case (to be implemented)
|
||||
// uint8_t alert = MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED; tlsv1.3
|
||||
// uint8_t alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE; tlsv1.2
|
||||
mbedtls_ssl_send_alert_message(&sslsock->ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
|
||||
}
|
||||
|
||||
if (*errcode == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
// The certificate may have been rejected for several reasons.
|
||||
char xcbuf[256];
|
||||
uint32_t flags = mbedtls_ssl_get_verify_result(&sslsock->ssl);
|
||||
int ret = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags);
|
||||
// The length of the string written (not including the terminated nul byte),
|
||||
// or a negative err code.
|
||||
if (ret > 0) {
|
||||
sslsock->sock = MP_OBJ_NULL;
|
||||
mbedtls_ssl_free(&sslsock->ssl);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), xcbuf);
|
||||
}
|
||||
}
|
||||
|
||||
sslsock->sock = MP_OBJ_NULL;
|
||||
mbedtls_ssl_free(&sslsock->ssl);
|
||||
mbedtls_raise_error(*errcode);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// SSLContext type.
|
||||
|
||||
@@ -162,6 +230,7 @@ STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
|
||||
mbedtls_x509_crt_init(&self->cacert);
|
||||
mbedtls_x509_crt_init(&self->cert);
|
||||
mbedtls_pk_init(&self->pkey);
|
||||
self->ciphersuites = NULL;
|
||||
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
|
||||
@@ -236,6 +305,48 @@ STATIC mp_obj_t ssl_context___del__(mp_obj_t self_in) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context___del___obj, ssl_context___del__);
|
||||
#endif
|
||||
|
||||
// SSLContext.get_ciphers()
|
||||
STATIC mp_obj_t ssl_context_get_ciphers(mp_obj_t self_in) {
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) {
|
||||
const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list);
|
||||
mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str(cipher_name, strlen(cipher_name))));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context_get_ciphers_obj, ssl_context_get_ciphers);
|
||||
|
||||
// SSLContext.set_ciphers(ciphersuite)
|
||||
STATIC mp_obj_t ssl_context_set_ciphers(mp_obj_t self_in, mp_obj_t ciphersuite) {
|
||||
mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// Check that ciphersuite is a list or tuple.
|
||||
size_t len = 0;
|
||||
mp_obj_t *ciphers;
|
||||
mp_obj_get_array(ciphersuite, &len, &ciphers);
|
||||
if (len == 0) {
|
||||
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
|
||||
}
|
||||
|
||||
// Parse list of ciphers.
|
||||
ssl_context->ciphersuites = m_new(int, len + 1);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
const char *ciphername = mp_obj_str_get_str(ciphers[i]);
|
||||
const int id = mbedtls_ssl_get_ciphersuite_id(ciphername);
|
||||
if (id == 0) {
|
||||
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
|
||||
}
|
||||
ssl_context->ciphersuites[i] = id;
|
||||
}
|
||||
ssl_context->ciphersuites[len] = 0;
|
||||
|
||||
// Configure ciphersuite.
|
||||
mbedtls_ssl_conf_ciphersuites(&ssl_context->conf, (const int *)ssl_context->ciphersuites);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_ciphers_obj, ssl_context_set_ciphers);
|
||||
|
||||
STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
|
||||
size_t key_len;
|
||||
const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len);
|
||||
@@ -264,6 +375,30 @@ STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, m
|
||||
}
|
||||
}
|
||||
|
||||
// SSLContext.load_cert_chain(certfile, keyfile)
|
||||
STATIC mp_obj_t ssl_context_load_cert_chain(mp_obj_t self_in, mp_obj_t certfile, mp_obj_t keyfile) {
|
||||
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t pkey;
|
||||
mp_obj_t cert;
|
||||
if (certfile != mp_const_none) {
|
||||
// check if key is a string/path
|
||||
if (!(mp_obj_is_type(keyfile, &mp_type_bytes))) {
|
||||
pkey = read_file(keyfile);
|
||||
} else {
|
||||
pkey = keyfile;
|
||||
}
|
||||
// check if cert is a string/path
|
||||
if (!(mp_obj_is_type(certfile, &mp_type_bytes))) {
|
||||
cert = read_file(certfile);
|
||||
} else {
|
||||
cert = certfile;
|
||||
}
|
||||
ssl_context_load_key(self, pkey, cert);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(ssl_context_load_cert_chain_obj, ssl_context_load_cert_chain);
|
||||
|
||||
STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
|
||||
size_t cacert_len;
|
||||
const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len);
|
||||
@@ -276,6 +411,30 @@ STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_
|
||||
mbedtls_ssl_conf_ca_chain(&self->conf, &self->cacert, NULL);
|
||||
}
|
||||
|
||||
// SSLContext.load_verify_locations(cafile=None, *, cadata=None)
|
||||
STATIC mp_obj_t ssl_context_load_verify_locations(size_t n_args, const mp_obj_t *pos_args,
|
||||
mp_map_t *kw_args) {
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_cafile, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
};
|
||||
|
||||
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
// cafile
|
||||
if (args[0].u_obj != mp_const_none) {
|
||||
ssl_context_load_cadata(self, read_file(args[0].u_obj));
|
||||
}
|
||||
// cadata
|
||||
if (args[1].u_obj != mp_const_none) {
|
||||
ssl_context_load_cadata(self, args[1].u_obj);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_load_verify_locations_obj, 1, ssl_context_load_verify_locations);
|
||||
|
||||
STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
@@ -300,6 +459,10 @@ STATIC const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
|
||||
#if MICROPY_PY_SSL_FINALISER
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ssl_context___del___obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_ciphers), MP_ROM_PTR(&ssl_context_get_ciphers_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_ciphers), MP_ROM_PTR(&ssl_context_set_ciphers_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_load_cert_chain), MP_ROM_PTR(&ssl_context_load_cert_chain_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_load_verify_locations), MP_ROM_PTR(&ssl_context_load_verify_locations_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
|
||||
@@ -369,6 +532,8 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
|
||||
o->last_error = 0;
|
||||
|
||||
int ret;
|
||||
uint32_t flags = 0;
|
||||
|
||||
mbedtls_ssl_init(&o->ssl);
|
||||
|
||||
ret = mbedtls_ssl_setup(&o->ssl, &ssl_context->conf);
|
||||
@@ -382,6 +547,11 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
|
||||
if (ret != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (ssl_context->authmode == MBEDTLS_SSL_VERIFY_REQUIRED && server_side == false) {
|
||||
|
||||
o->sock = MP_OBJ_NULL;
|
||||
mbedtls_ssl_free(&o->ssl);
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("CERT_REQUIRED requires server_hostname"));
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
|
||||
@@ -391,20 +561,34 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
goto cleanup;
|
||||
}
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
#endif
|
||||
mp_event_wait_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
|
||||
cleanup:
|
||||
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
flags = mbedtls_ssl_get_verify_result(&o->ssl);
|
||||
}
|
||||
|
||||
o->sock = MP_OBJ_NULL;
|
||||
mbedtls_ssl_free(&o->ssl);
|
||||
|
||||
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
char xcbuf[256];
|
||||
int ret_info = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags);
|
||||
// The length of the string written (not including the terminated nul byte),
|
||||
// or a negative err code.
|
||||
if (ret_info > 0) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), xcbuf);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_raise_error(ret);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
if (!mp_obj_is_true(binary_form)) {
|
||||
@@ -417,6 +601,18 @@ STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
|
||||
return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mod_ssl_cipher(mp_obj_t o_in) {
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl);
|
||||
const char *tls_version = mbedtls_ssl_get_version(&o->ssl);
|
||||
mp_obj_t tuple[2] = {mp_obj_new_str(cipher_suite, strlen(cipher_suite)),
|
||||
mp_obj_new_str(tls_version, strlen(tls_version))};
|
||||
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ssl_cipher_obj, mod_ssl_cipher);
|
||||
|
||||
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
@@ -454,6 +650,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
|
||||
} else {
|
||||
o->last_error = ret;
|
||||
}
|
||||
ssl_check_async_handshake_failure(o, &ret);
|
||||
*errcode = ret;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
@@ -482,6 +679,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
|
||||
} else {
|
||||
o->last_error = ret;
|
||||
}
|
||||
ssl_check_async_handshake_failure(o, &ret);
|
||||
*errcode = ret;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
@@ -566,7 +764,10 @@ STATIC const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
|
||||
#if MICROPY_UNIX_COVERAGE
|
||||
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_cipher), MP_ROM_PTR(&mod_ssl_cipher_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(ssl_socket_locals_dict, ssl_socket_locals_dict_table);
|
||||
|
||||
@@ -647,6 +848,7 @@ STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
|
||||
|
||||
// Constants.
|
||||
{ MP_ROM_QSTR(MP_QSTR_MBEDTLS_VERSION), MP_ROM_PTR(&mbedtls_version_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MBEDTLS_SSL_IS_CLIENT) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MBEDTLS_SSL_IS_SERVER) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },
|
||||
|
@@ -96,7 +96,7 @@ STATIC NORETURN void syntax_error(void) {
|
||||
STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 2, 3, false);
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type);
|
||||
o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]);
|
||||
o->addr = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]);
|
||||
o->desc = args[1];
|
||||
o->flags = LAYOUT_NATIVE;
|
||||
if (n_args == 3) {
|
||||
|
@@ -222,8 +222,13 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m
|
||||
|
||||
// Wait for scan to finish, with a 10s timeout
|
||||
uint32_t start = mp_hal_ticks_ms();
|
||||
while (cyw43_wifi_scan_active(self->cyw) && mp_hal_ticks_ms() - start < 10000) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
const uint32_t TIMEOUT = 10000;
|
||||
while (cyw43_wifi_scan_active(self->cyw)) {
|
||||
uint32_t elapsed = mp_hal_ticks_ms() - start;
|
||||
if (elapsed >= TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
mp_event_wait_ms(TIMEOUT - elapsed);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include "py/misc.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "shared/netutils/netutils.h"
|
||||
#include "shared/runtime/softtimer.h"
|
||||
#include "extmod/modnetwork.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
@@ -50,6 +51,7 @@
|
||||
typedef struct _nina_obj_t {
|
||||
mp_obj_base_t base;
|
||||
bool active;
|
||||
bool poll_enable;
|
||||
uint32_t itf;
|
||||
mp_uint_t security;
|
||||
char ssid[NINA_MAX_SSID_LEN + 1];
|
||||
@@ -71,6 +73,7 @@ typedef struct _nina_obj_t {
|
||||
#define SO_ERROR (0x1007)
|
||||
#define SO_TYPE (0x1008)
|
||||
#define SO_NO_CHECK (0x100a)
|
||||
#define NINAW10_POLL_INTERVAL (100)
|
||||
|
||||
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
|
||||
|
||||
@@ -78,28 +81,56 @@ typedef struct _nina_obj_t {
|
||||
|
||||
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
|
||||
const mp_obj_type_t mod_network_nic_type_nina;
|
||||
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
|
||||
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
|
||||
static mp_sched_node_t mp_wifi_sockpoll_node;
|
||||
static mp_sched_node_t mp_wifi_connpoll_node;
|
||||
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_STA_IF};
|
||||
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_AP_IF};
|
||||
static mp_sched_node_t mp_wifi_poll_node;
|
||||
static soft_timer_entry_t mp_wifi_poll_timer;
|
||||
STATIC void network_ninaw10_deinit(void);
|
||||
|
||||
STATIC bool network_ninaw10_poll_list_is_empty(void) {
|
||||
return MP_STATE_PORT(mp_wifi_poll_list) == NULL ||
|
||||
MP_STATE_PORT(mp_wifi_poll_list)->len == 0;
|
||||
}
|
||||
|
||||
STATIC void network_ninaw10_poll_list_insert(mp_obj_t socket) {
|
||||
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
|
||||
MP_STATE_PORT(mp_wifi_poll_list) = mp_obj_new_list(0, NULL);
|
||||
}
|
||||
mp_obj_list_append(MP_STATE_PORT(mp_wifi_poll_list), socket);
|
||||
}
|
||||
|
||||
STATIC void network_ninaw10_poll_list_remove(mp_obj_t socket) {
|
||||
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
|
||||
return;
|
||||
}
|
||||
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_poll_list), socket);
|
||||
if (MP_STATE_PORT(mp_wifi_poll_list)->len == 0) {
|
||||
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
|
||||
(void)node;
|
||||
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_wifi_sockpoll_list)->len; i++) {
|
||||
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_sockpoll_list)->items[i];
|
||||
for (mp_uint_t i = 0; MP_STATE_PORT(mp_wifi_poll_list) && i < MP_STATE_PORT(mp_wifi_poll_list)->len;) {
|
||||
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_poll_list)->items[i];
|
||||
uint8_t flags = 0;
|
||||
if (socket->callback == MP_OBJ_NULL || nina_socket_poll(socket->fileno, &flags) < 0) {
|
||||
// remove from poll list on error.
|
||||
// Remove socket from poll list on error.
|
||||
socket->callback = MP_OBJ_NULL;
|
||||
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
|
||||
} else if (flags) {
|
||||
mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
|
||||
if (flags & SOCKET_POLL_ERR) {
|
||||
// remove from poll list on error.
|
||||
socket->callback = MP_OBJ_NULL;
|
||||
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
|
||||
}
|
||||
network_ninaw10_poll_list_remove(socket);
|
||||
// Check the same index on the next iteration.
|
||||
continue;
|
||||
}
|
||||
if (flags & SOCKET_POLL_RD) {
|
||||
mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
|
||||
}
|
||||
i++;
|
||||
debug_printf("poll_sockets(%d) -> flags %d\n", socket->fileno, flags);
|
||||
}
|
||||
|
||||
if (!network_ninaw10_poll_list_is_empty()) {
|
||||
// Reschedule the sockets polling code.
|
||||
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +140,8 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
|
||||
int status = nina_connection_status();
|
||||
if (status == NINA_STATUS_CONNECTED) {
|
||||
// Connected to AP, nothing else to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (status != NINA_STATUS_NO_SSID_AVAIL) {
|
||||
self->poll_enable = false;
|
||||
} else if (status != NINA_STATUS_NO_SSID_AVAIL) {
|
||||
// If not connected, and no connection in progress, the connection attempt has failed.
|
||||
// Read the ESP failure reason, reconnect and reschedule the connection polling code.
|
||||
int reason = nina_connection_reason();
|
||||
@@ -121,7 +150,7 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
|
||||
reason == NINA_ESP_REASON_NOT_AUTHED ||
|
||||
reason == NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT ||
|
||||
reason >= NINA_ESP_REASON_BEACON_TIMEOUT) {
|
||||
debug_printf(&mp_plat_print, "poll_connect() status: %d reason %d\n", status, reason);
|
||||
debug_printf("poll_connect() status: %d reason %d\n", status, reason);
|
||||
if (nina_connect(self->ssid, self->security, self->key, 0) != 0) {
|
||||
mp_raise_msg_varg(&mp_type_OSError,
|
||||
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"),
|
||||
@@ -129,21 +158,23 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
|
||||
}
|
||||
} else {
|
||||
// Will not attempt to reconnect if there's another error code set.
|
||||
return;
|
||||
self->poll_enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reschedule the connection polling code.
|
||||
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
|
||||
// Reinsert the timer to schedule the polling code.
|
||||
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
|
||||
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
|
||||
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
|
||||
STATIC void network_ninaw10_timer_callback(soft_timer_entry_t *self) {
|
||||
debug_printf("timer_callback() poll status STA: %d AP: %d SOCKETS: %d\n",
|
||||
network_nina_wl_sta.poll_enable, network_nina_wl_ap.poll_enable, !network_ninaw10_poll_list_is_empty());
|
||||
if (network_nina_wl_sta.poll_enable) {
|
||||
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_connect);
|
||||
} else if (!network_ninaw10_poll_list_is_empty()) {
|
||||
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_sockets);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_timer_callback_obj, network_ninaw10_timer_callback);
|
||||
|
||||
STATIC mp_obj_t network_ninaw10_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
@@ -162,6 +193,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
|
||||
nina_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
if (n_args == 2) {
|
||||
bool active = mp_obj_is_true(args[1]);
|
||||
network_ninaw10_deinit();
|
||||
if (active) {
|
||||
int error = 0;
|
||||
if ((error = nina_init()) != 0) {
|
||||
@@ -190,19 +222,9 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
|
||||
NINA_FW_VER_MIN_MAJOR, NINA_FW_VER_MIN_MINOR, NINA_FW_VER_MIN_PATCH, semver[NINA_FW_VER_MAJOR_OFFS] - 48,
|
||||
semver[NINA_FW_VER_MINOR_OFFS] - 48, semver[NINA_FW_VER_PATCH_OFFS] - 48);
|
||||
}
|
||||
MP_STATE_PORT(mp_wifi_sockpoll_list) = mp_obj_new_list(0, NULL);
|
||||
if (MP_STATE_PORT(mp_wifi_timer) == MP_OBJ_NULL) {
|
||||
// Start sockets poll timer
|
||||
mp_obj_t timer_args[] = {
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
|
||||
};
|
||||
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
|
||||
}
|
||||
soft_timer_static_init(&mp_wifi_poll_timer, SOFT_TIMER_MODE_ONE_SHOT, 0, network_ninaw10_timer_callback);
|
||||
} else {
|
||||
nina_deinit();
|
||||
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_NULL;
|
||||
MP_STATE_PORT(mp_wifi_sockpoll_list) = MP_OBJ_NULL;
|
||||
}
|
||||
self->active = active;
|
||||
return mp_const_none;
|
||||
@@ -283,7 +305,8 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
|
||||
self->security = security;
|
||||
strncpy(self->key, key, NINA_MAX_WPA_LEN);
|
||||
strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
|
||||
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
|
||||
self->poll_enable = true;
|
||||
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
|
||||
} else {
|
||||
mp_uint_t channel = args[ARG_channel].u_int;
|
||||
|
||||
@@ -428,7 +451,11 @@ STATIC mp_obj_t network_ninaw10_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_
|
||||
nina_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t buf;
|
||||
mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE);
|
||||
nina_ioctl(mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf);
|
||||
int ret = nina_ioctl(mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf);
|
||||
if (ret != 0) {
|
||||
mp_raise_msg_varg(&mp_type_OSError,
|
||||
MP_ERROR_TEXT("ioctl %d failed %d"), mp_obj_get_int(cmd_in), ret);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_ninaw10_ioctl_obj, network_ninaw10_ioctl);
|
||||
@@ -447,7 +474,7 @@ STATIC int network_ninaw10_socket_poll(mod_network_socket_obj_t *socket, uint32_
|
||||
}
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
for (; !(flags & rwf); mp_hal_delay_ms(5)) {
|
||||
if (nina_socket_poll(socket->fileno, &flags) < 0 || (flags & SOCKET_POLL_ERR)) {
|
||||
if (nina_socket_poll(socket->fileno, &flags) < 0) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_poll(%d) -> errno %d flags %d\n", socket->fileno, *_errno, flags);
|
||||
return -1;
|
||||
@@ -529,10 +556,8 @@ STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *
|
||||
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
|
||||
debug_printf("socket_close(%d)\n", socket->fileno);
|
||||
if (socket->callback != MP_OBJ_NULL) {
|
||||
mp_sched_lock();
|
||||
socket->callback = MP_OBJ_NULL;
|
||||
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
|
||||
mp_sched_unlock();
|
||||
network_ninaw10_poll_list_remove(socket);
|
||||
}
|
||||
if (socket->fileno >= 0) {
|
||||
nina_socket_close(socket->fileno);
|
||||
@@ -740,7 +765,8 @@ STATIC int network_ninaw10_socket_setsockopt(mod_network_socket_obj_t *socket, m
|
||||
mp_sched_lock();
|
||||
socket->callback = (void *)optval;
|
||||
if (socket->callback != MP_OBJ_NULL) {
|
||||
mp_obj_list_append(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
|
||||
network_ninaw10_poll_list_insert(socket);
|
||||
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
|
||||
}
|
||||
mp_sched_unlock();
|
||||
return 0;
|
||||
@@ -804,6 +830,14 @@ STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uin
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC void network_ninaw10_deinit(void) {
|
||||
// On soft-reboot, gc_sweep_all is called and all open sockets are closed
|
||||
// and collected. Make sure that the driver is not keeping any references
|
||||
// to collected sockets in the poll list.
|
||||
soft_timer_remove(&mp_wifi_poll_timer);
|
||||
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t nina_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_ninaw10_active_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_ninaw10_scan_obj) },
|
||||
@@ -827,6 +861,7 @@ STATIC MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
|
||||
|
||||
STATIC const mod_network_nic_protocol_t mod_network_nic_protocol_nina = {
|
||||
.gethostbyname = network_ninaw10_gethostbyname,
|
||||
.deinit = network_ninaw10_deinit,
|
||||
.socket = network_ninaw10_socket_socket,
|
||||
.close = network_ninaw10_socket_close,
|
||||
.bind = network_ninaw10_socket_bind,
|
||||
@@ -852,7 +887,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
||||
);
|
||||
|
||||
MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi);
|
||||
MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer);
|
||||
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list);
|
||||
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_poll_list);
|
||||
|
||||
#endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10
|
||||
|
@@ -38,7 +38,7 @@
|
||||
|
||||
#include "shared/netutils/netutils.h"
|
||||
#include "extmod/modnetwork.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#include "extmod/virtpin.h"
|
||||
#include "modmachine.h"
|
||||
#include "drivers/bus/spi.h"
|
||||
|
@@ -53,10 +53,6 @@
|
||||
#include "nimble/host/src/ble_hs_hci_priv.h"
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME
|
||||
#define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME "MPY NIMBLE"
|
||||
#endif
|
||||
|
||||
#define DEBUG_printf(...) // printf("nimble: " __VA_ARGS__)
|
||||
|
||||
#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV
|
||||
@@ -350,9 +346,6 @@ STATIC void sync_cb(void) {
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
DEBUG_printf("sync_cb: Setting device name\n");
|
||||
ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME);
|
||||
|
||||
mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
@@ -570,7 +563,7 @@ void mp_bluetooth_nimble_port_shutdown(void) {
|
||||
ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL);
|
||||
|
||||
while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_indefinite();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,10 +629,11 @@ int mp_bluetooth_init(void) {
|
||||
// On non-ringbuffer builds (NimBLE on STM32/Unix) this will also poll the UART and run the event queue.
|
||||
mp_uint_t timeout_start_ticks_ms = mp_hal_ticks_ms();
|
||||
while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) {
|
||||
if (mp_hal_ticks_ms() - timeout_start_ticks_ms > NIMBLE_STARTUP_TIMEOUT) {
|
||||
uint32_t elapsed = mp_hal_ticks_ms() - timeout_start_ticks_ms;
|
||||
if (elapsed > NIMBLE_STARTUP_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
mp_event_wait_ms(NIMBLE_STARTUP_TIMEOUT - elapsed);
|
||||
}
|
||||
|
||||
if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) {
|
||||
@@ -1701,7 +1695,7 @@ STATIC int create_l2cap_channel(uint16_t mtu, mp_bluetooth_nimble_l2cap_channel_
|
||||
// multiply that by the "MTUs per channel" (set to 3 above).
|
||||
const size_t buf_blocks = MP_CEIL_DIVIDE(mtu, L2CAP_BUF_BLOCK_SIZE) * L2CAP_BUF_SIZE_MTUS_PER_CHANNEL;
|
||||
|
||||
mp_bluetooth_nimble_l2cap_channel_t *chan = m_new_obj_var(mp_bluetooth_nimble_l2cap_channel_t, uint8_t, OS_MEMPOOL_SIZE(buf_blocks, L2CAP_BUF_BLOCK_SIZE) * sizeof(os_membuf_t));
|
||||
mp_bluetooth_nimble_l2cap_channel_t *chan = m_new_obj_var(mp_bluetooth_nimble_l2cap_channel_t, sdu_mem, uint8_t, OS_MEMPOOL_SIZE(buf_blocks, L2CAP_BUF_BLOCK_SIZE) * sizeof(os_membuf_t));
|
||||
MP_STATE_PORT(bluetooth_nimble_root_pointers)->l2cap_chan = chan;
|
||||
|
||||
// Will be set in BLE_L2CAP_EVENT_COC_CONNECTED or BLE_L2CAP_EVENT_COC_ACCEPT.
|
||||
|
@@ -134,7 +134,11 @@ int nimble_sprintf(char *str, const char *fmt, ...);
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1)
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1)
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("pybd")
|
||||
#ifdef MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME (MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME)
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("MPY NIMBLE")
|
||||
#endif
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31)
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1)
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0)
|
||||
|
@@ -94,6 +94,22 @@ uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags) {
|
||||
}
|
||||
|
||||
int mp_os_dupterm_rx_chr(void) {
|
||||
#if MICROPY_PY_OS_DUPTERM_NOTIFY
|
||||
// When os.dupterm_notify() is enabled it is usually called from a scheduled
|
||||
// function, via mp_os_dupterm_notify(). That can lead to recursive calls of
|
||||
// this function when this function is called from mp_hal_stdin_rx_chr():
|
||||
// - mp_hal_stdin_rx_chr()
|
||||
// - mp_os_dupterm_rx_chr()
|
||||
// - <Python code>
|
||||
// - os.dupterm_notify() is scheduled via interrupt/event
|
||||
// - <Python code> runs scheduled code (eg WebREPL -> rp2.Flash().writeblocks())
|
||||
// - mp_os_dupterm_notify()
|
||||
// - mp_os_dupterm_rx_chr()
|
||||
// Break that cycle by locking the scheduler during this function's duration.
|
||||
mp_sched_lock();
|
||||
#endif
|
||||
|
||||
int ret = -1; // no chars available
|
||||
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
|
||||
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
|
||||
continue;
|
||||
@@ -106,7 +122,8 @@ int mp_os_dupterm_rx_chr(void) {
|
||||
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
|
||||
mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
|
||||
if (errcode == 0 && out_sz != 0) {
|
||||
return buf[0];
|
||||
ret = buf[0];
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
@@ -132,45 +149,63 @@ int mp_os_dupterm_rx_chr(void) {
|
||||
} else {
|
||||
// read 1 byte
|
||||
nlr_pop();
|
||||
if (buf[0] == mp_interrupt_char) {
|
||||
ret = buf[0];
|
||||
if (ret == mp_interrupt_char) {
|
||||
// Signal keyboard interrupt to be raised as soon as the VM resumes
|
||||
mp_sched_keyboard_interrupt();
|
||||
return -2;
|
||||
ret = -2;
|
||||
}
|
||||
return buf[0];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mp_os_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
}
|
||||
}
|
||||
|
||||
// No chars available
|
||||
return -1;
|
||||
#if MICROPY_PY_OS_DUPTERM_NOTIFY
|
||||
mp_sched_unlock();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mp_os_dupterm_tx_strn(const char *str, size_t len) {
|
||||
int mp_os_dupterm_tx_strn(const char *str, size_t len) {
|
||||
// Returns the minimum successful write length, or -1 if no write is attempted.
|
||||
int ret = len;
|
||||
bool did_write = false;
|
||||
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
|
||||
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
|
||||
continue;
|
||||
}
|
||||
did_write = true;
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM
|
||||
if (mp_os_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
|
||||
int errcode = 0;
|
||||
const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
|
||||
stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
|
||||
mp_uint_t written = stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
|
||||
int write_res = MAX(0, written);
|
||||
ret = MIN(write_res, ret);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
|
||||
mp_obj_t written = mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
|
||||
if (written == mp_const_none) {
|
||||
ret = 0;
|
||||
} else if (mp_obj_is_small_int(written)) {
|
||||
int written_int = MAX(0, MP_OBJ_SMALL_INT_VALUE(written));
|
||||
ret = MIN(written_int, ret);
|
||||
}
|
||||
nlr_pop();
|
||||
} else {
|
||||
mp_os_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return did_write ? ret : -1;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_os_dupterm(size_t n_args, const mp_obj_t *args) {
|
||||
|
@@ -1 +0,0 @@
|
||||
|
@@ -99,7 +99,7 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size
|
||||
config->lookahead_buffer = m_new(uint8_t, config->lookahead / 8);
|
||||
#else
|
||||
config->block_cycles = 100;
|
||||
config->cache_size = 4 * MAX(read_size, prog_size);
|
||||
config->cache_size = MIN(config->block_size, (4 * MAX(read_size, prog_size)));
|
||||
config->lookahead_size = lookahead;
|
||||
config->read_buffer = m_new(uint8_t, config->cache_size);
|
||||
config->prog_buffer = m_new(uint8_t, config->cache_size);
|
||||
|
@@ -90,9 +90,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod
|
||||
}
|
||||
|
||||
#if LFS_BUILD_VERSION == 1
|
||||
MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->prog_size);
|
||||
MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->prog_size);
|
||||
#else
|
||||
MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size);
|
||||
MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->cache_size);
|
||||
#endif
|
||||
o->base.type = type;
|
||||
o->vfs = self;
|
||||
|
@@ -46,6 +46,9 @@
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h> // For mkdir etc.
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_vfs_posix_t {
|
||||
mp_obj_base_t base;
|
||||
@@ -55,21 +58,23 @@ typedef struct _mp_obj_vfs_posix_t {
|
||||
} mp_obj_vfs_posix_t;
|
||||
|
||||
STATIC const char *vfs_posix_get_path_str(mp_obj_vfs_posix_t *self, mp_obj_t path) {
|
||||
if (self->root_len == 0) {
|
||||
return mp_obj_str_get_str(path);
|
||||
const char *path_str = mp_obj_str_get_str(path);
|
||||
if (self->root_len == 0 || path_str[0] != '/') {
|
||||
return path_str;
|
||||
} else {
|
||||
self->root.len = self->root_len;
|
||||
vstr_add_str(&self->root, mp_obj_str_get_str(path));
|
||||
self->root.len = self->root_len - 1;
|
||||
vstr_add_str(&self->root, path_str);
|
||||
return vstr_null_terminated_str(&self->root);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path) {
|
||||
if (self->root_len == 0) {
|
||||
const char *path_str = mp_obj_str_get_str(path);
|
||||
if (self->root_len == 0 || path_str[0] != '/') {
|
||||
return path;
|
||||
} else {
|
||||
self->root.len = self->root_len;
|
||||
vstr_add_str(&self->root, mp_obj_str_get_str(path));
|
||||
self->root.len = self->root_len - 1;
|
||||
vstr_add_str(&self->root, path_str);
|
||||
return mp_obj_new_str(self->root.buf, self->root.len);
|
||||
}
|
||||
}
|
||||
@@ -107,7 +112,28 @@ STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
||||
mp_obj_vfs_posix_t *vfs = mp_obj_malloc(mp_obj_vfs_posix_t, type);
|
||||
vstr_init(&vfs->root, 0);
|
||||
if (n_args == 1) {
|
||||
vstr_add_str(&vfs->root, mp_obj_str_get_str(args[0]));
|
||||
const char *root = mp_obj_str_get_str(args[0]);
|
||||
// if the root is relative, make it absolute, otherwise we'll get confused by chdir
|
||||
#ifdef _WIN32
|
||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||
DWORD result = GetFullPathNameA(root, sizeof(buf), buf, NULL);
|
||||
if (result > 0 && result < sizeof(buf)) {
|
||||
vstr_add_str(&vfs->root, buf);
|
||||
} else {
|
||||
mp_raise_OSError(GetLastError());
|
||||
}
|
||||
#else
|
||||
if (root[0] != '\0' && root[0] != '/') {
|
||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||
const char *cwd = getcwd(buf, sizeof(buf));
|
||||
if (cwd == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
vstr_add_str(&vfs->root, cwd);
|
||||
vstr_add_char(&vfs->root, '/');
|
||||
}
|
||||
vstr_add_str(&vfs->root, root);
|
||||
#endif
|
||||
vstr_add_char(&vfs->root, '/');
|
||||
}
|
||||
vfs->root_len = vfs->root.len;
|
||||
@@ -160,7 +186,14 @@ STATIC mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) {
|
||||
if (ret == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
ret += self->root_len;
|
||||
if (self->root_len > 0) {
|
||||
ret += self->root_len - 1;
|
||||
#ifdef _WIN32
|
||||
if (*ret == '\\') {
|
||||
*(char *)ret = '/';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return mp_obj_new_str(ret, strlen(ret));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd);
|
||||
|
@@ -279,14 +279,14 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
|
||||
|
||||
#if MICROPY_PY_SYS_STDIO_BUFFER
|
||||
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO};
|
||||
|
||||
// Forward declarations.
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdin_obj;
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdout_obj;
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stderr_obj;
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdin_obj;
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdout_obj;
|
||||
mp_obj_vfs_posix_file_t mp_sys_stderr_obj;
|
||||
|
||||
STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
if (dest[0] != MP_OBJ_NULL) {
|
||||
@@ -332,8 +332,8 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
||||
locals_dict, &vfs_posix_rawfile_locals_dict
|
||||
);
|
||||
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO};
|
||||
const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO};
|
||||
mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO};
|
||||
|
||||
#endif // MICROPY_VFS_POSIX
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
@@ -34,33 +35,39 @@
|
||||
|
||||
#if MICROPY_READER_VFS
|
||||
|
||||
#ifndef MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE
|
||||
#define MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE (2 * MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf))
|
||||
#endif
|
||||
#define MICROPY_READER_VFS_MIN_BUFFER_SIZE (MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf))
|
||||
#define MICROPY_READER_VFS_MAX_BUFFER_SIZE (255)
|
||||
|
||||
typedef struct _mp_reader_vfs_t {
|
||||
mp_obj_t file;
|
||||
uint16_t len;
|
||||
uint16_t pos;
|
||||
byte buf[24];
|
||||
uint8_t bufpos;
|
||||
uint8_t buflen;
|
||||
uint8_t bufsize;
|
||||
byte buf[];
|
||||
} mp_reader_vfs_t;
|
||||
|
||||
STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) {
|
||||
mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data;
|
||||
if (reader->pos >= reader->len) {
|
||||
if (reader->len < sizeof(reader->buf)) {
|
||||
if (reader->bufpos >= reader->buflen) {
|
||||
if (reader->buflen < reader->bufsize) {
|
||||
return MP_READER_EOF;
|
||||
} else {
|
||||
int errcode;
|
||||
reader->len = mp_stream_rw(reader->file, reader->buf, sizeof(reader->buf),
|
||||
&errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
|
||||
reader->buflen = mp_stream_rw(reader->file, reader->buf, reader->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
|
||||
if (errcode != 0) {
|
||||
// TODO handle errors properly
|
||||
return MP_READER_EOF;
|
||||
}
|
||||
if (reader->len == 0) {
|
||||
if (reader->buflen == 0) {
|
||||
return MP_READER_EOF;
|
||||
}
|
||||
reader->pos = 0;
|
||||
reader->bufpos = 0;
|
||||
}
|
||||
}
|
||||
return reader->buf[reader->pos++];
|
||||
return reader->buf[reader->bufpos++];
|
||||
}
|
||||
|
||||
STATIC void mp_reader_vfs_close(void *data) {
|
||||
@@ -69,19 +76,32 @@ STATIC void mp_reader_vfs_close(void *data) {
|
||||
m_del_obj(mp_reader_vfs_t, reader);
|
||||
}
|
||||
|
||||
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
|
||||
mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t);
|
||||
void mp_reader_new_file(mp_reader_t *reader, qstr filename) {
|
||||
mp_obj_t args[2] = {
|
||||
mp_obj_new_str(filename, strlen(filename)),
|
||||
MP_OBJ_NEW_QSTR(filename),
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
|
||||
};
|
||||
rf->file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map);
|
||||
int errcode;
|
||||
rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
|
||||
mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map);
|
||||
|
||||
const mp_stream_p_t *stream_p = mp_get_stream(file);
|
||||
int errcode = 0;
|
||||
mp_uint_t bufsize = stream_p->ioctl(file, MP_STREAM_GET_BUFFER_SIZE, 0, &errcode);
|
||||
if (bufsize == MP_STREAM_ERROR || bufsize == 0) {
|
||||
// bufsize == 0 is included here to support mpremote v1.21 and older where mount file ioctl
|
||||
// returned 0 by default.
|
||||
bufsize = MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE;
|
||||
} else {
|
||||
bufsize = MIN(MICROPY_READER_VFS_MAX_BUFFER_SIZE, MAX(MICROPY_READER_VFS_MIN_BUFFER_SIZE, bufsize));
|
||||
}
|
||||
|
||||
mp_reader_vfs_t *rf = m_new_obj_var(mp_reader_vfs_t, buf, byte, bufsize);
|
||||
rf->file = file;
|
||||
rf->bufsize = bufsize;
|
||||
rf->buflen = mp_stream_rw(rf->file, rf->buf, rf->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
|
||||
if (errcode != 0) {
|
||||
mp_raise_OSError(errcode);
|
||||
}
|
||||
rf->pos = 0;
|
||||
rf->bufpos = 0;
|
||||
reader->data = rf;
|
||||
reader->readbyte = mp_reader_vfs_readbyte;
|
||||
reader->close = mp_reader_vfs_close;
|
||||
|
1011
lib/littlefs/lfs2.c
1011
lib/littlefs/lfs2.c
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,6 @@
|
||||
#ifndef LFS2_H
|
||||
#define LFS2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "lfs2_util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -23,14 +21,14 @@ extern "C"
|
||||
// Software library version
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS2_VERSION 0x00020005
|
||||
#define LFS2_VERSION 0x00020008
|
||||
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
|
||||
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
|
||||
|
||||
// Version of On-disk data structures
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS2_DISK_VERSION 0x00020000
|
||||
#define LFS2_DISK_VERSION 0x00020001
|
||||
#define LFS2_DISK_VERSION_MAJOR (0xffff & (LFS2_DISK_VERSION >> 16))
|
||||
#define LFS2_DISK_VERSION_MINOR (0xffff & (LFS2_DISK_VERSION >> 0))
|
||||
|
||||
@@ -114,6 +112,8 @@ enum lfs2_type {
|
||||
LFS2_TYPE_SOFTTAIL = 0x600,
|
||||
LFS2_TYPE_HARDTAIL = 0x601,
|
||||
LFS2_TYPE_MOVESTATE = 0x7ff,
|
||||
LFS2_TYPE_CCRC = 0x500,
|
||||
LFS2_TYPE_FCRC = 0x5ff,
|
||||
|
||||
// internal chip sources
|
||||
LFS2_FROM_NOOP = 0x000,
|
||||
@@ -263,6 +263,14 @@ struct lfs2_config {
|
||||
// can help bound the metadata compaction time. Must be <= block_size.
|
||||
// Defaults to block_size when zero.
|
||||
lfs2_size_t metadata_max;
|
||||
|
||||
#ifdef LFS2_MULTIVERSION
|
||||
// On-disk version to use when writing in the form of 16-bit major version
|
||||
// + 16-bit minor version. This limiting metadata to what is supported by
|
||||
// older minor versions. Note that some features will be lost. Defaults to
|
||||
// to the most recent minor version when zero.
|
||||
uint32_t disk_version;
|
||||
#endif
|
||||
};
|
||||
|
||||
// File info structure
|
||||
@@ -280,6 +288,27 @@ struct lfs2_info {
|
||||
char name[LFS2_NAME_MAX+1];
|
||||
};
|
||||
|
||||
// Filesystem info structure
|
||||
struct lfs2_fsinfo {
|
||||
// On-disk version.
|
||||
uint32_t disk_version;
|
||||
|
||||
// Size of a logical block in bytes.
|
||||
lfs2_size_t block_size;
|
||||
|
||||
// Number of logical blocks in filesystem.
|
||||
lfs2_size_t block_count;
|
||||
|
||||
// Upper limit on the length of file names in bytes.
|
||||
lfs2_size_t name_max;
|
||||
|
||||
// Upper limit on the size of files in bytes.
|
||||
lfs2_size_t file_max;
|
||||
|
||||
// Upper limit on the size of custom attributes in bytes.
|
||||
lfs2_size_t attr_max;
|
||||
};
|
||||
|
||||
// Custom attribute structure, used to describe custom attributes
|
||||
// committed atomically during file writes.
|
||||
struct lfs2_attr {
|
||||
@@ -410,6 +439,7 @@ typedef struct lfs2 {
|
||||
} free;
|
||||
|
||||
const struct lfs2_config *cfg;
|
||||
lfs2_size_t block_count;
|
||||
lfs2_size_t name_max;
|
||||
lfs2_size_t file_max;
|
||||
lfs2_size_t attr_max;
|
||||
@@ -534,8 +564,8 @@ int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
|
||||
// are values from the enum lfs2_open_flags that are bitwise-ored together.
|
||||
//
|
||||
// The config struct provides additional config options per file as described
|
||||
// above. The config struct must be allocated while the file is open, and the
|
||||
// config struct must be zeroed for defaults and backwards compatibility.
|
||||
// above. The config struct must remain allocated while the file is open, and
|
||||
// the config struct must be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
|
||||
@@ -659,6 +689,12 @@ int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir);
|
||||
|
||||
/// Filesystem-level filesystem operations
|
||||
|
||||
// Find on-disk info about the filesystem
|
||||
//
|
||||
// Fills out the fsinfo structure based on the filesystem found on-disk.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs2_fs_stat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo);
|
||||
|
||||
// Finds the current size of the filesystem
|
||||
//
|
||||
// Note: Result is best effort. If files share COW structures, the returned
|
||||
@@ -676,6 +712,40 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2);
|
||||
// Returns a negative error code on failure.
|
||||
int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data);
|
||||
|
||||
// Attempt to proactively find free blocks
|
||||
//
|
||||
// Calling this function is not required, but may allowing the offloading of
|
||||
// the expensive block allocation scan to a less time-critical code path.
|
||||
//
|
||||
// Note: littlefs currently does not persist any found free blocks to disk.
|
||||
// This may change in the future.
|
||||
//
|
||||
// Returns a negative error code on failure. Finding no free blocks is
|
||||
// not an error.
|
||||
int lfs2_fs_gc(lfs2_t *lfs2);
|
||||
|
||||
#ifndef LFS2_READONLY
|
||||
// Attempt to make the filesystem consistent and ready for writing
|
||||
//
|
||||
// Calling this function is not required, consistency will be implicitly
|
||||
// enforced on the first operation that writes to the filesystem, but this
|
||||
// function allows the work to be performed earlier and without other
|
||||
// filesystem changes.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs2_fs_mkconsistent(lfs2_t *lfs2);
|
||||
#endif
|
||||
|
||||
#ifndef LFS2_READONLY
|
||||
// Grows the filesystem to a new size, updating the superblock with the new
|
||||
// block count.
|
||||
//
|
||||
// Note: This is irreversible.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count);
|
||||
#endif
|
||||
|
||||
#ifndef LFS2_READONLY
|
||||
#ifdef LFS2_MIGRATE
|
||||
// Attempts to migrate a previous version of littlefs
|
||||
|
@@ -167,10 +167,9 @@ static inline int lfs2_scmp(uint32_t a, uint32_t b) {
|
||||
|
||||
// Convert between 32-bit little-endian and native order
|
||||
static inline uint32_t lfs2_fromle32(uint32_t a) {
|
||||
#if !defined(LFS2_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
#if (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
return a;
|
||||
#elif !defined(LFS2_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
@@ -196,10 +195,9 @@ static inline uint32_t lfs2_frombe32(uint32_t a) {
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#elif !defined(LFS2_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
#elif (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
return a;
|
||||
#else
|
||||
return (((uint8_t*)&a)[0] << 24) |
|
||||
|
@@ -45,10 +45,6 @@
|
||||
#include "mbedtls/aes.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C)
|
||||
#include "mbedtls/arc4.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
#include "mbedtls/aria.h"
|
||||
#endif
|
||||
@@ -65,10 +61,6 @@
|
||||
#include "mbedtls/bignum.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BLOWFISH_C)
|
||||
#include "mbedtls/blowfish.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
#include "mbedtls/camellia.h"
|
||||
#endif
|
||||
@@ -89,10 +81,6 @@
|
||||
#include "mbedtls/cipher.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
#include "mbedtls/cmac.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CTR_DRBG_C)
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#endif
|
||||
@@ -113,6 +101,14 @@
|
||||
#include "mbedtls/entropy.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C)
|
||||
#include "mbedtls/error.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#include "mbedtls/gcm.h"
|
||||
#endif
|
||||
@@ -125,22 +121,14 @@
|
||||
#include "mbedtls/hmac_drbg.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_LMS_C)
|
||||
#include "mbedtls/lms.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
#include "mbedtls/md.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD2_C)
|
||||
#include "mbedtls/md2.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
#include "mbedtls/md4.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MD5_C)
|
||||
#include "mbedtls/md5.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#endif
|
||||
@@ -149,10 +137,6 @@
|
||||
#include "mbedtls/oid.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PADLOCK_C)
|
||||
#include "mbedtls/padlock.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
|
||||
#include "mbedtls/pem.h"
|
||||
#endif
|
||||
@@ -169,18 +153,14 @@
|
||||
#include "mbedtls/pkcs5.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#if defined(MBEDTLS_PKCS7_C)
|
||||
#include "mbedtls/pkcs7.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
#include "mbedtls/poly1305.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
#include "mbedtls/ripemd160.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
#include "mbedtls/rsa.h"
|
||||
#endif
|
||||
@@ -209,10 +189,6 @@
|
||||
#include "mbedtls/x509.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_XTEA_C)
|
||||
#include "mbedtls/xtea.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Error code table type
|
||||
struct ssl_errs {
|
||||
@@ -231,7 +207,6 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED), "CIPHER_FULL_BLOCK_EXPECTED" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_AUTH_FAILED), "CIPHER_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT), "CIPHER_INVALID_CONTEXT" },
|
||||
{ -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED), "CIPHER_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CIPHER_C */
|
||||
|
||||
#if defined(MBEDTLS_DHM_C)
|
||||
@@ -244,7 +219,6 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_DHM_INVALID_FORMAT), "DHM_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_DHM_ALLOC_FAILED), "DHM_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_FILE_IO_ERROR), "DHM_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED), "DHM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED), "DHM_SET_GROUP_FAILED" },
|
||||
#endif /* MBEDTLS_DHM_C */
|
||||
|
||||
@@ -257,7 +231,6 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_ECP_RANDOM_FAILED), "ECP_RANDOM_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_INVALID_KEY), "ECP_INVALID_KEY" },
|
||||
{ -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH), "ECP_SIG_LEN_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED), "ECP_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_ECP_IN_PROGRESS), "ECP_IN_PROGRESS" },
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
@@ -266,7 +239,6 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_MD_BAD_INPUT_DATA), "MD_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_MD_ALLOC_FAILED), "MD_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_MD_FILE_IO_ERROR), "MD_FILE_IO_ERROR" },
|
||||
{ -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED), "MD_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
|
||||
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
|
||||
@@ -296,7 +268,7 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE), "PK_UNKNOWN_NAMED_CURVE" },
|
||||
{ -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE), "PK_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH), "PK_SIG_LEN_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED), "PK_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL), "PK_BUFFER_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_PK_C */
|
||||
|
||||
#if defined(MBEDTLS_PKCS12_C)
|
||||
@@ -313,6 +285,21 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH), "PKCS5_PASSWORD_MISMATCH" },
|
||||
#endif /* MBEDTLS_PKCS5_C */
|
||||
|
||||
#if defined(MBEDTLS_PKCS7_C)
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT), "PKCS7_INVALID_FORMAT" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE), "PKCS7_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_VERSION), "PKCS7_INVALID_VERSION" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO), "PKCS7_INVALID_CONTENT_INFO" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_ALG), "PKCS7_INVALID_ALG" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_CERT), "PKCS7_INVALID_CERT" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE), "PKCS7_INVALID_SIGNATURE" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO), "PKCS7_INVALID_SIGNER_INFO" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA), "PKCS7_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED), "PKCS7_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL), "PKCS7_VERIFY_FAIL" },
|
||||
{ -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID), "PKCS7_CERT_DATE_INVALID" },
|
||||
#endif /* MBEDTLS_PKCS7_C */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
{ -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA), "RSA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_RSA_INVALID_PADDING), "RSA_INVALID_PADDING" },
|
||||
@@ -323,45 +310,34 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_RSA_VERIFY_FAILED), "RSA_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE), "RSA_OUTPUT_TOO_LARGE" },
|
||||
{ -(MBEDTLS_ERR_RSA_RNG_FAILED), "RSA_RNG_FAILED" },
|
||||
{ -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION), "RSA_UNSUPPORTED_OPERATION" },
|
||||
{ -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED), "RSA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
{ -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
|
||||
{ -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE), "SSL_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA), "SSL_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_MAC), "SSL_INVALID_MAC" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_RECORD), "SSL_INVALID_RECORD" },
|
||||
{ -(MBEDTLS_ERR_SSL_CONN_EOF), "SSL_CONN_EOF" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER), "SSL_UNKNOWN_CIPHER" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN), "SSL_NO_CIPHER_CHOSEN" },
|
||||
{ -(MBEDTLS_ERR_SSL_DECODE_ERROR), "SSL_DECODE_ERROR" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_RNG), "SSL_NO_RNG" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE), "SSL_NO_CLIENT_CERTIFICATE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE), "SSL_CERTIFICATE_TOO_LARGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED), "SSL_CERTIFICATE_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION), "SSL_UNSUPPORTED_EXTENSION" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL), "SSL_NO_APPLICATION_PROTOCOL" },
|
||||
{ -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED), "SSL_PRIVATE_KEY_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED), "SSL_CA_CHAIN_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE), "SSL_UNEXPECTED_MESSAGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED), "SSL_PEER_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME), "SSL_UNRECOGNIZED_NAME" },
|
||||
{ -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY), "SSL_PEER_CLOSE_NOTIFY" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO), "SSL_BAD_HS_CLIENT_HELLO" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO), "SSL_BAD_HS_SERVER_HELLO" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE), "SSL_BAD_HS_CERTIFICATE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST), "SSL_BAD_HS_CERTIFICATE_REQUEST" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE), "SSL_BAD_HS_SERVER_KEY_EXCHANGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE), "SSL_BAD_HS_SERVER_HELLO_DONE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY), "SSL_BAD_HS_CERTIFICATE_VERIFY" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC), "SSL_BAD_HS_CHANGE_CIPHER_SPEC" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED), "SSL_BAD_HS_FINISHED" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE), "SSL_BAD_CERTIFICATE" },
|
||||
{ -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET), "SSL_RECEIVED_NEW_SESSION_TICKET" },
|
||||
{ -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA), "SSL_CANNOT_READ_EARLY_DATA" },
|
||||
{ -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA), "SSL_CANNOT_WRITE_EARLY_DATA" },
|
||||
{ -(MBEDTLS_ERR_SSL_ALLOC_FAILED), "SSL_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED), "SSL_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH), "SSL_HW_ACCEL_FALLTHROUGH" },
|
||||
{ -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED), "SSL_COMPRESSION_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION), "SSL_BAD_HS_PROTOCOL_VERSION" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET), "SSL_BAD_HS_NEW_SESSION_TICKET" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION), "SSL_BAD_PROTOCOL_VERSION" },
|
||||
{ -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE), "SSL_HANDSHAKE_FAILURE" },
|
||||
{ -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED), "SSL_SESSION_TICKET_EXPIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH), "SSL_PK_TYPE_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY), "SSL_UNKNOWN_IDENTITY" },
|
||||
@@ -370,18 +346,18 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO), "SSL_WAITING_SERVER_HELLO_RENEGO" },
|
||||
{ -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED), "SSL_HELLO_VERIFY_REQUIRED" },
|
||||
{ -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL), "SSL_BUFFER_TOO_SMALL" },
|
||||
{ -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE), "SSL_NO_USABLE_CIPHERSUITE" },
|
||||
{ -(MBEDTLS_ERR_SSL_WANT_READ), "SSL_WANT_READ" },
|
||||
{ -(MBEDTLS_ERR_SSL_WANT_WRITE), "SSL_WANT_WRITE" },
|
||||
{ -(MBEDTLS_ERR_SSL_TIMEOUT), "SSL_TIMEOUT" },
|
||||
{ -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT), "SSL_CLIENT_RECONNECT" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD), "SSL_UNEXPECTED_RECORD" },
|
||||
{ -(MBEDTLS_ERR_SSL_NON_FATAL), "SSL_NON_FATAL" },
|
||||
{ -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH), "SSL_INVALID_VERIFY_HASH" },
|
||||
{ -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER), "SSL_ILLEGAL_PARAMETER" },
|
||||
{ -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
|
||||
{ -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
|
||||
{ -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
|
||||
{ -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
|
||||
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_CID), "SSL_UNEXPECTED_CID" },
|
||||
{ -(MBEDTLS_ERR_SSL_VERSION_MISMATCH), "SSL_VERSION_MISMATCH" },
|
||||
{ -(MBEDTLS_ERR_SSL_BAD_CONFIG), "SSL_BAD_CONFIG" },
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
@@ -418,19 +394,11 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH), "AES_INVALID_KEY_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH), "AES_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_AES_BAD_INPUT_DATA), "AES_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE), "AES_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED), "AES_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_AES_C */
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C)
|
||||
{ -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED), "ARC4_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_ARC4_C */
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
{ -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA), "ARIA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH), "ARIA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE), "ARIA_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED), "ARIA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_ARIA_C */
|
||||
|
||||
#if defined(MBEDTLS_ASN1_PARSE_C)
|
||||
@@ -459,28 +427,18 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_MPI_ALLOC_FAILED), "MPI_ALLOC_FAILED" },
|
||||
#endif /* MBEDTLS_BIGNUM_C */
|
||||
|
||||
#if defined(MBEDTLS_BLOWFISH_C)
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA), "BLOWFISH_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH), "BLOWFISH_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED), "BLOWFISH_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_BLOWFISH_C */
|
||||
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA), "CAMELLIA_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH), "CAMELLIA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED), "CAMELLIA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CAMELLIA_C */
|
||||
|
||||
#if defined(MBEDTLS_CCM_C)
|
||||
{ -(MBEDTLS_ERR_CCM_BAD_INPUT), "CCM_BAD_INPUT" },
|
||||
{ -(MBEDTLS_ERR_CCM_AUTH_FAILED), "CCM_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED), "CCM_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
{ -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA), "CHACHA20_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE), "CHACHA20_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED), "CHACHA20_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CHACHA20_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
@@ -488,10 +446,6 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED), "CHACHAPOLY_AUTH_FAILED" },
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
{ -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED), "CMAC_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_CMAC_C */
|
||||
|
||||
#if defined(MBEDTLS_CTR_DRBG_C)
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED), "CTR_DRBG_ENTROPY_SOURCE_FAILED" },
|
||||
{ -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG), "CTR_DRBG_REQUEST_TOO_BIG" },
|
||||
@@ -501,7 +455,6 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
{ -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH), "DES_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED), "DES_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_DES_C */
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
@@ -512,10 +465,20 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
|
||||
#endif /* MBEDTLS_ENTROPY_C */
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C)
|
||||
{ -(MBEDTLS_ERR_ERROR_GENERIC_ERROR), "ERROR_GENERIC_ERROR" },
|
||||
{ -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED), "ERROR_CORRUPTION_DETECTED" },
|
||||
#endif /* MBEDTLS_ERROR_C */
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
{ -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
{ -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
|
||||
{ -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_GCM_BAD_INPUT), "GCM_BAD_INPUT" },
|
||||
{ -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL), "GCM_BUFFER_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
@@ -529,17 +492,13 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED), "HMAC_DRBG_ENTROPY_SOURCE_FAILED" },
|
||||
#endif /* MBEDTLS_HMAC_DRBG_C */
|
||||
|
||||
#if defined(MBEDTLS_MD2_C)
|
||||
{ -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED), "MD2_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD2_C */
|
||||
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
{ -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED), "MD4_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD4_C */
|
||||
|
||||
#if defined(MBEDTLS_MD5_C)
|
||||
{ -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED), "MD5_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_MD5_C */
|
||||
#if defined(MBEDTLS_LMS_C)
|
||||
{ -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA), "LMS_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS), "LMS_OUT_OF_PRIVATE_KEYS" },
|
||||
{ -(MBEDTLS_ERR_LMS_VERIFY_FAILED), "LMS_VERIFY_FAILED" },
|
||||
{ -(MBEDTLS_ERR_LMS_ALLOC_FAILED), "LMS_ALLOC_FAILED" },
|
||||
{ -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL), "LMS_BUFFER_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_LMS_C */
|
||||
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
{ -(MBEDTLS_ERR_NET_SOCKET_FAILED), "NET_SOCKET_FAILED" },
|
||||
@@ -562,50 +521,26 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
|
||||
{ -(MBEDTLS_ERR_OID_BUF_TOO_SMALL), "OID_BUF_TOO_SMALL" },
|
||||
#endif /* MBEDTLS_OID_C */
|
||||
|
||||
#if defined(MBEDTLS_PADLOCK_C)
|
||||
{ -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED), "PADLOCK_DATA_MISALIGNED" },
|
||||
#endif /* MBEDTLS_PADLOCK_C */
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
{ -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
{ -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA), "POLY1305_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE), "POLY1305_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED), "POLY1305_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_POLY1305_C */
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
{ -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED), "RIPEMD160_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_RIPEMD160_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
{ -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED), "SHA1_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA), "SHA1_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA1_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
{ -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED), "SHA256_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA), "SHA256_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA256_C */
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
{ -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED), "SHA512_HW_ACCEL_FAILED" },
|
||||
{ -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA), "SHA512_BAD_INPUT_DATA" },
|
||||
#endif /* MBEDTLS_SHA512_C */
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
{ -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE), "THREADING_FEATURE_UNAVAILABLE" },
|
||||
{ -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA), "THREADING_BAD_INPUT_DATA" },
|
||||
{ -(MBEDTLS_ERR_THREADING_MUTEX_ERROR), "THREADING_MUTEX_ERROR" },
|
||||
#endif /* MBEDTLS_THREADING_C */
|
||||
|
||||
#if defined(MBEDTLS_XTEA_C)
|
||||
{ -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH), "XTEA_INVALID_INPUT_LENGTH" },
|
||||
{ -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED), "XTEA_HW_ACCEL_FAILED" },
|
||||
#endif /* MBEDTLS_XTEA_C */
|
||||
// END generated code
|
||||
};
|
||||
|
||||
@@ -655,7 +590,7 @@ void mbedtls_strerror(int ret, char *buf, size_t buflen) {
|
||||
if (got_hl) {
|
||||
use_ret = ret & 0xFF80;
|
||||
|
||||
// special case
|
||||
// special case, don't try to translate low level code
|
||||
#if defined(MBEDTLS_SSL_TLS_C)
|
||||
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
|
||||
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user