diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index c5039f58b54dc..690e5f46a4fc0 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,27 @@ +# all: Update Python formatting to ruff-format. +bbd8760bd9a2302e5abee29db279102bb11d7732 + +# all: Fix various spelling mistakes found by codespell 2.2.6. +cf490a70917a1b2d38ba9b58e763e0837d0f7ca7 + +# all: Fix spelling mistakes based on codespell check. +b1229efbd1509654dec6053865ab828d769e29db + +# top: Update Python formatting to black "2023 stable style". +8b2748269244304854b3462cb8902952b4dcb892 + +# all: Reformat remaining C code that doesn't have a space after a comma. +5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d + +# ports: Reformat more C and Python source code. +5c32111fa0e31e451b0f1666bdf926be2fdfd82c + +# all: Update Python formatting to latest Black version 22.1.0. +ab2923dfa1174dc177f0a90cb00a7e4ff87958d2 + +# all: Update Python formatting to latest Black version 21.12b0. +3770fab33449a5dadf8eb06edfae0767e75320a6 + # tools/gen-cpydiff.py: Fix formatting of doc strings for new Black. 0f78c36c5aa458a954eed39a46942209107a553e diff --git a/.gitattributes b/.gitattributes index e6d31d6aa31fc..2d8496db50488 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..7bad9562964af --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug report +about: Report an issue +title: '' +labels: bug +assignees: '' + +--- + +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead. + +* In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it. + +* If this issue involves external hardware, please include links to relevant datasheets and schematics. + +* If you are seeing code being executed incorrectly, please provide a minimal example and expected output (e.g. comparison to CPython). + +* For build issues, please include full details of your environment, compiler versions, command lines, and build output. + +* Please provide as much information as possible about the version of MicroPython you're running, such as: + - firmware file name + - git commit hash and port/board + - version information shown in the REPL (hit Ctrl-B to see the startup message) + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..f3662464da337 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: MicroPython GitHub Discussions + url: https://github.com/orgs/micropython/discussions + about: Community discussion about all things MicroPython. This is the best place to start if you have questions about using MicroPython or getting started with MicroPython development. + - name: MicroPython Documentation + url: https://docs.micropython.org/ + about: Documentation for using and working with MicroPython and libraries. + - name: MicroPython Downloads + url: https://micropython.org/download/ + about: Pre-built firmware and information for most supported boards. diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000000000..e36fa62ac29a4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,16 @@ +--- +name: Documentation issue +about: Report areas of the documentation or examples that need improvement +title: 'docs: ' +labels: documentation +assignees: '' + +--- + +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab instead. + +* Describe what was missing from the documentation and/or what was incorrect/incomplete. + +* If possible, please link to the relevant page on https://docs.micropython.org/ + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..81b55d98e0da8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: Feature request +about: Request a feature or improvement +title: '' +labels: enhancement +assignees: '' + +--- + +* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead. + +* Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library). + +* For core Python features, where possible please include a link to the relevant PEP. + +* For new architectures / ports / boards, please provide links to relevant documentation, specifications, and toolchains. Any information about the popularity and unique features about this hardware would also be useful. + +* For features for existing ports (e.g. new peripherals or microcontroller features), please describe which port(s) it applies too, and whether this is could be an extension to the machine API or a port-specific module? + +* For drivers (e.g. for external hardware), please link to datasheets and/or existing drivers from other sources. + +* Who do you expect will implement the feature you are requesting? Would you be willing to sponsor this work? + +* Remove all placeholder text above before submitting. diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md new file mode 100644 index 0000000000000..cfe4a4befdb14 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/security.md @@ -0,0 +1,16 @@ +--- +name: Security report +about: Report a security issue or vulnerability in MicroPython +title: '' +labels: security +assignees: '' + +--- + +* If you need to raise this issue privately with the MicroPython team, please email contact@micropython.org instead. + +* Include a clear and concise description of what the security issue is. + +* What does this issue allow an attacker to do? + +* Remove all placeholder text above before submitting. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..2c7d1708395e2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index aab347d78e97d..9f30f048cfdbe 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -2,15 +2,19 @@ name: Check code formatting on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - build: - runs-on: ubuntu-latest + code-formatting: + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + - uses: actions/checkout@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 diff --git a/.github/workflows/code_size.yml b/.github/workflows/code_size.yml index 7570261e7d23b..a65a00201a7d2 100644 --- a/.github/workflows/code_size.yml +++ b/.github/workflows/code_size.yml @@ -12,11 +12,15 @@ on: - 'ports/bare-arm/**' - 'ports/minimal/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 100 - name: Install packages @@ -24,4 +28,18 @@ jobs: - name: Build run: source tools/ci.sh && ci_code_size_build - name: Compute code size difference - run: tools/metrics.py diff --error-threshold 0 ~/size0 ~/size1 + run: tools/metrics.py diff ~/size0 ~/size1 | tee diff + - name: Save PR number + if: github.event_name == 'pull_request' + env: + PR_NUMBER: ${{ github.event.number }} + run: echo $PR_NUMBER > pr_number + - name: Upload diff + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: code-size-report + path: | + diff + pr_number + retention-days: 1 diff --git a/.github/workflows/code_size_comment.yml b/.github/workflows/code_size_comment.yml new file mode 100644 index 0000000000000..a394f7a14b054 --- /dev/null +++ b/.github/workflows/code_size_comment.yml @@ -0,0 +1,105 @@ +name: Code size comment + +on: + workflow_run: + workflows: [Check code size] + types: [completed] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + comment: + runs-on: ubuntu-20.04 + steps: + - name: 'Download artifact' + id: download-artifact + uses: actions/github-script@v7 + with: + result-encoding: string + script: | + const fs = require('fs'); + + const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + + const matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "code-size-report" + }); + + if (matchArtifact.length === 0) { + console.log('no matching artifact found'); + console.log('result: "skip"'); + + return 'skip'; + } + + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact[0].id, + archive_format: 'zip', + }); + + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/code-size-report.zip`, Buffer.from(download.data)); + + console.log('artifact downloaded to `code-size-report.zip`'); + console.log('result: "ok"'); + + return 'ok'; + - name: 'Unzip artifact' + if: steps.download-artifact.outputs.result == 'ok' + run: unzip code-size-report.zip + - name: Post comment to pull request + if: steps.download-artifact.outputs.result == 'ok' + uses: actions/github-script@v7 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const fs = require('fs'); + + const prNumber = Number(fs.readFileSync('pr_number')); + const codeSizeReport = `Code size report: + + \`\`\` + ${fs.readFileSync('diff')} + \`\`\` + `; + + const comments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + } + ); + + comments.reverse(); + + const previousComment = comments.find(comment => + comment.user.login === 'github-actions[bot]' + ) + + // if github-actions[bot] already made a comment, update it, + // otherwise create a new comment. + + if (previousComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: previousComment.id, + body: codeSizeReport, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: codeSizeReport, + }); + } diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000000..2d8b4627aac2d --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,13 @@ +name: Check spelling with codespell + +on: [push, pull_request] + +jobs: + codespell: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # codespell version should be kept in sync with .pre-commit-config.yml + - run: pip install --user codespell==2.2.6 tomli + - run: codespell + diff --git a/.github/workflows/commit_formatting.yml b/.github/workflows/commit_formatting.yml index 5f96fbb934426..3fdcabc4ca73f 100644 --- a/.github/workflows/commit_formatting.yml +++ b/.github/workflows/commit_formatting.yml @@ -2,13 +2,17 @@ name: Check commit message formatting on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: '100' - - uses: actions/setup-python@v1 + - uses: actions/setup-python@v5 - name: Check commit message formatting run: source tools/ci.sh && ci_commit_formatting_run diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ec6b4c7f1962a..d01a4b50c9810 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,18 +1,23 @@ name: Build docs on: + push: pull_request: paths: - docs/** +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 - name: Install Python packages - run: pip install Sphinx + run: pip install -r docs/requirements.txt - name: Build docs run: make -C docs/ html diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000000000..6613f106625a2 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,25 @@ +name: Check examples + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'examples/**' + - 'ports/unix/**' + - 'py/**' + - 'shared/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + embedding: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding + - name: Run + run: ./examples/embedding/embed | grep "hello world" diff --git a/.github/workflows/mpremote.yml b/.github/workflows/mpremote.yml new file mode 100644 index 0000000000000..ee91b6360b9b4 --- /dev/null +++ b/.github/workflows/mpremote.yml @@ -0,0 +1,29 @@ +name: Package mpremote + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'tools/**' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # 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@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@v4 + with: + name: mpremote + path: | + tools/mpremote/dist/mpremote*.whl diff --git a/.github/workflows/mpy_format.yml b/.github/workflows/mpy_format.yml new file mode 100644 index 0000000000000..baa02ce08d507 --- /dev/null +++ b/.github/workflows/mpy_format.yml @@ -0,0 +1,24 @@ +name: .mpy file format and tools + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'examples/**' + - 'tests/**' + - 'tools/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-20.04 # use 20.04 to get python2 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: source tools/ci.sh && ci_mpy_format_setup + - name: Test mpy-tool.py + run: source tools/ci.sh && ci_mpy_format_test diff --git a/.github/workflows/ports.yml b/.github/workflows/ports.yml new file mode 100644 index 0000000000000..1f262b0ba4bee --- /dev/null +++ b/.github/workflows/ports.yml @@ -0,0 +1,22 @@ +name: Build ports metadata + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'tools/**' + - ports/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build ports download metadata + run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards diff --git a/.github/workflows/ports_cc3200.yml b/.github/workflows/ports_cc3200.yml index 0eaa36da3796e..f178a140587db 100644 --- a/.github/workflows/ports_cc3200.yml +++ b/.github/workflows/ports_cc3200.yml @@ -8,15 +8,20 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/cc3200/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_cc3200_setup - name: Build diff --git a/.github/workflows/ports_esp32.yml b/.github/workflows/ports_esp32.yml index de88de3755421..45808b659add7 100644 --- a/.github/workflows/ports_esp32.yml +++ b/.github/workflows/ports_esp32.yml @@ -8,25 +8,50 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/esp32/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - build_idf402: + 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@v2 - - name: Install packages - run: source tools/ci.sh && ci_esp32_idf402_setup - - name: Build - run: source tools/ci.sh && ci_esp32_build + - uses: actions/checkout@v4 - build_idf44: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - name: Install packages - run: source tools/ci.sh && ci_esp32_idf44_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@v4 + 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 }} diff --git a/.github/workflows/ports_esp8266.yml b/.github/workflows/ports_esp8266.yml index f4ce1f8212d87..5236edf40b959 100644 --- a/.github/workflows/ports_esp8266.yml +++ b/.github/workflows/ports_esp8266.yml @@ -8,15 +8,20 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/esp8266/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH - name: Build diff --git a/.github/workflows/ports_javascript.yml b/.github/workflows/ports_javascript.yml deleted file mode 100644 index 244dc966aa6d9..0000000000000 --- a/.github/workflows/ports_javascript.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: javascript port - -on: - push: - pull_request: - paths: - - '.github/workflows/*.yml' - - 'tools/**' - - 'py/**' - - 'extmod/**' - - 'lib/**' - - 'ports/javascript/**' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install packages - run: source tools/ci.sh && ci_javascript_setup - - name: Build - run: source tools/ci.sh && ci_javascript_build - - name: Run tests - run: source tools/ci.sh && ci_javascript_run_tests diff --git a/.github/workflows/ports_mimxrt.yml b/.github/workflows/ports_mimxrt.yml index 8fbc2209e4139..9e782bf63b31c 100644 --- a/.github/workflows/ports_mimxrt.yml +++ b/.github/workflows/ports_mimxrt.yml @@ -8,15 +8,25 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/mimxrt/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-20.04 + defaults: + run: + working-directory: 'micropython repo' # test build with space in path steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + path: 'micropython repo' - name: Install packages run: source tools/ci.sh && ci_mimxrt_setup - name: Build diff --git a/.github/workflows/ports_nrf.yml b/.github/workflows/ports_nrf.yml index 1ba3b0ce61e96..d9cffb9778cba 100644 --- a/.github/workflows/ports_nrf.yml +++ b/.github/workflows/ports_nrf.yml @@ -8,15 +8,20 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/nrf/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_nrf_setup - name: Build diff --git a/.github/workflows/ports_powerpc.yml b/.github/workflows/ports_powerpc.yml index 88fa59767b756..c41b13e5ddffe 100644 --- a/.github/workflows/ports_powerpc.yml +++ b/.github/workflows/ports_powerpc.yml @@ -8,15 +8,20 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/powerpc/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_powerpc_setup - name: Build diff --git a/.github/workflows/ports_qemu-arm.yml b/.github/workflows/ports_qemu-arm.yml index 8d144ca3cb7aa..db3cd7871d591 100644 --- a/.github/workflows/ports_qemu-arm.yml +++ b/.github/workflows/ports_qemu-arm.yml @@ -8,20 +8,25 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/qemu-arm/**' - 'tests/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build_and_test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_qemu_arm_setup - name: Build and run test suite run: source tools/ci.sh && ci_qemu_arm_build - name: Print failures if: failure() - run: grep --text "FAIL" ports/qemu-arm/build/console.out + run: grep --before-context=100 --text "FAIL" ports/qemu-arm/build/console.out diff --git a/.github/workflows/ports_renesas-ra.yml b/.github/workflows/ports_renesas-ra.yml new file mode 100644 index 0000000000000..b1a30c2f11798 --- /dev/null +++ b/.github/workflows/ports_renesas-ra.yml @@ -0,0 +1,29 @@ +name: renesas-ra port + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'tools/**' + - 'py/**' + - 'extmod/**' + - 'shared/**' + - 'lib/**' + - 'drivers/**' + - 'ports/renesas-ra/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_renesas_ra_board: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: source tools/ci.sh && ci_renesas_ra_setup + - name: Build + run: source tools/ci.sh && ci_renesas_ra_board_build + diff --git a/.github/workflows/ports_rp2.yml b/.github/workflows/ports_rp2.yml index 668b79cae256c..748f38e143893 100644 --- a/.github/workflows/ports_rp2.yml +++ b/.github/workflows/ports_rp2.yml @@ -8,15 +8,25 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/rp2/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest + defaults: + run: + working-directory: 'micropython repo' # test build with space in path steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + path: 'micropython repo' - name: Install packages run: source tools/ci.sh && ci_rp2_setup - name: Build diff --git a/.github/workflows/ports_samd.yml b/.github/workflows/ports_samd.yml index bde4ed965faa0..5bf1826cd17bb 100644 --- a/.github/workflows/ports_samd.yml +++ b/.github/workflows/ports_samd.yml @@ -8,15 +8,20 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/samd/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_samd_setup - name: Build diff --git a/.github/workflows/ports_stm32.yml b/.github/workflows/ports_stm32.yml index 4634339c96a6a..84d30b27f6e66 100644 --- a/.github/workflows/ports_stm32.yml +++ b/.github/workflows/ports_stm32.yml @@ -8,25 +8,28 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'drivers/**' - 'ports/stm32/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + 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@v2 + - 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@v2 - - name: Install packages - run: source tools/ci.sh && ci_stm32_setup - - name: Build - run: source tools/ci.sh && ci_stm32_nucleo_build diff --git a/.github/workflows/ports_teensy.yml b/.github/workflows/ports_teensy.yml deleted file mode 100644 index 7ae77c80af604..0000000000000 --- a/.github/workflows/ports_teensy.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: teensy port - -on: - push: - pull_request: - paths: - - '.github/workflows/*.yml' - - 'tools/**' - - 'py/**' - - 'extmod/**' - - 'lib/**' - - 'drivers/**' - - 'ports/teensy/**' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install packages - run: source tools/ci.sh && ci_teensy_setup - - name: Build - run: source tools/ci.sh && ci_teensy_build diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 4e75172b64f46..2367eddbe6ea5 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -8,16 +8,22 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'examples/**' + - 'mpy-cross/**' - 'ports/unix/**' - 'tests/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: minimal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_minimal_build - name: Run main test suite @@ -29,36 +35,34 @@ jobs: reproducible: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build with reproducible date run: source tools/ci.sh && ci_unix_minimal_build env: SOURCE_DATE_EPOCH: 1234567890 - name: Check reproducible build date - run: echo | ports/unix/micropython-minimal -i | grep 'on 2009-02-13;' + run: echo | ports/unix/build-minimal/micropython -i | grep 'on 2009-02-13;' standard: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_standard_build - name: Run main test suite run: source tools/ci.sh && ci_unix_standard_run_tests - - name: Run performance benchmarks - run: source tools/ci.sh && ci_unix_standard_run_perfbench - name: Print failures if: failure() run: tests/run-tests.py --print-failures - dev: + standard_v2: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build - run: source tools/ci.sh && ci_unix_dev_build + run: source tools/ci.sh && ci_unix_standard_v2_build - name: Run main test suite - run: source tools/ci.sh && ci_unix_dev_run_tests + run: source tools/ci.sh && ci_unix_standard_v2_run_tests - name: Print failures if: failure() run: tests/run-tests.py --print-failures @@ -66,13 +70,15 @@ jobs: coverage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_coverage_setup - name: Build run: source tools/ci.sh && ci_unix_coverage_build - name: Run main test suite run: source tools/ci.sh && ci_unix_coverage_run_tests + - name: Test merging .mpy files + run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests - name: Build native mpy modules run: source tools/ci.sh && ci_native_mpy_modules_build - name: Test importing .mpy generated by mpy_ld.py @@ -82,7 +88,7 @@ jobs: (cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true) (cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true) - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: fail_ci_if_error: true verbose: true @@ -91,9 +97,9 @@ jobs: run: tests/run-tests.py --print-failures coverage_32bit: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -109,9 +115,9 @@ jobs: run: tests/run-tests.py --print-failures nanbox: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_32bit_setup - name: Build @@ -125,7 +131,7 @@ jobs: float: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_float_build - name: Run main test suite @@ -137,7 +143,7 @@ jobs: stackless_clang: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -151,7 +157,7 @@ jobs: float_clang: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_clang_setup - name: Build @@ -165,7 +171,7 @@ jobs: settrace: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_settrace_build - name: Run main test suite @@ -177,7 +183,7 @@ jobs: settrace_stackless: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Build run: source tools/ci.sh && ci_unix_settrace_stackless_build - name: Run main test suite @@ -189,8 +195,8 @@ jobs: macos: runs-on: macos-11.0 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.8' - name: Build @@ -204,7 +210,7 @@ jobs: qemu_mips: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_qemu_mips_setup - name: Build @@ -218,7 +224,7 @@ jobs: qemu_arm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_unix_qemu_arm_setup - name: Build diff --git a/.github/workflows/ports_webassembly.yml b/.github/workflows/ports_webassembly.yml new file mode 100644 index 0000000000000..880f15ab34469 --- /dev/null +++ b/.github/workflows/ports_webassembly.yml @@ -0,0 +1,32 @@ +name: webassembly port + +on: + push: + pull_request: + paths: + - '.github/workflows/*.yml' + - 'tools/**' + - 'py/**' + - 'extmod/**' + - 'shared/**' + - 'lib/**' + - 'ports/webassembly/**' + +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_webassembly_setup + - name: Build + run: source tools/ci.sh && ci_webassembly_build + - name: Run tests + run: source tools/ci.sh && ci_webassembly_run_tests + - name: Print failures + if: failure() + run: tests/run-tests.py --print-failures diff --git a/.github/workflows/ports_windows.yml b/.github/workflows/ports_windows.yml index 1bfe40c7fded2..a2759880a2f65 100644 --- a/.github/workflows/ports_windows.yml +++ b/.github/workflows/ports_windows.yml @@ -8,15 +8,147 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'ports/unix/**' - 'ports/windows/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - build: + build-vs: + strategy: + fail-fast: false + matrix: + platform: [x86, x64] + configuration: [Debug, Release] + variant: [dev, standard] + visualstudio: ['2017', '2019', '2022'] + include: + - visualstudio: '2017' + runner: windows-latest + vs_version: '[15, 16)' + - visualstudio: '2019' + runner: windows-2019 + vs_version: '[16, 17)' + - visualstudio: '2022' + runner: windows-2022 + vs_version: '[17, 18)' + # trim down the number of jobs in the matrix + exclude: + - variant: standard + configuration: Debug + - visualstudio: '2019' + configuration: Debug + runs-on: ${{ matrix.runner }} + steps: + - name: Install Visual Studio 2017 + if: matrix.visualstudio == '2017' + run: | + choco install visualstudio2017buildtools + choco install visualstudio2017-workload-vctools + choco install windows-sdk-8.1 + - uses: microsoft/setup-msbuild@v2 + with: + vs-version: ${{ matrix.vs_version }} + - uses: actions/setup-python@v5 + if: matrix.runner == 'windows-2019' + with: + python-version: '3.9' + - uses: actions/checkout@v4 + - name: Build mpy-cross.exe + run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} + - name: Update submodules + run: git submodule update --init lib/micropython-lib + - name: Build micropython.exe + run: msbuild ports\windows\micropython.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }} + - name: Get micropython.exe path + id: get_path + run: | + $exePath="$(msbuild ports\windows\micropython.vcxproj -nologo -v:m -t:ShowTargetPath -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }})" + echo ("micropython=" + $exePath.Trim()) >> $env:GITHUB_OUTPUT + - name: Run tests + id: test + env: + MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }} + working-directory: tests + run: python run-tests.py + - name: Print failures + if: failure() && steps.test.conclusion == 'failure' + working-directory: tests + run: python run-tests.py --print-failures + - name: Run mpy tests + id: test_mpy + env: + MICROPY_MICROPYTHON: ${{ steps.get_path.outputs.micropython }} + working-directory: tests + run: python run-tests.py --via-mpy -d basics float micropython + - name: Print mpy failures + if: failure() && steps.test_mpy.conclusion == 'failure' + working-directory: tests + run: python run-tests.py --print-failures + + build-mingw: + strategy: + fail-fast: false + matrix: + variant: [dev, standard] + sys: [mingw32, mingw64] + include: + - sys: mingw32 + env: i686 + - sys: mingw64 + env: x86_64 + runs-on: windows-2022 + env: + CHERE_INVOKING: enabled_from_arguments + defaults: + run: + shell: msys2 {0} + steps: + - name: Get Python path + id: python_path + shell: python + run: | + import os + import sys + output = f"python={os.fspath(sys.executable)}" + print(output) + with open(os.environ["GITHUB_OUTPUT"], "w") as f: + f.write(output) + - uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.sys }} + update: true + install: >- + make + mingw-w64-${{ matrix.env }}-gcc + pkg-config + python3 + git + diffutils + - uses: actions/checkout@v4 + - name: Build mpy-cross.exe + run: make -C mpy-cross -j2 + - name: Update submodules + run: make -C ports/windows VARIANT=${{ matrix.variant }} submodules + - name: Build micropython.exe + run: make -C ports/windows -j2 VARIANT=${{ matrix.variant }} + - name: Run tests + id: test + # msys python breaks tests so we need to use "real" windows python + run: MICROPY_CPYTHON3=$(cygpath "${{ steps.python_path.outputs.python }}") make -C ports/windows test_full VARIANT=${{ matrix.variant }} + - name: Print failures + if: failure() && steps.test.conclusion == 'failure' + working-directory: tests + run: python run-tests.py --print-failures + + cross-build-on-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_windows_setup - name: Build diff --git a/.github/workflows/ports_zephyr.yml b/.github/workflows/ports_zephyr.yml index d9ae2b8c55a2a..f6f328c9277e4 100644 --- a/.github/workflows/ports_zephyr.yml +++ b/.github/workflows/ports_zephyr.yml @@ -8,14 +8,19 @@ on: - 'tools/**' - 'py/**' - 'extmod/**' + - 'shared/**' - 'lib/**' - 'ports/zephyr/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install packages run: source tools/ci.sh && ci_zephyr_setup - name: Install Zephyr diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000000000..29e9ddbf8b61a --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,13 @@ +name: Python code lint and formatting with ruff + +on: [push, pull_request] + +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # ruff version should be kept in sync with .pre-commit-config.yaml + - run: pip install --user ruff==0.1.3 + - run: ruff check --output-format=github . + - run: ruff format --diff . diff --git a/.gitignore b/.gitignore index 7342489927888..2d20cb18970e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,48 +1,25 @@ -# Compiled Sources -################### -*.o -*.a -*.elf -*.bin -*.map -*.hex -*.dis -*.exe - -# Packages -############ - -# Logs and Databases -###################### -*.log - -# VIM Swap Files -###################### -*.swp +# This .gitignore file is intended to be minimal. +# +# If you find that you need additional rules, such as IDE temporary +# files, please do so either via a global .gitignore file (registered +# with core.excludesFile), or by adding private repository-specific +# rules to .git/info/exclude. See https://git-scm.com/docs/gitignore +# for more information. # Build directories -###################### build/ build-*/ +docs/genrst/ # Test failure outputs -###################### tests/results/* # Python cache files -###################### __pycache__/ -*.pyc # Customized Makefile/project overrides -###################### GNUmakefile user.props -# Generated rst files -###################### -genrst/ - # MacOS desktop metadata files -###################### .DS_Store diff --git a/.gitmodules b/.gitmodules index 9fd45dfecf00d..95675132938ef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "lib/stm32lib"] path = lib/stm32lib url = https://github.com/micropython/stm32lib - branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0 + branch = work-F0-1.9.0+F4-1.16.0+F7-1.7.0+G0-1.5.1+G4-1.3.0+H7-1.6.0+L0-1.11.2+L1-1.10.3+L4-1.17.0+WB-1.10.0+WL-1.1.0 [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git @@ -23,12 +23,13 @@ [submodule "lib/asf4"] path = lib/asf4 url = https://github.com/adafruit/asf4 + branch = circuitpython [submodule "lib/tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb [submodule "lib/mynewt-nimble"] path = lib/mynewt-nimble - url = https://github.com/apache/mynewt-nimble.git + url = https://github.com/micropython/mynewt-nimble.git [submodule "lib/btstack"] path = lib/btstack url = https://github.com/bluekitchen/btstack.git @@ -41,3 +42,23 @@ [submodule "lib/pico-sdk"] path = lib/pico-sdk url = https://github.com/raspberrypi/pico-sdk.git +[submodule "lib/fsp"] + path = lib/fsp + url = https://github.com/renesas/fsp.git +[submodule "lib/wiznet"] + path = lib/wiznet5k + url = https://github.com/andrewleech/wiznet_ioLibrary_Driver.git + # Requires https://github.com/Wiznet/ioLibrary_Driver/pull/120 + # url = https://github.com/Wiznet/ioLibrary_Driver.git +[submodule "lib/cyw43-driver"] + path = lib/cyw43-driver + url = https://github.com/georgerobotics/cyw43-driver.git +[submodule "lib/micropython-lib"] + path = lib/micropython-lib + url = https://github.com/micropython/micropython-lib.git +[submodule "lib/protobuf-c"] + path = lib/protobuf-c + url = https://github.com/protobuf-c/protobuf-c.git +[submodule "lib/pico-extras"] + path = lib/pico-extras + url = https://github.com/raspberrypi/pico-extras.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000..a1c811339adcc --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,27 @@ +repos: + - repo: local + hooks: + - id: codeformat + 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 + entry: tools/verifygitlog.py --check-file --ignore-rebase + language: python + verbose: true + stages: [commit-msg] + - repo: https://github.com/charliermarsh/ruff-pre-commit + # Version should be kept in sync with .github/workflows/ruff.yml + rev: v0.1.3 + hooks: + - id: ruff + - id: ruff-format + - repo: https://github.com/codespell-project/codespell + # Version should be kept in sync with .github/workflows/codespell.yml + rev: v2.2.6 + hooks: + - id: codespell + name: Spellcheck for changed files (codespell) + additional_dependencies: + - tomli diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index 78fb912a6ab75..d6af0418e42ef 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -11,7 +11,7 @@ It's also ok to drop file extensions. Besides prefix, first line of a commit message should describe a change clearly and to the point, and be a grammatical sentence with -final full stop. First line should fit within 72 characters. Examples +final full stop. First line must fit within 72 characters. Examples of good first line of commit messages: py/objstr: Add splitlines() method. @@ -27,12 +27,9 @@ change beyond 5 lines would likely require such detailed description. To get good practical examples of good commits and their messages, browse the `git log` of the project. -When committing you are encouraged to sign-off your commit by adding -"Signed-off-by" lines and similar, eg using "git commit -s". If you don't -explicitly sign-off in this way then the commit message, which includes your -name and email address in the "Author" line, implies your sign-off. In either -case, of explicit or implicit sign-off, you are certifying and signing off -against the following: +When committing you must sign-off your commit by adding "Signed-off-by:" +line(s) at the end of the commit message, e.g. using `git commit -s`. You +are then certifying and signing off against the following: * That you wrote the change yourself, or took it from a project with a compatible license (in the latter case the commit message, and possibly @@ -49,28 +46,146 @@ against the following: * Your contribution including commit message will be publicly and indefinitely available for anyone to access, including redistribution under the terms of the project's license. -* Your signature for all of the above, which is the "Signed-off-by" line - or the "Author" line in the commit message, includes your full real name and - a valid and active email address by which you can be contacted in the - foreseeable future. +* Your signature for all of the above, which is the "Signed-off-by" line, + includes your full real name and a valid and active email address by + which you can be contacted in the foreseeable future. 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 +========== + +Only [uncrustify](https://github.com/uncrustify/uncrustify) v0.71 or v0.72 can +be used for MicroPython. Different uncrustify versions produce slightly +different formatting, and the configuration file formats are often +incompatible. v0.73 or newer *will not work*. + +Depending on your operating system version, it may be possible to install a pre-compiled +uncrustify version: + +Ubuntu, Debian +-------------- + +Ubuntu versions 21.10 or 22.04LTS, and Debian versions bullseye or bookworm all +include v0.72 so can be installed directly: + +``` +$ apt install uncrustify +``` + +Arch Linux +---------- + +The current Arch uncrustify version is too new. There is an [old Arch package +for v0.72](https://archive.archlinux.org/packages/u/uncrustify/) that can be +installed from the Arch Linux archive ([more +information](https://wiki.archlinux.org/title/Downgrading_packages#Arch_Linux_Archive)). Use +the [IgnorePkg feature](https://wiki.archlinux.org/title/Pacman#Skip_package_from_being_upgraded) +to prevent it re-updating. + +Brew +---- + +This command may work, please raise a new Issue if it doesn't: + +``` +curl -L https://github.com/Homebrew/homebrew-core/raw/2b07d8192623365078a8b855a164ebcdf81494a6/Formula/uncrustify.rb > uncrustify.rb && brew install uncrustify.rb && rm uncrustify.rb +``` + +Code spell checking +=================== + +Code spell checking is done using [codespell](https://github.com/codespell-project/codespell#codespell) +and runs in a GitHub action in CI. Codespell is configured via `pyproject.toml` +to avoid false positives. It is recommended run codespell before submitting a +PR. To simplify this, codespell is configured as a pre-commit hook and will be +installed if you run `pre-commit install` (see below). + +If you want to install and run codespell manually, you can do so by running: + +``` +$ pip install codespell tomli +$ codespell +``` + +Automatic Pre-Commit Hooks +========================== + +To have code formatting and commit message conventions automatically checked, +a configuration file is provided for the [pre-commit](https://pre-commit.com/) +tool. + +First install `pre-commit`, either from your system package manager or via +`pip`. When installing `pre-commit` via pip, it is recommended to use a +virtual environment. Other sources, such as Brew are also available, see +[the docs](https://pre-commit.com/index.html#install) for details. + +``` +$ apt install pre-commit # Ubuntu, Debian +$ pacman -Sy python-precommit # Arch Linux +$ brew install pre-commit # Brew +$ pip install pre-commit # PyPI +``` + +Next, install [uncrustify (see above)](#uncrustify). Other dependencies are managed by +pre-commit automatically, but uncrustify needs to be installed and available on +the PATH. + +Then, inside the MicroPython repository, register the git hooks for pre-commit +by running: + +``` +$ pre-commit install --hook-type pre-commit --hook-type commit-msg +``` + +pre-commit will now automatically run during `git commit` for both code and +commit message formatting. + +The same formatting checks will be run by CI for any Pull Request submitted to +MicroPython. Pre-commit allows you to see any failure more quickly, and in many +cases will automatically correct it in your local working copy. + +To unregister `pre-commit` from your MicroPython repository, run: + +``` +$ pre-commit uninstall --hook-type pre-commit --hook-type commit-msg +``` + +Tips: + +* To skip pre-commit checks on a single commit, use `git commit -n` (for + `--no-verify`). +* 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. @@ -165,7 +280,7 @@ Documentation conventions ========================= MicroPython generally follows CPython in documentation process and -conventions. reStructuredText syntax is used for the documention. +conventions. reStructuredText syntax is used for the documentation. Specific conventions/suggestions: diff --git a/LICENSE b/LICENSE index 5b5c37f7d1ead..b85f31808a483 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2021 Damien P. George +Copyright (c) 2013-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 @@ -35,9 +35,7 @@ used during the build process and is not part of the compiled source code. / (MIT) /drivers - /cc3000 (BSD-3-clause) /cc3100 (BSD-3-clause) - /wiznet5k (BSD-3-clause) /lib /asf4 (Apache-2.0) /axtls (BSD-3-clause) @@ -62,12 +60,17 @@ used during the build process and is not part of the compiled source code. /tinytest (BSD-3-clause) /tinyusb (MIT) /uzlib (Zlib) + /wiznet5k (MIT) /logo (uses OFL-1.1) /ports /cc3200 /hal (BSD-3-clause) /simplelink (BSD-3-clause) /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) @@ -77,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 diff --git a/README.md b/README.md index d197924f0e759..ca2450ea292b6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,37 @@ -[![CI badge](https://github.com/micropython/micropython/workflows/unix%20port/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython) +[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython) + +This is a fork of the MicroPython project to allow deep sleeping and waking +from the internal real time clock of the Raspberry Pico. + +This can be built with the following commands: + +```bash +git clone https://github.com/ghubcoder/micropython-pico-deepsleep.git +cd micropython-pico-deepsleep/ +make -C mpy-cross/ +git submodule update --init -- lib/pico-sdk +git submodule update --init -- lib/pico-extras +git submodule update --init -- lib/tinyusb +cd ports/rp2sleep +make -j4 +``` + +This will create a `firmware.uf2` file which can then be loaded onto your +Pico in the usual way using the BOOTSEL button. + +A precompiled binary can be found [here](https://github.com/ghubcoder/micropython-pico-deepsleep/releases/tag/v1.1-pico-deepsleep). + +Example usage: + +```python +import picosleep +picosleep.seconds(60) +``` + +Please see [this](https://ghubcoder.github.io/posts/deep-sleeping-the-pico-micropython/) +post for more information. + +Original readme follows: The MicroPython project ======================= @@ -15,174 +48,133 @@ code-base, including project-wide name changes and API changes. MicroPython implements the entire Python 3.4 syntax (including exceptions, `with`, `yield from`, etc., and additionally `async`/`await` keywords from -Python 3.5). The following core datatypes are provided: `str` (including -basic Unicode support), `bytes`, `bytearray`, `tuple`, `list`, `dict`, `set`, -`frozenset`, `array.array`, `collections.namedtuple`, classes and instances. -Builtin modules include `sys`, `time`, and `struct`, etc. Select ports have -support for `_thread` module (multithreading). Note that only a subset of -Python 3 functionality is implemented for the data types and modules. - -MicroPython can execute scripts in textual source form or from precompiled -bytecode, in both cases either from an on-device filesystem or "frozen" into -the MicroPython executable. - -See the repository http://github.com/micropython/pyboard for the MicroPython -board (PyBoard), the officially supported reference electronic circuit board. - -Major components in this repository: -- py/ -- the core Python implementation, including compiler, runtime, and +Python 3.5 and some select features from later versions). The following core +datatypes are provided: `str`(including basic Unicode support), `bytes`, +`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`, +`collections.namedtuple`, classes and instances. Builtin modules include +`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for +`_thread` module (multithreading), `socket` and `ssl` for networking, and +`asyncio`. Note that only a subset of Python 3 functionality is implemented +for the data types and modules. + +MicroPython can execute scripts in textual source form (.py files) or from +precompiled bytecode (.mpy files), in both cases either from an on-device +filesystem or "frozen" into the MicroPython executable. + +MicroPython also provides a set of MicroPython-specific modules to access +hardware-specific functionality and peripherals such as GPIO, Timers, ADC, +DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB. + +Getting started +--------------- + +See the [online documentation](https://docs.micropython.org/) for API +references and information about using MicroPython and information about how +it is implemented. + +We use [GitHub Discussions](https://github.com/micropython/micropython/discussions) +as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These +are great places to ask questions and advice from the community or to discuss your +MicroPython-based projects. + +For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose) +and follow the templates there. + +For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features), +the officially supported board from the +[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers), +see the [schematics and pinouts](http://github.com/micropython/pyboard) and +[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html). + +Contributing +------------ + +MicroPython is an open-source project and welcomes contributions. To be +productive, please be sure to follow the +[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines) +and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md). +Note that MicroPython is licenced under the MIT license, and all contributions +should follow this license. + +About this repository +--------------------- + +This repository contains the following components: +- [py/](py/) -- the core Python implementation, including compiler, runtime, and core library. -- mpy-cross/ -- the MicroPython cross-compiler which is used to turn scripts +- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts into precompiled bytecode. -- ports/unix/ -- a version of MicroPython that runs on Unix. -- ports/stm32/ -- a version of MicroPython that runs on the PyBoard and similar - STM32 boards (using ST's Cube HAL drivers). -- ports/minimal/ -- a minimal MicroPython port. Start with this if you want - to port MicroPython to another microcontroller. -- tests/ -- test framework and test scripts. -- docs/ -- user documentation in Sphinx reStructuredText format. Rendered - HTML documentation is available at http://docs.micropython.org. - -Additional components: -- ports/bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used - mostly to control code size. -- ports/teensy/ -- a version of MicroPython that runs on the Teensy 3.1 - (preliminary but functional). -- ports/pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers. -- ports/cc3200/ -- a version of MicroPython that runs on the CC3200 from TI. -- ports/esp8266/ -- a version of MicroPython that runs on Espressif's ESP8266 SoC. -- ports/esp32/ -- a version of MicroPython that runs on Espressif's ESP32 SoC. -- ports/nrf/ -- a version of MicroPython that runs on Nordic's nRF51 and nRF52 MCUs. -- extmod/ -- additional (non-core) modules implemented in C. -- tools/ -- various tools, including the pyboard.py module. -- examples/ -- a few example Python scripts. - -The subdirectories above may include READMEs with additional info. +- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on. +- [lib/](lib/) -- submodules for external dependencies. +- [tests/](tests/) -- test framework and test scripts. +- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org). +- [extmod/](extmod/) -- additional (non-core) modules implemented in C. +- [tools/](tools/) -- various tools, including the pyboard.py module. +- [examples/](examples/) -- a few example Python scripts. "make" is used to build the components, or "gmake" on BSD-based systems. You will also need bash, gcc, and Python 3.3+ available as the command `python3` (if your system only has Python 2.7 then invoke make with the additional option -`PYTHON=python2`). +`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake. + +Supported platforms & architectures +----------------------------------- + +MicroPython runs on a wide range of microcontrollers, as well as on Unix-like +(including Linux, BSD, macOS, WSL) and Windows systems. + +Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although +devices with at least 512kiB flash + 128kiB RAM allow a much more +full-featured experience. + +The [Unix](ports/unix) and [Windows](ports/windows) ports allow both +development and testing of MicroPython itself, as well as providing +lightweight alternative to CPython on these platforms (in particular on +embedded Linux systems). + +The ["minimal"](ports/minimal) port provides an example of a very basic +MicroPython port and can be compiled as both a standalone Linux binary as +well as for ARM Cortex M4. Start with this if you want to port MicroPython to +another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port +is an example of the absolute minimum configuration, and is used to keep +track of the code size of the core runtime and VM. + +In addition, the following ports are provided in this repository: + - [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy). + - [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3). + - [esp8266](ports/esp8266) -- Espressif ESP8266 SoC. + - [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x). + - [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52. + - [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit. + - [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt) + - [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing) + - [renesas-ra](ports/renesas-ra) -- Renesas RA family. + - [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) + - [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS. + - [zephyr](ports/zephyr) -- Zephyr RTOS. The MicroPython cross-compiler, mpy-cross ----------------------------------------- -Most ports require the MicroPython cross-compiler to be built first. This -program, called mpy-cross, is used to pre-compile Python scripts to .mpy -files which can then be included (frozen) into the firmware/executable for -a port. To build mpy-cross use: +Most ports require the [MicroPython cross-compiler](mpy-cross) to be built +first. This program, called mpy-cross, is used to pre-compile Python scripts +to .mpy files which can then be included (frozen) into the +firmware/executable for a port. To build mpy-cross use: $ cd mpy-cross $ make -The Unix version ----------------- - -The "unix" port requires a standard Unix environment with gcc and GNU make. -x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well -as ARM and MIPS. Making full-featured port to another architecture requires -writing some assembly code for the exception handling and garbage collection. -Alternatively, fallback implementation based on setjmp/longjmp can be used. - -To build (see section below for required dependencies): - - $ cd ports/unix - $ make submodules - $ make - -Then to give it a try: - - $ ./micropython - >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) - -Use `CTRL-D` (i.e. EOF) to exit the shell. -Learn about command-line options (in particular, how to increase heap size -which may be needed for larger applications): - - $ ./micropython -h - -Run complete testsuite: - - $ make test - -Unix version comes with a builtin package manager called upip, e.g.: - - $ ./micropython -m upip install micropython-pystone - $ ./micropython -m pystone - -Browse available modules on -[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython). -Standard library modules come from -[micropython-lib](https://github.com/micropython/micropython-lib) project. - External dependencies --------------------- -Building MicroPython ports may require some dependencies installed. - -For Unix port, `libffi` library and `pkg-config` tool are required. On -Debian/Ubuntu/Mint derivative Linux distros, install `build-essential` -(includes toolchain and make), `libffi-dev`, and `pkg-config` packages. - -Other dependencies can be built together with MicroPython. This may -be required to enable extra features or capabilities, and in recent -versions of MicroPython, these may be enabled by default. To build -these additional dependencies, in the port directory you're -interested in (e.g. `ports/unix/`) first execute: +The core MicroPython VM and runtime has no external dependencies, but a given +port might depend on third-party drivers or vendor HALs. This repository +includes [several submodules](lib/) linking to these external dependencies. +Before compiling a given port, use + $ cd ports/name $ make submodules -This will fetch all the relevant git submodules (sub repositories) that -the port needs. Use the same command to get the latest versions of -submodules as they are updated from time to time. After that execute: - - $ make deplibs - -This will build all available dependencies (regardless whether they -are used or not). If you intend to build MicroPython with additional -options (like cross-compiling), the same set of options should be passed -to `make deplibs`. To actually enable/disable use of dependencies, edit -`ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. -For example, to build SSL module (required for `upip` tool described above, -and so enabled by default), `MICROPY_PY_USSL` should be set to 1. - -For some ports, building required dependences is transparent, and happens -automatically. But they still need to be fetched with the `make submodules` -command. - -The STM32 version ------------------ - -The "stm32" port requires an ARM compiler, arm-none-eabi-gcc, and associated -bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils, -arm-none-eabi-gcc and arm-none-eabi-newlib packages. Otherwise, try here: -https://launchpad.net/gcc-arm-embedded - -To build: - - $ cd ports/stm32 - $ make submodules - $ make - -You then need to get your board into DFU mode. On the pyboard, connect the -3V3 pin to the P1/DFU pin with a wire (on PYBv1.0 they are next to each other -on the bottom left of the board, second row from the bottom). - -Then to flash the code via USB DFU to your device: - - $ make deploy - -This will use the included `tools/pydfu.py` script. If flashing the firmware -does not work it may be because you don't have the correct permissions, and -need to use `sudo make deploy`. -See the README.md file in the ports/stm32/ directory for further details. - -Contributing ------------- - -MicroPython is an open-source project and welcomes contributions. To be -productive, please be sure to follow the -[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines) -and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md). -Note that MicroPython is licenced under the MIT license, and all contributions -should follow this license. +to ensure that all required submodules are initialised. diff --git a/docs/Makefile b/docs/Makefile index 05709617c35b9..766a669a500dc 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -3,7 +3,7 @@ # You can set these variables from the command line. PYTHON = python3 -SPHINXOPTS = -W --keep-going +SPHINXOPTS = -W --keep-going -j auto SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build/$(MICROPY_PORT) diff --git a/docs/README.md b/docs/README.md index 1591911c34560..892726ba17ffe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -47,7 +47,7 @@ This can be achieved with: make latexpdf -but require rather complete install of LaTeX with various extensions. On -Debian/Ubuntu, try (500MB+ download): +but requires a rather complete install of LaTeX with various extensions. On +Debian/Ubuntu, try (1GB+ download): - apt-get install texlive-latex-recommended texlive-latex-extra + apt install texlive-latex-recommended texlive-latex-extra texlive-xetex texlive-fonts-extra cm-super xindy diff --git a/docs/conf.py b/docs/conf.py index 1a3c18a4f44f3..728e3c4285d82 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,54 +19,56 @@ # 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 - ], - 'downloads':[ - ('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'), + "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"), ], + "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', + "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-2021, 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 @@ -74,45 +76,45 @@ # # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # breakdown, so use the same version identifier for both to avoid confusion. -version = release = '1.17' +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 @@ -124,153 +126,168 @@ # -- 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 # " v 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", +] # 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 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': '\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" # -- Options for manual page output --------------------------------------- # 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 ------------------------------------------- @@ -279,23 +296,29 @@ # (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)} diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index 38225e8686a7b..75dbc953c06f8 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -49,9 +49,17 @@ A MicroPython user C module is a directory with the following files: in your ``micropython.mk`` to a local make variable, eg ``EXAMPLE_MOD_DIR := $(USERMOD_DIR)`` - Your ``micropython.mk`` must add your modules source files relative to your - expanded copy of ``$(USERMOD_DIR)`` to ``SRC_USERMOD``, eg - ``SRC_USERMOD += $(EXAMPLE_MOD_DIR)/example.c`` + Your ``micropython.mk`` must add your modules source files to the + ``SRC_USERMOD_C`` or ``SRC_USERMOD_LIB_C`` variables. The former will be + processed for ``MP_QSTR_`` and ``MP_REGISTER_MODULE`` definitions, the latter + will not (e.g. helpers and library code that isn't MicroPython-specific). + These paths should include your expanded copy of ``$(USERMOD_DIR)``, e.g.:: + + SRC_USERMOD_C += $(EXAMPLE_MOD_DIR)/modexample.c + SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c + + Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++ + source files. If you have custom compiler options (like ``-I`` to add directories to search for header files), these should be added to ``CFLAGS_USERMOD`` for C code @@ -87,9 +95,12 @@ A MicroPython user C module is a directory with the following files: Basic example ------------- -This simple module named ``cexample`` provides a single function -``cexample.add_ints(a, b)`` which adds the two integer args together and returns -the result. It can be found in the MicroPython source tree +The ``cexample`` module provides examples for a function and a class. The +``cexample.add_ints(a, b)`` function adds two integer args together and returns +the result. The ``cexample.Timer()`` type creates timers that can be used to +measure the elapsed time since the object is instantiated. + +The module can be found in the MicroPython source tree `in the examples directory `_ and has a source file and a Makefile fragment with content as described above:: @@ -221,23 +232,25 @@ as described above. If a module is not enabled by default then the corresponding C preprocessor macro must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE`` line in the module's source code (it usually appears at the end of the main source file). -The third argument to ``MP_REGISTER_MODULE`` is the macro name, and this must be set -to 1 using ``CFLAGS_EXTRA`` to make the module available. If the third argument is just -the number 1 then the module is enabled by default. +This macro should be surrounded by a ``#if X`` / ``#endif`` pair, and the configuration +option ``X`` must be set to 1 using ``CFLAGS_EXTRA`` to make the module available. If +there is no ``#if X`` / ``#endif`` pair then the module is enabled by default. For example, the ``examples/usercmodule/cexample`` module is enabled by default so has the following line in its source code: .. code-block:: c - MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1); + MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule); Alternatively, to make this module disabled by default but selectable through a preprocessor configuration option, it would be: .. code-block:: c - MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED); + #if MODULE_CEXAMPLE_ENABLED + MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule); + #endif In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1`` to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add @@ -262,3 +275,13 @@ can now be accessed in Python just like any other builtin module, e.g. import cexample print(cexample.add_ints(1, 3)) # should display 4 + +.. code-block:: python + + from cexample import Timer + from time import sleep_ms + + watch = Timer() + sleep_ms(1000) + print(watch.time()) + # should display approximately 1000 diff --git a/docs/develop/compiler.rst b/docs/develop/compiler.rst index 2007657490f55..cac92585ff4ee 100644 --- a/docs/develop/compiler.rst +++ b/docs/develop/compiler.rst @@ -147,10 +147,17 @@ The most relevant method you should know about is this: .. code-block:: c mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { + // Create a context for this module, and set its globals dict. + mp_module_context_t *context = m_new_obj(mp_module_context_t); + context->module.globals = mp_globals_get(); + // Compile the input parse_tree to a raw-code structure. - mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, is_repl); + mp_compiled_module_t cm; + cm.context = context; + mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm); + // Create and return a function object that executes the outer module. - return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL); + return mp_make_function_from_raw_code(cm.rc, cm.context, NULL); } The compiler compiles the code in four passes: scope, stack size, code size and emit. diff --git a/docs/develop/extendingmicropython.rst b/docs/develop/extendingmicropython.rst index 7fb1ae47a0e4e..b4029c421c89a 100644 --- a/docs/develop/extendingmicropython.rst +++ b/docs/develop/extendingmicropython.rst @@ -16,4 +16,3 @@ live in the main MicroPython repository. cmodules.rst natmod.rst - \ No newline at end of file diff --git a/docs/develop/gettingstarted.rst b/docs/develop/gettingstarted.rst index 30b26071ea012..a17a320671f52 100644 --- a/docs/develop/gettingstarted.rst +++ b/docs/develop/gettingstarted.rst @@ -4,7 +4,7 @@ Getting Started =============== This guide covers a step-by-step process on setting up version control, obtaining and building -a copy of the source code for a port, building the documentation, running tests, and a description of the +a copy of the source code for a port, building the documentation, running tests, and a description of the directory structure of the MicroPython code base. Source control with git @@ -16,7 +16,7 @@ code is pulled and pushed to and from the main repository. Install the respectiv of Git for your operating system to follow through the rest of the steps. .. note:: - For a reference on the installation instructions, please refer to + For a reference on the installation instructions, please refer to the `Git installation instructions `_. Learn about the basic git commands in this `Git Handbook `_ or any other sources on the internet. @@ -58,12 +58,12 @@ MicroPython repository. After the above configuration, your setup should be similar to this: .. code-block:: bash - + $ git remote -v - origin https://github.com//micropython (fetch) - origin https://github.com//micropython (push) - upstream https://github.com/micropython/micropython (fetch) - upstream https://github.com/micropython/micropython (push) + origin https://github.com//micropython (fetch) + origin https://github.com//micropython (push) + upstream https://github.com/micropython/micropython (fetch) + upstream https://github.com/micropython/micropython (push) You should now have a copy of the source code. By default, you are pointing to the master branch. To prepare for further development, it is recommended @@ -73,7 +73,7 @@ to work on a development branch. $ git checkout -b dev-branch -You can give it any name. You will have to compile MicroPython whenever you change +You can give it any name. You will have to compile MicroPython whenever you change to a different branch. Compile and build the code @@ -100,10 +100,10 @@ For the stm32 port, the ARM cross-compiler is required: .. code-block:: bash - $ sudo apt-get install arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib + $ sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi See the `ARM GCC -toolchain `_ +toolchain `_ for the latest details. Python is also required. Python 2 is supported for now, but we recommend using Python 3. @@ -140,8 +140,8 @@ If it built successfully, you should see a message similar to this: .. code-block:: bash LINK mpy-cross - text data bss dec hex filename - 279328 776 880 280984 44998 mpy-cross + text data bss dec hex filename + 279328 776 880 280984 44998 mpy-cross .. note:: @@ -181,8 +181,8 @@ If MicroPython built correctly, you should see the following: .. code-block:: bash LINK micropython - text data bss dec hex filename - 412033 5680 2496 420209 66971 micropython + text data bss dec hex filename + 412033 5680 2496 420209 66971 micropython Now run it: @@ -215,7 +215,7 @@ as detailed in the :ref:`required_dependencies` section, then build: $ make submodules $ make -Please refer to the `stm32 documentation `_ +Please refer to the `stm32 documentation `_ for more details on flashing the firmware. .. note:: @@ -228,7 +228,7 @@ You can also specify which board to use: .. code-block:: bash $ cd ports/stm32 - $ make submodules + $ make BOARD= submodules $ make BOARD= See `ports/stm32/boards `_ @@ -245,7 +245,7 @@ that you use a virtual environment: $ python3 -m venv env $ source env/bin/activate - $ pip install sphinx + $ pip install -r docs/requirements.txt Navigate to the ``docs`` directory: @@ -259,7 +259,7 @@ Build the docs: $ make html -Open ``docs/build/html/index.html`` in your browser to view the docs locally. Refer to the +Open ``docs/build/html/index.html`` in your browser to view the docs locally. Refer to the documentation on `importing your documentation `_ to use Read the Docs. @@ -322,7 +322,8 @@ tests tools - Contains helper tools including the ``upip`` and the ``pyboard.py`` module. + Contains scripts used by the build and CI process, as well as user tools such + as ``pyboard.py`` and ``mpremote``. examples diff --git a/docs/develop/index.rst b/docs/develop/index.rst index 7a6a6be67c5b9..327038f1978bd 100644 --- a/docs/develop/index.rst +++ b/docs/develop/index.rst @@ -5,7 +5,7 @@ This chapter covers a tour of MicroPython from the perspective of a developer, c to MicroPython. It acts as a comprehensive resource on the implementation details of MicroPython for both novice and expert contributors. -Development around MicroPython usually involves modifying the core runtime, porting or +Development around MicroPython usually involves modifying the core runtime, porting or maintaining a new library. This guide describes at great depth, the implementation details of MicroPython including a getting started guide, compiler internals, porting MicroPython to a new platform and implementing a core MicroPython library. @@ -24,4 +24,3 @@ MicroPython to a new platform and implementing a core MicroPython library. publiccapi.rst extendingmicropython.rst porting.rst - \ No newline at end of file diff --git a/docs/develop/library.rst b/docs/develop/library.rst index 47ea2dc8d2431..c2a86ea1699bc 100644 --- a/docs/develop/library.rst +++ b/docs/develop/library.rst @@ -64,7 +64,7 @@ hypothetical new module ``subsystem`` in the file ``modsubsystem.c``: .globals = (mp_obj_dict_t *)&mp_module_subsystem_globals, }; - MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem, MICROPY_PY_SUBSYSTEM); + MP_REGISTER_MODULE(MP_QSTR_subsystem, mp_module_subsystem); #endif diff --git a/docs/develop/natmod.rst b/docs/develop/natmod.rst index 8ffe49591cc69..6d15f867bcfe8 100644 --- a/docs/develop/natmod.rst +++ b/docs/develop/natmod.rst @@ -34,6 +34,7 @@ options for the ``ARCH`` variable, see below): * ``x86`` (32 bit) * ``x64`` (64 bit x86) +* ``armv6m`` (ARM Thumb, eg Cortex-M0) * ``armv7m`` (ARM Thumb 2, eg Cortex-M3) * ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7) * ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7) @@ -171,7 +172,7 @@ The file ``Makefile`` contains: # Source files (.c or .py) SRC = factorial.c - # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) + # Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin) ARCH = x64 # Include to get the rules for compiling and linking the module diff --git a/docs/develop/optimizations.rst b/docs/develop/optimizations.rst index d972cde66616a..7f2c8cbe7282c 100644 --- a/docs/develop/optimizations.rst +++ b/docs/develop/optimizations.rst @@ -25,6 +25,8 @@ into the firmware image as part of the main firmware compilation process, which the bytecode will be executed from ROM. This can lead to a significant memory saving, and reduce heap fragmentation. +See :ref:`manifest` for more information. + Variables --------- diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst index 549227d76267c..09e61d5d9bfe0 100644 --- a/docs/develop/porting.rst +++ b/docs/develop/porting.rst @@ -38,6 +38,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main. .. code-block:: c + #include "py/builtin.h" #include "py/compile.h" #include "py/gc.h" #include "py/mperrno.h" @@ -53,8 +54,6 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main. mp_stack_ctrl_init(); gc_init(heap, heap + sizeof(heap)); mp_init(); - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); // Start a normal REPL; will exit when ctrl-D is entered on a blank line. pyexec_friendly_repl(); @@ -84,7 +83,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main. } // There is no filesystem so opening a file raises an exception. - mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + mp_lexer_t *mp_lexer_new_from_file(qstr filename) { mp_raise_OSError(MP_ENOENT); } @@ -97,10 +96,11 @@ We also need a Makefile at this point for the port: # Include py core make definitions. include $(TOP)/py/py.mk + include $(TOP)/extmod/extmod.mk # Set CFLAGS and libraries. - CFLAGS = -I. -I$(BUILD) -I$(TOP) - LIBS = -lm + CFLAGS += -I. -I$(BUILD) -I$(TOP) + LIBS += -lm # Define the required source files. SRC_C = \ @@ -111,6 +111,9 @@ We also need a Makefile at this point for the port: shared/runtime/pyexec.c \ shared/runtime/stdout_helpers.c \ + # Define source files containung qstrs. + SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c + # Define the required object files. OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) @@ -172,9 +175,6 @@ The following is an example of an ``mpconfigport.h`` file: #define MP_STATE_PORT MP_STATE_VM - #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[8]; - This configuration file contains machine-specific configurations including aspects like if different MicroPython features should be enabled e.g. ``#define MICROPY_ENABLE_GC (1)``. Making this Setting ``(0)`` disables the feature. @@ -279,12 +279,7 @@ To add a custom module like ``myport``, first add the module definition in a fil .globals = (mp_obj_dict_t *)&myport_module_globals, }; - MP_REGISTER_MODULE(MP_QSTR_myport, myport_module, 1); - -Note: the "1" as the third argument in ``MP_REGISTER_MODULE`` enables this new module -unconditionally. To allow it to be conditionally enabled, replace the "1" by -``MICROPY_PY_MYPORT`` and then add ``#define MICROPY_PY_MYPORT (1)`` in ``mpconfigport.h`` -accordingly. + MP_REGISTER_MODULE(MP_QSTR_myport, myport_module); You will also need to edit the Makefile to add ``modmyport.c`` to the ``SRC_C`` list, and a new line adding the same file to ``SRC_QSTR`` (so qstrs are searched for in this new file), @@ -298,7 +293,7 @@ like this: mphalport.c \ ... - SRC_QSTR += modport.c + SRC_QSTR += modmyport.c If all went correctly then, after rebuilding, you should be able to import the new module: diff --git a/docs/develop/qstr.rst b/docs/develop/qstr.rst index cd1fc47862cf0..5d1ac5bb4a49f 100644 --- a/docs/develop/qstr.rst +++ b/docs/develop/qstr.rst @@ -59,7 +59,7 @@ Processing happens in the following stages: information. Note that this step only uses files that have changed, which means that ``qstr.i.last`` will only contain data from files that have changed since the last compile. - + 2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split`` on qstr.i.last. It's just used as a dependency to indicate that the step ran. This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``, diff --git a/docs/differences/index_template.txt b/docs/differences/index_template.txt index 41ddeb6d3e4aa..1bbfbfedce921 100644 --- a/docs/differences/index_template.txt +++ b/docs/differences/index_template.txt @@ -3,8 +3,22 @@ MicroPython differences from CPython ==================================== -The operations listed in this section produce conflicting results in MicroPython when compared to standard Python. -MicroPython implements Python 3.4 and some select features of Python 3.5. +MicroPython implements Python 3.4 and some select features of Python 3.5 and +above. The sections below describe the current status of these features. + +.. toctree:: + + ../differences/python_35.rst + ../differences/python_36.rst + ../differences/python_37.rst + ../differences/python_38.rst + ../differences/python_39.rst + ../differences/python_310.rst + +For the features of Python that are implemented by MicroPython, there are +sometimes differences in their behaviour compared to standard Python. The +operations listed in the sections below produce conflicting results in +MicroPython when compared to standard Python. .. toctree:: :maxdepth: 2 diff --git a/docs/differences/modules_preamble.txt b/docs/differences/modules_preamble.txt new file mode 100644 index 0000000000000..1958f0084d2db --- /dev/null +++ b/docs/differences/modules_preamble.txt @@ -0,0 +1,33 @@ +.. Preamble section inserted into generated output + +Positional-only Parameters +-------------------------- + +To save code size, many functions that accept keyword arguments in CPython only accept positional arguments in MicroPython. + +MicroPython marks positional-only parameters in the same way as CPython, by inserting a ``/`` to mark the end of the positional parameters. Any function whose signature ends in ``/`` takes *only* positional arguments. For more details, see `PEP 570 `_. + +Example +~~~~~~~ + +For example, in CPython 3.4 this is the signature of the constructor ``socket.socket``:: + + socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) + +However, the signature documented in :func:`MicroPython` is:: + + socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /) + +The ``/`` at the end of the parameters indicates that they are all positional-only in MicroPython. The following code works in CPython but not in most MicroPython ports:: + + import socket + s = socket.socket(type=socket.SOCK_DGRAM) + +MicroPython will raise an exception:: + + TypeError: function doesn't take keyword arguments + +The following code will work in both CPython and MicroPython:: + + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) diff --git a/docs/differences/python_310.rst b/docs/differences/python_310.rst new file mode 100644 index 0000000000000..f9d92db655372 --- /dev/null +++ b/docs/differences/python_310.rst @@ -0,0 +1,238 @@ +.. _python_310: + +Python 3.10 +=========== + +Python 3.10.0 (final) was released on the 4 October 2021. The Features for 3.10 are +defined in `PEP 619 `_ +and a detailed description of the changes can be found in +`What's New in Python 3.10 `_. + +.. table:: + :widths: 20 60 20 + + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | **New syntax features** | **Status** | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 634 `_ | Structural Pattern Matching: Specification | [#spm]_ | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 635 `_ | Structural Pattern Matching: Motivation and | [#spm]_ | + | | Rationale | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 636 `_ | Structural Pattern Matching: Tutorial | [#spm]_ | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `bpo-12782 | Parenthesized context managers are now officially | | + | `_ | allowed | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | **New features in the standard library** | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 618 `_ | Add Optional Length-Checking To zip | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | **Interpreter improvements** | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 626 `_ | Precise line numbers for debugging and other tools | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | **New typing features** | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 604 `_ | Allow writing union types as X | Y | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 613 `_ | Explicit Type Aliases | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 612 `_ | Parameter Specification Variables | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | **Important deprecations, removals or restrictions** | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 644 `_ | Require OpenSSL 1.1.1 or newer | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 632 `_ | Deprecate distutils module. | Not relevant | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 623 `_ | Deprecate and prepare for the removal of the wstr | Not relevant | + | | member in PyUnicodeObject. | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 624 `_ | Remove Py_UNICODE encoder APIs | Not relevant | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + | `PEP 597 `_ | Add optional EncodingWarning | | + +--------------------------------------------------------+----------------------------------------------------+--------------+ + + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +-------------------------------------------------------------------------------------------------------------+---------------+ + | The :class:`int` type has a new method :meth:`int.bit_count`, returning the | | + | number of ones in the binary expansion of a given integer, also known | | + | as the population count. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | The views returned by :meth:`dict.keys`, :meth:`dict.values` and | | + | :meth:`dict.items` now all have a ``mapping`` attribute that gives a | | + | :class:`types.MappingProxyType` object wrapping the original | | + | dictionary. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | :pep:`618`: The :func:`zip` function now has an optional ``strict`` flag, used | | + | to require that all the iterables have an equal length. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Builtin and extension functions that take integer arguments no longer accept | | + | :class:`~decimal.Decimal`\ s, :class:`~fractions.Fraction`\ s and other | | + | objects that can be converted to integers only with a loss (e.g. that have | | + | the :meth:`~object.__int__` method but do not have the | | + | :meth:`~object.__index__` method). | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | If :func:`object.__ipow__` returns :const:`NotImplemented`, the operator will | | + | correctly fall back to :func:`object.__pow__` and :func:`object.__rpow__` as expected. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Assignment expressions can now be used unparenthesized within set literals | | + | and set comprehensions, as well as in sequence indexes (but not slices). | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Functions have a new ``__builtins__`` attribute which is used to look for | | + | builtin symbols when a function is executed, instead of looking into | | + | ``__globals__['__builtins__']``. The attribute is initialized from | | + | ``__globals__["__builtins__"]`` if it exists, else from the current builtins. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Two new builtin functions -- :func:`aiter` and :func:`anext` have been added | | + | to provide asynchronous counterparts to :func:`iter` and :func:`next`, | | + | respectively. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Static methods (:func:`@staticmethod `) and class methods | | + | (:func:`@classmethod `) now inherit the method attributes | | + | (``__module__``, ``__name__``, ``__qualname__``, ``__doc__``, | | + | ``__annotations__``) and have a new ``__wrapped__`` attribute. | | + | Moreover, static methods are now callable as regular functions. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Annotations for complex targets (everything beside ``simple name`` targets | | + | defined by :pep:`526`) no longer cause any runtime effects with ``from __future__ import annotations``. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Class and module objects now lazy-create empty annotations dicts on demand. | | + | The annotations dicts are stored in the object’s ``__dict__`` for | | + | backwards compatibility. This improves the best practices for working | | + | with ``__annotations__``. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Annotations consist of ``yield``, ``yield from``, ``await`` or named expressions | | + | are now forbidden under ``from __future__ import annotations`` due to their side | | + | effects. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Usage of unbound variables, ``super()`` and other expressions that might | | + | alter the processing of symbol table as annotations are now rendered | | + | effectless under ``from __future__ import annotations``. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Hashes of NaN values of both :class:`float` type and | | + | :class:`decimal.Decimal` type now depend on object identity. Formerly, they | | + | always hashed to ``0`` even though NaN values are not equal to one another. | | + | This caused potentially quadratic runtime behavior due to excessive hash | | + | collisions when creating dictionaries and sets containing multiple NaNs. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | A :exc:`SyntaxError` (instead of a :exc:`NameError`) will be raised when deleting | | + | the :const:`__debug__` constant. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | :exc:`SyntaxError` exceptions now have ``end_lineno`` and | | + | ``end_offset`` attributes. They will be ``None`` if not determined. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `asyncio `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket` | | + | method. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `array `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The :meth:`~array.array.index` method of :class:`array.array` now has | | + | optional *start* and *stop* parameters. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `gc `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and | | + | :func:`gc.get_referents`. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `hashlib `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The hashlib module requires OpenSSL 1.1.1 or newer. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The hashlib module has preliminary support for OpenSSL 3.0.0. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The pure-Python fallback of :func:`~hashlib.pbkdf2_hmac` is deprecated. In | | + | the future PBKDF2-HMAC will only be available when Python has been built with | | + | OpenSSL support. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `os `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :func:`os.cpu_count()` support for VxWorks RTOS. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add a new function :func:`os.eventfd` and related helpers to wrap the | | + | ``eventfd2`` syscall on Linux. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :func:`os.splice()` that allows to move data between two file | | + | descriptors without copying between kernel address space and user | | + | address space, where one of the file descriptors must refer to a | | + | pipe. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :data:`~os.O_EVTONLY`, :data:`~os.O_FSYNC`, :data:`~os.O_SYMLINK` | | + | and :data:`~os.O_NOFOLLOW_ANY` for macOS. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `platform `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :func:`platform.freedesktop_os_release()` to retrieve operation system | | + | identification from `freedesktop.org os-release | | + | `_ standard file. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `socket `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add option to create MPTCP sockets with ``IPPROTO_MPTCP``. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add ``IP_RECVTOS`` option to receive the type of service (ToS) or DSCP/ECN fields. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `ssl `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The ssl module requires OpenSSL 1.1.1 or newer. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The ssl module has preliminary support for OpenSSL 3.0.0 and new option | | + | :data:`~ssl.OP_IGNORE_UNEXPECTED_EOF`. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Deprecated function and use of deprecated constants now result in | | + | a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has | | + | :data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and | | + | therefore cannot warn about setting the flag again. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The ssl module now has more secure default settings. Ciphers without forward | | + | secrecy or SHA-1 MAC are disabled by default. Security level 2 prohibits | | + | weak RSA, DH, and ECC keys with less than 112 bits of security. | | + | :class:`~ssl.SSLContext` defaults to minimum protocol version TLS 1.2. | | + | Settings are based on Hynek Schlawack's research. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The deprecated protocols SSL 3.0, TLS 1.0, and TLS 1.1 are no longer | | + | officially supported. Python does not block them actively. However | | + | OpenSSL build options, distro configurations, vendor patches, and cipher | | + | suites may prevent a successful handshake. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add a *timeout* parameter to the :func:`ssl.get_server_certificate` function. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The ssl module uses heap-types and multi-phase initialization. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | A new verify flag :data:`~ssl.VERIFY_X509_PARTIAL_CHAIN` has been added. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `sys `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :data:`sys.orig_argv` attribute: the list of the original command line | | + | arguments passed to the Python executable. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Add :data:`sys.stdlib_module_names`, containing the list of the standard library | | + | module names. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `_thread `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | :func:`_thread.interrupt_main` now takes an optional signal number to | | + | simulate (the default is still :data:`signal.SIGINT`). | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + +.. rubric:: Notes + +.. [#spm] The structural pattern matching feature is discussed in `issue #7847 `_. + diff --git a/docs/differences/python_35.rst b/docs/differences/python_35.rst new file mode 100644 index 0000000000000..0fdc6121a1dd0 --- /dev/null +++ b/docs/differences/python_35.rst @@ -0,0 +1,193 @@ +.. _python_35: + +Python 3.5 +========== + +Below is a list of finalised/accepted PEPs for Python 3.5 grouped into their impact to MicroPython. + +.. table:: + :widths: 30 50 20 + + +--------------------------------------------------------------------------------------------------------------+--------------------+ + | **Extensions to the syntax** | **Status** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 448 `_ | Additional unpacking generalizations | Partial | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 465 `_ | A new matrix multiplication operator | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 492 `_ | Coroutines with ``async`` and ``await`` syntax | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Extensions and changes to runtime** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 461 `_ | % formatting for binary strings | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 475 `_ | Retrying system calls that fail with ``EINTR`` | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 479 `_ | Change ``StopIteration`` handling inside generators | Complete | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Standard library changes** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 471 `_ | ``os.scandir()`` | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 485 `_ | ``math.isclose()``, a function for testing | Complete | + | | approximate equality | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | **Miscellaneous changes** | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 441 `_ | Improved Python zip application support | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 486 `_ | Make the Python Launcher aware of virtual | Not relevant | + | | environments | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 484 `_ | Type hints (advisory only) | Complete [#fth]_ | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 488 `_ | Elimination of PYO files | Not relevant | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + | `PEP 489 `_ | Redesigning extension module loading | | + +--------------------------------------------------------+-----------------------------------------------------+--------------------+ + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Added the *namereplace* error handlers. The *backslashreplace* error handlers now work with decoding and | | + | translating. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Circular imports involving relative imports are now supported. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + + +New Modules: + +* `typing `_ + +* `zipzap `_ + + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `collections `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *OrderedDict* class is now implemented in C, which makes it 4 to 100 times faster. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | *OrderedDict.items()* , *OrderedDict.keys()* , *OrderedDict.values()* views now support reversed() | | + | iteration. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The deque class now defines *index()*, *insert()*, and *copy()*, and supports the + and * operators. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Docstrings produced by namedtuple() can now be updated. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The UserString class now implements the *__getnewargs__()*, *__rmod__()*, *casefold()*, *format_map()*, | | + | *isprintable()*, and *maketrans()* methods to match the corresponding methods of str. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `heapq `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Element comparison in *merge()* can now be customized by passing a key function in a new optional key | | + | keyword argument, and a new optional *reverse* keyword argument can be used to reverse element comparison | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `io `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *BufferedIOBase.readinto1()* method, that uses at most one call to the underlying raw stream's | | + | *RawIOBase.read()* or *RawIOBase.readinto()* methods | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `json `_ | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | JSON decoder now raises JSONDecodeError instead of ValueError to provide better context information about | | + | the error. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `math `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Two new constants have been added to the math module: *inf* and *nan*. | Complete | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new function *isclose()* provides a way to test for approximate equality. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *gcd()* function has been added. The *fractions.gcd()* function is now deprecated. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `os `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The new *scandir()* function returning an iterator of DirEntry objects has been added. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *urandom()* function now uses the *getrandom()* syscall on Linux 3.17 or newer, and *getentropy()* on | | + | OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file | | + | descriptor exhaustion. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | New *get_blocking()* and *set_blocking()* functions allow getting and setting a file descriptor's blocking| | + | mode (O_NONBLOCK.) | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | There is a new *os.path.commonpath()* function returning the longest common sub-path of each passed | | + | pathname | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `re `_ | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | References and conditional references to groups with fixed length are now allowed in lookbehind assertions| | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The number of capturing groups in regular expressions is no longer limited to 100. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *sub()* and *subn()* functions now replace unmatched groups with empty strings instead of raising an | | + | exception. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *re.error* exceptions have new attributes, msg, pattern, pos, lineno, and colno, that provide better | | + | context information about the error | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `socket `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Functions with timeouts now use a monotonic clock, instead of a system clock. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *socket.sendfile()* method allows sending a file over a socket by using the high-performance | | + | *os.sendfile()* function on UNIX, resulting in uploads being from 2 to 3 times faster than when using | | + | plain *socket.send()* | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *socket.sendall()* method no longer resets the socket timeout every time bytes are received or sent. | | + | The socket timeout is now the maximum total duration to send all data. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The backlog argument of the *socket.listen()* method is now optional. By default it is set to SOMAXCONN or| Complete | + | to 128, whichever is less. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `ssl `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Memory BIO Support | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | Application-Layer Protocol Negotiation Support | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | There is a new *SSLSocket.version()* method to query the actual protocol version in use. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The SSLSocket class now implements a *SSLSocket.sendfile()* method. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *SSLSocket.send()* method now raises either the *ssl.SSLWantReadError* or *ssl.SSLWantWriteError* | | + | exception on a non-blocking socket if the operation would block. Previously, it would return 0. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *cert_time_to_seconds()* function now interprets the input time as UTC and not as local time, per RFC | | + | 5280. Additionally, the return value is always an int. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | New *SSLObject.shared_ciphers()* and *SSLSocket.shared_ciphers()* methods return the list of ciphers sent | | + | by the client during the handshake. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *SSLSocket.do_handshake()*, *SSLSocket.read()*, *SSLSocket.shutdown()*, and *SSLSocket.write()* | | + | methods of the SSLSocket class no longer reset the socket timeout every time bytes are received or sent. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *match_hostname()* function now supports matching of IP addresses. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `sys `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *set_coroutine_wrapper()* function allows setting a global hook that will be called whenever a | | + | coroutine object is created by an async def function. A corresponding *get_coroutine_wrapper()* can be | | + | used to obtain a currently set wrapper. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | A new *is_finalizing()* function can be used to check if the Python interpreter is shutting down. | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | `time `_ | + +-----------------------------------------------------------------------------------------------------------+---------------+ + | The *monotonic()* function is now always available | | + +-----------------------------------------------------------------------------------------------------------+---------------+ + +.. rubric:: Notes + +.. [#fth] The MicroPython parser correct ignores all type hints. However, the ``typing`` module is not built-in. diff --git a/docs/differences/python_36.rst b/docs/differences/python_36.rst new file mode 100644 index 0000000000000..3315b0594dafc --- /dev/null +++ b/docs/differences/python_36.rst @@ -0,0 +1,200 @@ +.. _python_36: + +Python 3.6 +========== + +Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features can be found here: + +.. table:: + :widths: 30 50 20 + + +-----------------------------------------------------------------------------------------------------------+-----------------+ + | **New Syntax Features** | **Status** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 498 `_ | Literal String Formatting | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 515 `_ | Underscores in Numeric Literals | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 525 `_ | Asynchronous Generators | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 526 `_ | Syntax for Variable Annotations (provisional) | Complete | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 530 `_ | Asynchronous Comprehensions | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **New Built-in Features** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 468 `_ | Preserving the order of *kwargs* in a function | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 487 `_ | Simpler customization of class creation | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 520 `_ | Preserving Class Attribute Definition Order | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **Standard Library Changes** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 495 `_ | Local Time Disambiguation | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 506 `_ | Adding A Secrets Module To The Standard Library | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 519 `_ | Adding a file system path protocol | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **CPython Internals** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 509 `_ | Add a private version to dict | Won't do | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 523 `_ | Adding a frame evaluation API to CPython | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | **Linux/Window Changes** | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 524 `_ | Make ``os.urandom()`` blocking on Linux | | + | | (during system startup) | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 528 `_ | Change Windows console encoding to UTF-8 | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + | `PEP 529 `_ | Change Windows filesystem encoding to UTF-8 | | + +--------------------------------------------------------+--------------------------------------------------+-----------------+ + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +-------------------------------------------------------------------------------------------------------------+---------------+ + | A *global* or *nonlocal* statement must now textually appear before the first use of the affected name in | | + | the same scope. Previously this was a SyntaxWarning. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | It is now possible to set a special method to None to indicate that the corresponding operation is not | | + | available. For example, if a class sets *__iter__()* to *None* , the class is not iterable. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Long sequences of repeated traceback lines are now abbreviated as *[Previous line repeated {count} more | | + | times]* | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Import now raises the new exception *ModuleNotFoundError* when it cannot find a module. Code that currently | | + | checks for ImportError (in try-except) will still work. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Class methods relying on zero-argument *super()* will now work correctly when called from metaclass methods | | + | during class creation. | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `array `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Exhausted iterators of *array.array* will now stay exhausted even if the iterated array is extended. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `binascii `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The b2a_base64() function now accepts an optional newline keyword argument to control whether the newline | Complete | + | character is appended to the return value | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `cmath `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new cmath.tau (τ) constant has been added | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | New constants: *cmath.inf* and *cmath.nan* to match *math.inf* and *math.nan* , and also *cmath.infj* and | | + | *cmath.nanj* to match the format used by complex repr | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `collections `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new Collection abstract base class has been added to represent sized iterable container classes | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new *Reversible* abstract base class represents iterable classes that also provide the *__reversed__()* | | + | method. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new *AsyncGenerator* abstract base class represents asynchronous generators. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The *namedtuple()* function now accepts an optional keyword argument module, which, when specified, is used | | + | for the *__module__* attribute of the returned named tuple class. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The verbose and rename arguments for *namedtuple()* are now keyword-only. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Recursive *collections.deque* instances can now be pickled. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `hashlib `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | BLAKE2 hash functions were added to the module. *blake2b()* and *blake2s()* are always available and support | | + | the full feature set of BLAKE2. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The SHA-3 hash functions *sha3_224()*, *sha3_256()*, *sha3_384()*, *sha3_512()*, and *SHAKE* hash functions | | + | *shake_128()* and *shake_256()* were added. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The password-based key derivation function *scrypt()* is now available with OpenSSL 1.1.0 and newer. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `json `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | *json.load()* and *json.loads()* now support binary input. Encoded JSON should be represented using either | | + | UTF-8, UTF-16, or UTF-32. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `math `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new math.tau (τ) constant has been added | Complete | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `os `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | A new *close()* method allows explicitly closing a *scandir()* iterator. The *scandir()* iterator now | | + | supports the context manager protocol. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | On Linux, *os.urandom()* now blocks until the system urandom entropy pool is initialized to increase the | | + | security. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The Linux *getrandom()* syscall (get random bytes) is now exposed as the new *os.getrandom()* function. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `re `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Added support of modifier spans in regular expressions. Examples: *'(?i:p)ython'* matches 'python' and | | + | 'Python', but not 'PYTHON'; *'(?i)g(?-i:v)r'* matches *'GvR'* and *'gvr'*, but not *'GVR'*. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Match object groups can be accessed by *__getitem__*, which is equivalent to *group()*. So *mo['name']* is | | + | now equivalent to *mo.group('name')*. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Match objects now support index-like objects as group indices. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `socket `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The *ioctl()* function now supports the *SIO_LOOPBACK_FAST_PATH* control code. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The *getsockopt()* constants *SO_DOMAIN* , *SO_PROTOCOL*, *SO_PEERSEC* , and *SO_PASSSEC* are now supported. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The *setsockopt()* now supports the *setsockopt(level, optname, None, optlen: int)* form. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The socket module now supports the address family *AF_ALG* to interface with Linux Kernel crypto API. | | + | *ALG_*, *SOL_ALG* and *sendmsg_afalg()* were added. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | New Linux constants *TCP_USER_TIMEOUT* and *TCP_CONGESTION* were added. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `ssl `_ | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | ssl supports OpenSSL 1.1.0. The minimum recommend version is 1.0.2. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | 3DES has been removed from the default cipher suites and ChaCha20 Poly1305 cipher suites have been added. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | *SSLContext* has better default configuration for options and ciphers. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | SSL session can be copied from one client-side connection to another with the new *SSLSession* class. TLS | | + | session resumption can speed up the initial handshake, reduce latency and improve performance. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new *get_ciphers()* method can be used to get a list of enabled ciphers in order of cipher priority. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | All constants and flags have been converted to *IntEnum* and *IntFlags*. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Server and client-side specific TLS protocols for *SSLContext* were added. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | Added *SSLContext.post_handshake_auth* to enable and *ssl.SSLSocket.verify_client_post_handshake()* to | | + | initiate TLS 1.3 post-handshake authentication. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `struct `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | now supports IEEE 754 half-precision floats via the 'e' format specifier. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `sys `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The new *getfilesystemencodeerrors()* function returns the name of the error mode used to convert between | | + | Unicode filenames and bytes filenames. | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | `zlib `_ | | + +--------------------------------------------------------------------------------------------------------------+----------------+ + | The *compress()* and *decompress()* functions now accept keyword arguments | | + +--------------------------------------------------------------------------------------------------------------+----------------+ diff --git a/docs/differences/python_37.rst b/docs/differences/python_37.rst new file mode 100644 index 0000000000000..86d1b6e81f96d --- /dev/null +++ b/docs/differences/python_37.rst @@ -0,0 +1,108 @@ +.. _python_37: + +Python 3.7 +========== + +New Features: + +.. table:: + :widths: 20 60 20 + + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | **Feature** | **Status** | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 538 `_ | Coercing the legacy C locale to a UTF-8 based | | + | | locale | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 539 `_ | A New C-API for Thread-Local Storage in CPython | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 540 `_ | UTF-8 mode | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 552 `_ | Deterministic pyc | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 553 `_ | Built-in ``breakpoint()`` | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 557 `_ | Data Classes | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 560 `_ | Core support for typing module and generic types | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 562 `_ | Module ``__getattr__`` and ``__dir__`` | Partial | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 563 `_ | Postponed Evaluation of Annotations | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 564 `_ | Time functions with nanosecond resolution | Partial [#ftimenanosec]_ | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 565 `_ | Show DeprecationWarning in ``__main__`` | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + | `PEP 567 `_ | Context Variables | | + +--------------------------------------------------------+--------------------------------------------------+--------------------------------------+ + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``async`` and ``await`` are now reserved keywords | Complete | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``dict`` objects must preserve insertion-order | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | More than 255 arguments can now be passed to a function; a function can now have more than 255 parameters | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``bytes.fromhex()`` and ``bytearray.fromhex()`` now ignore all ASCII whitespace, not only spaces | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``str``, ``bytes``, and ``bytearray`` gained support for the new ``isascii()`` method, which can be used to | | + | test if a string or bytes contain only the ASCII characters | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``ImportError`` now displays module name and module ``__file__`` path when ``from ... import ...`` fails | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | Circular imports involving absolute imports with binding a submodule to a name are now supported | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | ``object.__format__(x, '')`` is now equivalent to ``str(x)`` rather than ``format(str(self), '')`` | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | In order to better support dynamic creation of stack traces, ``types.TracebackType`` can now be | | + | instantiated from Python code, and the ``tb_next`` attribute on tracebacks is now writable | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | When using the ``-m`` switch, ``sys.path[0]`` is now eagerly expanded to the full starting directory path, | | + | rather than being left as the empty directory (which allows imports from the current working directory | | + | at the time when an import occurs) | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + | The new ``-X importtime`` option or the ``PYTHONPROFILEIMPORTTIME`` environment variable can be used to | | + | show the timing of each module import | | + +-----------------------------------------------------------------------------------------------------------------+----------------+ + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +------------------------------------------------------------------------------------------------------------+----------------+ + | `asyncio `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | Too many to list | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | `gc `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | New features include *gc.freeze()*, *gc.unfreeze()*, *gc-get_freeze_count* | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | `math `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | math.remainder() added to implement IEEE 754-style remainder | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | `re `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | A number of tidy up features including better support for splitting on empty strings and copy support for | | + | compiled expressions and match objects | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | `sys `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | sys.breakpointhook() added. sys.get(/set)_coroutine_origin_tracking_depth() added | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | `time `_ | | + +------------------------------------------------------------------------------------------------------------+----------------+ + | Mostly updates to support nanosecond resolution in PEP564, see above | | + +------------------------------------------------------------------------------------------------------------+----------------+ + +.. rubric:: Notes + +.. [#ftimenanosec] Only :func:`time.time_ns` is implemented. diff --git a/docs/differences/python_38.rst b/docs/differences/python_38.rst new file mode 100644 index 0000000000000..32fd68d2caeac --- /dev/null +++ b/docs/differences/python_38.rst @@ -0,0 +1,127 @@ +.. _python_38: + +Python 3.8 +========== + +Python 3.8.0 (final) was released on the 14 October 2019. The Features for 3.8 +are defined in `PEP 569 `_ and +a detailed description of the changes can be found in `What's New in Python +3.8. `_ + +.. table:: + :widths: 20 60 20 + + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | **Features** | **Status** | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 570 `_ | Positional-only arguments | | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 572 `_ | Assignment Expressions | Complete | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 574 `_ | Pickle protocol 5 with out-of-band data | | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 578 `_ | Runtime audit hooks | | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 587 `_ | Python Initialization Configuration | | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | `PEP 590 `_ | Vectorcall: a fast calling protocol for CPython | | + +--------------------------------------------------------+---------------------------------------------------+---------------+ + | **Miscellaneous** | + +------------------------------------------------------------------------------------------------------------+---------------+ + | f-strings support = for self-documenting expressions and debugging | Complete | + +------------------------------------------------------------------------------------------------------------+---------------+ + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +------------------------------------------------------------------------------------------------------------+-------------+ + | A *continue* statement was illegal in the *finally* clause due to a problem with the implementation. In | Complete | + | Python 3.8 this restriction was lifted | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | The *bool*, *int* , and *fractions.Fraction* types now have an *as_integer_ratio()* method like that found | | + | in *float* and *decimal.Decimal* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Constructors of *int*, *float* and *complex* will now use the *__index__()* special method, if available | | + | and the corresponding method *__int__()*, *__float__()* or *__complex__()* is not available | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added support of *\N{name}* escapes in regular expressions | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Dict and dictviews are now iterable in reversed insertion order using *reversed()* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | The syntax allowed for keyword names in function calls was further restricted. In particular, | | + | f((keyword)=arg) is no longer allowed | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Generalized iterable unpacking in yield and return statements no longer requires enclosing parentheses | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | When a comma is missed in code such as [(10, 20) (30, 40)], the compiler displays a SyntaxWarning with a | | + | helpful suggestion | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Arithmetic operations between subclasses of *datetime.date* or *datetime.datetime* and *datetime.timedelta*| | + | objects now return an instance of the subclass, rather than the base class | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | When the Python interpreter is interrupted by *Ctrl-C (SIGINT)* and the resulting *KeyboardInterrupt* | | + | exception is not caught, the Python process now exits via a SIGINT signal or with the correct exit code | | + | such that the calling process can detect that it died due to a *Ctrl-C* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Some advanced styles of programming require updating the *types.CodeType* object for an existing function | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | For integers, the three-argument form of the pow() function now permits the exponent to be negative in the | | + | case where the base is relatively prime to the modulus | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Dict comprehensions have been synced-up with dict literals so that the key is computed first and the value | | + | second | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | The *object.__reduce__()* method can now return a tuple from two to six elements long | | + +------------------------------------------------------------------------------------------------------------+-------------+ + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +------------------------------------------------------------------------------------------------------------+-------------+ + | `asyncio `_ | + +------------------------------------------------------------------------------------------------------------+-------------+ + | *asyncio.run()* has graduated from the provisional to stable API | Complete | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Running *python -m asyncio* launches a natively async REPL | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | The exception *asyncio.CancelledError* now inherits from *BaseException* rather than *Exception* and no | Complete | + | longer inherits from *concurrent.futures.CancelledError* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added *asyncio.Task.get_coro()* for getting the wrapped coroutine within an *asyncio.Task* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Asyncio tasks can now be named, either by passing the name keyword argument to *asyncio.create_task()* or | | + | the *create_task()* event loop method, or by calling the *set_name()* method on the task object | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added support for Happy Eyeballs to *asyncio.loop.create_connection()*. To specify the behavior, two new | | + | parameters have been added: *happy_eyeballs_delay* and interleave. | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | `gc `_ | + +------------------------------------------------------------------------------------------------------------+-------------+ + | *get_objects()* can now receive an optional generation parameter indicating a generation to get objects | | + | from. (Note, though, that while *gc* is a built-in, *get_objects()* is not implemented for MicroPython) | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | `math `_ | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added new function *math.dist()* for computing Euclidean distance between two points | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Expanded the *math.hypot()* function to handle multiple dimensions | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added new function, *math.prod()*, as analogous function to *sum()* that returns the product of a "start" | | + | value (default: 1) times an iterable of numbers | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added two new combinatoric functions *math.perm()* and *math.comb()* | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Added a new function *math.isqrt()* for computing accurate integer square roots without conversion to | | + | floating point | | + +------------------------------------------------------------------------------------------------------------+-------------+ + | The function *math.factorial()* no longer accepts arguments that are not int-like | Complete | + +------------------------------------------------------------------------------------------------------------+-------------+ + | `sys `_ | + +------------------------------------------------------------------------------------------------------------+-------------+ + | Add new *sys.unraisablehook()* function which can be overridden to control how "unraisable exceptions" | | + | are handled | | + +------------------------------------------------------------------------------------------------------------+-------------+ diff --git a/docs/differences/python_39.rst b/docs/differences/python_39.rst new file mode 100644 index 0000000000000..f68abc50740ac --- /dev/null +++ b/docs/differences/python_39.rst @@ -0,0 +1,134 @@ +.. _python_39: + +Python 3.9 +========== + +Python 3.9.0 (final) was released on the 5th October 2020. The Features for 3.9 are +defined in `PEP 596 `_ +and a detailed description of the changes can be found in +`What's New in Python 3.9 `_ + +.. table:: + :widths: 20 60 20 + + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | **Features** | | **Status** | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 573 `_ | Fast access to module state from methods of C | Not relevant | + | | extension types | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 584 `_ | Union operators added to dict | Complete [#pep584]_ | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 585 `_ | Type hinting generics in standard collections | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 593 `_ | Flexible function and variable annotations | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 602 `_ | CPython adopts an annual release cycle. Instead of | Not relevant | + | | annual, aiming for two month release cycle | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 614 `_ | Relaxed grammar restrictions on decorators | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 615 `_ | The IANA Time Zone Database is now present in the | | + | | standard library in the zoneinfo module | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 616 `_ | String methods to remove prefixes and suffixes | | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + | `PEP 617 `_ | CPython now uses a new parser based on PEG | Not relevant | + +--------------------------------------------------------+----------------------------------------------------+----------------------+ + +Other Language Changes: + +.. table:: + :widths: 90 10 + + +-------------------------------------------------------------------------------------------------------------+---------------+ + | *__import__()* now raises *ImportError* instead of *ValueError* | Complete | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Python now gets the absolute path of the script filename specified on the command line (ex: *python3* | | + | *script.py*): the *__file__* attribute of the *__main__* module became an absolute path, rather than a | | + | relative path | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | By default, for best performance, the errors argument is only checked at the first encoding/decoding error | | + | and the encoding argument is sometimes ignored for empty strings | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | *"".replace("", s, n)* now returns *s* instead of an empty string for all non-zero n. It is now consistent | | + | with *"".replace("", s)* | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Any valid expression can now be used as a decorator. Previously, the grammar was much more restrictive | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Parallel running of *aclose()* / *asend()* / *athrow()* is now prohibited, and *ag_running* now reflects | | + | the actual running status of the async generator | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Unexpected errors in calling the *__iter__* method are no longer masked by TypeError in the in operator and | | + | functions contains(), indexOf() and countOf() of the operator module | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + | Unparenthesized lambda expressions can no longer be the expression part in an if clause in comprehensions | | + | and generator expressions | | + +-------------------------------------------------------------------------------------------------------------+---------------+ + +Changes to built-in modules: + +.. table:: + :widths: 90 10 + + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `asyncio `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Due to significant security concerns, the reuse_address parameter of *asyncio.loop.create_datagram_endpoint()*| | + | is no longer supported | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added a new coroutine *shutdown_default_executor()* that schedules a shutdown for the default executor that | | + | waits on the *ThreadPoolExecutor* to finish closing. Also, *asyncio.run()* has been updated to use the new | | + | coroutine. | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added *asyncio.PidfdChildWatcher*, a Linux-specific child watcher implementation that polls process file | | + | descriptors | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | added a new *coroutine asyncio.to_thread()* | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | When cancelling the task due to a timeout, *asyncio.wait_for()* will now wait until the cancellation is | | + | complete also in the case when timeout is <= 0, like it does with positive timeouts | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | *asyncio* now raises *TyperError* when calling incompatible methods with an *ssl.SSLSocket* socket | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `gc `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Garbage collection does not block on resurrected objects | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added a new function *gc.is_finalized()* to check if an object has been finalized by the garbage collector | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `math `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Expanded the *math.gcd()* function to handle multiple arguments. Formerly, it only supported two arguments | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added *math.lcm()*: return the least common multiple of specified arguments | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added *math.nextafter()*: return the next floating-point value after x towards y | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added *math.ulp()*: return the value of the least significant bit of a float | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `os `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Exposed the Linux-specific *os.pidfd_open()* and *os.P_PIDFD* | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The *os.unsetenv()* function is now also available on Windows | Complete | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | The *os.putenv()* and *os.unsetenv()* functions are now always available | Complete | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added *os.waitstatus_to_exitcode()* function: convert a wait status to an exit code | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `random `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added a new *random.Random.randbytes* method: generate random bytes | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | `sys `_ | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Added a new *sys.platlibdir* attribute: name of the platform-specific library directory | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + | Previously, *sys.stderr* was block-buffered when non-interactive. Now stderr defaults to always being | | + | line-buffered | | + +---------------------------------------------------------------------------------------------------------------+---------------+ + +.. rubric:: Notes + +.. [#pep584] PEP 584 ``dict`` union operator is only available on MicroPython builds with ``MICROPY_CPYTHON_COMPAT`` enabled. diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 7391a4aa4b546..9c77dc402ebef 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -57,7 +57,6 @@ The :mod:`esp32` module:: import esp32 - esp32.hall_sensor() # read the internal hall sensor esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit esp32.ULP() # access to the Ultra-Low-Power Co-processor @@ -68,6 +67,9 @@ by reading the temperature sensor immediately after waking up from sleep. Networking ---------- +WLAN +^^^^ + The :mod:`network` module:: import network @@ -76,12 +78,12 @@ The :mod:`network` module:: wlan.active(True) # activate the interface wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP - wlan.connect('essid', 'password') # connect to an AP + wlan.connect('ssid', 'key') # connect to an AP wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface - ap.config(essid='ESP-AP') # set the ESSID of the access point + ap.config(ssid='ESP-AP') # set the SSID of the access point ap.config(max_clients=10) # set how many clients can connect to the network ap.active(True) # activate the interface @@ -93,13 +95,13 @@ A useful function for connecting to your local WiFi network is:: wlan.active(True) if not wlan.isconnected(): print('connecting to network...') - wlan.connect('essid', 'password') + wlan.connect('ssid', 'key') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) Once the network is established the :mod:`socket ` module can be used -to create and use TCP/UDP sockets as usual, and the ``urequests`` module for +to create and use TCP/UDP sockets as usual, and the ``requests`` module for convenient HTTP requests. After a call to ``wlan.connect()``, the device will by default retry to connect @@ -110,6 +112,55 @@ calling ``wlan.config(reconnects=n)``, where n are the number of desired reconne attempts (0 means it won't retry, -1 will restore the default behaviour of trying to reconnect forever). +LAN +^^^ + +To use the wired interfaces one has to specify the pins and mode :: + + import network + + lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration + lan.active(True) # activate the interface + lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses + + +The keyword arguments for the constructor defining the PHY type and interface are: + +- mdc=pin-object # set the mdc and mdio pins. +- mdio=pin-object +- power=pin-object # set the pin which switches the power of the PHY device. +- phy_type= # Select the PHY device type. Supported devices are PHY_LAN8710, + PHY_LAN8720, PH_IP101, PHY_RTL8201, PHY_DP83848 and PHY_KSZ8041 +- phy_addr=number # The address number of the PHY device. +- ref_clk_mode=mode # Defines, whether the ref_clk at the ESP32 is an input + or output. Suitable values are Pin.IN and Pin.OUT. +- ref_clk=pin-object # defines the Pin used for ref_clk. + +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), + phy_type=network.PHY_LAN8720, phy_addr=0, + ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT) + + # Wireless-Tag's WT32-ETH01 + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), + phy_type=network.PHY_LAN8720, phy_addr=1, power=None) + + # Wireless-Tag's WT32-ETH01 v1.4 + + lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), + phy_type=network.PHY_LAN8720, phy_addr=1, + power=machine.Pin(16)) + + # Espressif ESP32-Ethernet-Kit_A_V1.2 + + lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5), + phy_type=network.PHY_IP101, phy_addr=1) + Delay and timing ---------------- @@ -160,6 +211,7 @@ Use the :ref:`machine.Pin ` class:: p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation + p6 = Pin(6, Pin.OUT, drive=Pin.DRIVE_3) # set maximum drive strength Available Pins are from the following ranges (inclusive): 0-19, 21-23, 25-27, 32-39. These correspond to the actual GPIO pin numbers of ESP32 chip. Note that many @@ -167,6 +219,23 @@ end-user boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). For mapping between board logical pins and physical chip pins consult your board documentation. +Four drive strengths are supported, using the ``drive`` keyword argument to the +``Pin()`` constructor or ``Pin.init()`` method, with different corresponding +safe maximum source/sink currents and approximate internal driver resistances: + + - ``Pin.DRIVE_0``: 5mA / 130 ohm + - ``Pin.DRIVE_1``: 10mA / 60 ohm + - ``Pin.DRIVE_2``: 20mA / 30 ohm (default strength if not configured) + - ``Pin.DRIVE_3``: 40mA / 15 ohm + +The ``hold=`` keyword argument to ``Pin()`` and ``Pin.init()`` will enable the +ESP32 "pad hold" feature. When set to ``True``, the pin configuration +(direction, pull resistors and output value) will be held and any further +changes (including changing the output level) will not be applied. Setting +``hold=False`` will immediately apply any outstanding pin configuration changes +and release the pin. Using ``hold=True`` while a pin is already held will apply +any configuration changes and then immediately reapply the hold. + Notes: * Pins 1 and 3 are REPL UART TX and RX respectively @@ -176,8 +245,7 @@ Notes: * Pins 34-39 are input only, and also do not have internal pull-up resistors -* The pull value of some pins can be set to ``Pin.PULL_HOLD`` to reduce power - consumption during deepsleep. +* See :ref:`Deep_sleep_Mode` for a discussion of pin behaviour during sleep There's a higher-level abstraction :ref:`machine.Signal ` which can be used to invert a pin. Useful for illuminating active-low LEDs @@ -199,9 +267,10 @@ They each have default GPIO assigned to them, however depending on your ESP32 variant and board, these pins may conflict with embedded flash, onboard PSRAM or peripherals. -Any GPIO can be used for hardware UARTs using the GPIO matrix, so to avoid -conflicts simply provide ``tx`` and ``rx`` pins when constructing. The default -pins listed below. +Any GPIO can be used for hardware UARTs using the GPIO matrix, except for +input-only pins 34-39 that can be used as ``rx``. To avoid conflicts simply +provide ``tx`` and ``rx`` pins when constructing. The default pins listed +below. ===== ===== ===== ===== \ UART0 UART1 UART2 @@ -218,20 +287,28 @@ range from 1Hz to 40MHz but there is a tradeoff; as the base frequency *increases* the duty resolution *decreases*. See `LED Control `_ for more details. -Currently the duty cycle has to be in the range of 0-1023. -Use the ``machine.PWM`` class:: +Use the :ref:`machine.PWM ` class:: from machine import Pin, PWM - pwm0 = PWM(Pin(0)) # create PWM object from a pin - pwm0.freq() # get current frequency (default 5kHz) - pwm0.freq(1000) # set frequency - pwm0.duty() # get current duty cycle (default 512, 50%) - pwm0.duty(200) # set duty cycle - pwm0.deinit() # turn off PWM on the pin + pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin + freq = pwm0.freq() # get current frequency + pwm0.freq(1000) # set PWM frequency from 1Hz to 40MHz + + duty = pwm0.duty() # get current duty cycle, range 0-1023 (default 512, 50%) + pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%) + + duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535 + pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%) + + duty_ns = pwm0.duty_ns() # get current pulse width in ns + pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%) + + pwm0.deinit() # turn off PWM on the pin pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go + print(pwm2) # view PWM settings ESP chips have different hardware peripherals: @@ -242,7 +319,7 @@ Number of groups (speed modes) 2 1 Number of timers per group 4 4 4 Number of channels per group 8 8 6 ----------------------------------------------------- -------- -------- -------- -Different of PWM frequencies (groups * timers) 8 4 4 +Different PWM frequencies (groups * timers) 8 4 4 Total PWM channels (Pins, duties) (groups * channels) 16 8 6 ===================================================== ======== ======== ======== @@ -251,57 +328,117 @@ but only 8 different PWM frequencies are available, the remaining 8 channels mus have the same frequency. On the other hand, 16 independent PWM duty cycles are 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) ---------------------------------- -On the ESP32 ADC functionality is available on Pins 32-39. Note that, when -using the default configuration, input voltages on the ADC pin must be between -0.0v and 1.0v (anything above 1.0v will just read as 4095). Attenuation must -be applied in order to increase this usable voltage range. +On the ESP32, ADC functionality is available on pins 32-39 (ADC block 1) and +pins 0, 2, 4, 12-15 and 25-27 (ADC block 2). Use the :ref:`machine.ADC ` class:: from machine import ADC - adc = ADC(Pin(32)) # create ADC object on ADC pin - adc.read() # read value, 0-4095 across voltage range 0.0v - 1.0v + adc = ADC(pin) # create an ADC object acting on a pin + val = adc.read_u16() # read a raw analog value in the range 0-65535 + val = adc.read_uv() # read an analog value in microvolts + +ADC block 2 is also used by WiFi and so attempting to read analog values from +block 2 pins when WiFi is active will raise an exception. + +The internal ADC reference voltage is typically 1.1V, but varies slightly from +package to package. The ADC is less linear close to the reference voltage +(particularly at higher attenuations) and has a minimum measurement voltage +around 100mV, voltages at or below this will read as 0. To read voltages +accurately, it is recommended to use the ``read_uv()`` method (see below). - adc.atten(ADC.ATTN_11DB) # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v) - adc.width(ADC.WIDTH_9BIT) # set 9 bit return values (returned range 0-511) - adc.read() # read value using the newly configured attenuation and width +ESP32-specific ADC class method reference: -ESP32 specific ADC class method reference: +.. class:: ADC(pin, *, atten) -.. method:: ADC.atten(attenuation) + Return the ADC object for the specified pin. ESP32 does not support + different timings for ADC sampling and so the ``sample_ns`` keyword argument + is not supported. - This method allows for the setting of the amount of attenuation on the - input of the ADC. This allows for a wider possible input voltage range, - at the cost of accuracy (the same number of bits now represents a wider - range). The possible attenuation options are: + To read voltages above the reference voltage, apply input attenuation with + the ``atten`` keyword argument. Valid values (and approximate linear + measurement ranges) are: - - ``ADC.ATTN_0DB``: 0dB attenuation, gives a maximum input voltage - of 1.00v - this is the default configuration - - ``ADC.ATTN_2_5DB``: 2.5dB attenuation, gives a maximum input voltage - of approximately 1.34v - - ``ADC.ATTN_6DB``: 6dB attenuation, gives a maximum input voltage - of approximately 2.00v - - ``ADC.ATTN_11DB``: 11dB attenuation, gives a maximum input voltage - of approximately 3.6v + - ``ADC.ATTN_0DB``: No attenuation (100mV - 950mV) + - ``ADC.ATTN_2_5DB``: 2.5dB attenuation (100mV - 1250mV) + - ``ADC.ATTN_6DB``: 6dB attenuation (150mV - 1750mV) + - ``ADC.ATTN_11DB``: 11dB attenuation (150mV - 2450mV) .. Warning:: - Despite 11dB attenuation allowing for up to a 3.6v range, note that the - absolute maximum voltage rating for the input pins is 3.6v, and so going - near this boundary may be damaging to the IC! + Note that the absolute maximum voltage rating for input pins is 3.6V. Going + near to this boundary risks damage to the IC! -.. method:: ADC.width(width) +.. method:: ADC.read_uv() - This method allows for the setting of the number of bits to be utilised - and returned during ADC reads. Possible width options are: + This method uses the known characteristics of the ADC and per-package eFuse + values - set during manufacture - to return a calibrated input voltage + (before attenuation) in microvolts. The returned value has only millivolt + resolution (i.e., will always be a multiple of 1000 microvolts). + + The calibration is only valid across the linear range of the ADC. In + particular, an input tied to ground will read as a value above 0 microvolts. + Within the linear range, however, more accurate and consistent results will + be obtained than using `read_u16()` and scaling the result with a constant. + +The ESP32 port also supports the :ref:`machine.ADC ` API: + +.. class:: ADCBlock(id, *, bits) + + Return the ADC block object with the given ``id`` (1 or 2) and initialize + it to the specified resolution (9 to 12-bits depending on the ESP32 series) + or the highest supported resolution if not specified. + +.. method:: ADCBlock.connect(pin) + ADCBlock.connect(channel) + ADCBlock.connect(channel, pin) + + Return the ``ADC`` object for the specified ADC pin or channel number. + Arbitrary connection of ADC channels to GPIO is not supported and so + specifying a pin that is not connected to this block, or specifying a + mismatched channel and pin, will raise an exception. + +Legacy methods: + +.. method:: ADC.read() + + This method returns the raw ADC value ranged according to the resolution of + the block, e.g., 0-4095 for 12-bit resolution. + +.. method:: ADC.atten(atten) + + Equivalent to ``ADC.init(atten=atten)``. + +.. method:: ADC.width(bits) + + Equivalent to ``ADC.block().init(bits=bits)``. + +For compatibility, the ``ADC`` object also provides constants matching the +supported ADC resolutions: + + - ``ADC.WIDTH_9BIT`` = 9 + - ``ADC.WIDTH_10BIT`` = 10 + - ``ADC.WIDTH_11BIT`` = 11 + - ``ADC.WIDTH_12BIT`` = 12 - - ``ADC.WIDTH_9BIT``: 9 bit data - - ``ADC.WIDTH_10BIT``: 10 bit data - - ``ADC.WIDTH_11BIT``: 11 bit data - - ``ADC.WIDTH_12BIT``: 12 bit data - this is the default configuration Software SPI bus ---------------- @@ -409,14 +546,14 @@ I2S bus See :ref:`machine.I2S `. :: from machine import I2S, Pin - + i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object i2s.write(buf) # write buffer of audio samples to I2S device - + i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object i2s.readinto(buf) # fill buffer with audio samples from I2S device - -The I2S class is currently available as a Technical Preview. During the preview period, feedback from + +The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. ESP32 has two I2S buses with id=0 and id=1 @@ -443,6 +580,8 @@ See :ref:`machine.WDT `. :: wdt = WDT(timeout=5000) wdt.feed() +.. _Deep_sleep_mode: + Deep-sleep mode --------------- @@ -462,30 +601,64 @@ Notes: * Calling ``deepsleep()`` without an argument will put the device to sleep indefinitely * A software reset does not change the reset cause -* There may be some leakage current flowing through enabled internal pullups. - To further reduce power consumption it is possible to disable the internal pullups:: - p1 = Pin(4, Pin.IN, Pin.PULL_HOLD) +Some ESP32 pins (0, 2, 4, 12-15, 25-27, 32-39) are connected to the RTC during +deep-sleep and can be used to wake the device with the ``wake_on_`` functions in +the :mod:`esp32` module. The output-capable RTC pins (all except 34-39) will +also retain their pull-up or pull-down resistor configuration when entering +deep-sleep. + +If the pull resistors are not actively required during deep-sleep and are likely +to cause current leakage (for example a pull-up resistor is connected to ground +through a switch), then they should be disabled to save power before entering +deep-sleep mode:: + + from machine import Pin, deepsleep - After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if - it is an output pin) via:: + # configure input RTC pin with pull-up on boot + pin = Pin(2, Pin.IN, Pin.PULL_UP) + + # disable pull-up and put the device to sleep for 10 seconds + pin.init(pull=None) + machine.deepsleep(10000) + +Output-configured RTC pins will also retain their output direction and level in +deep-sleep if pad hold is enabled with the ``hold=True`` argument to +``Pin.init()``. + +Non-RTC GPIO pins will be disconnected by default on entering deep-sleep. +Configuration of non-RTC pins - including output level - can be retained by +enabling pad hold on the pin and enabling GPIO pad hold during deep-sleep:: + + from machine import Pin, deepsleep + import esp32 - p1 = Pin(4, Pin.OUT, None) + opin = Pin(19, Pin.OUT, value=1, hold=True) # hold output level + ipin = Pin(21, Pin.IN, Pin.PULL_UP, hold=True) # hold pull-up + + # enable pad hold in deep-sleep for non-RTC GPIO + esp32.gpio_deep_sleep_hold(True) + + # put the device to sleep for 10 seconds + deepsleep(10000) + +The pin configuration - including the pad hold - will be retained on wake from +sleep. See :ref:`Pins_and_GPIO` above for a further discussion of pad holding. SD card ------- See :ref:`machine.SDCard `. :: - import machine, os + import machine, os, vfs # Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23 sd = machine.SDCard(slot=2) - os.mount(sd, "/sd") # mount + vfs.mount(sd, '/sd') # mount os.listdir('/sd') # list directory contents - os.umount('/sd') # eject + vfs.umount('/sd') # eject RMT --- @@ -499,7 +672,7 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with r = esp32.RMT(0, pin=Pin(18), clock_div=8) r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) # The channel resolution is 100ns (1/(source_freq/clock_div)). - r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns + r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns OneWire driver -------------- @@ -552,17 +725,16 @@ The APA106 driver extends NeoPixel, but internally uses a different colour order ap = APA106(pin, 8) r, g, b = ap[0] -For low-level driving of a NeoPixel:: - - import esp - esp.neopixel_write(pin, grb_buf, is800khz) - .. Warning:: By default ``NeoPixel`` is configured to control the more popular *800kHz* units. It is possible to use alternative timing to control other (typically 400kHz) devices by passing ``timing=0`` when constructing the ``NeoPixel`` object. +For low-level driving of a NeoPixel see `machine.bitstream`. +This low-level driver uses an RMT channel by default. To configure this see +`RMT.bitstream_channel`. + APA102 (DotStar) uses a different driver as it has an additional clock pin. Capacitive touch diff --git a/docs/esp32/tutorial/img/mem32_gpio_output.jpg b/docs/esp32/tutorial/img/mem32_gpio_output.jpg new file mode 100755 index 0000000000000..5544202871eb7 Binary files /dev/null and b/docs/esp32/tutorial/img/mem32_gpio_output.jpg differ diff --git a/docs/esp32/tutorial/intro.rst b/docs/esp32/tutorial/intro.rst index 4c567383476f9..be09599871ce6 100644 --- a/docs/esp32/tutorial/intro.rst +++ b/docs/esp32/tutorial/intro.rst @@ -17,7 +17,7 @@ Requirements The first thing you need is a board with an ESP32 chip. The MicroPython software supports the ESP32 chip itself and any board should work. The main characteristic of a board is how the GPIO pins are connected to the outside -world, and whether it includes a built-in USB-serial convertor to make the +world, and whether it includes a built-in USB-serial converter to make the UART available to your PC. Names of pins will be given in this tutorial using the chip names (eg GPIO2) @@ -34,8 +34,8 @@ Please refer to the documentation for your board for further details. Getting the firmware -------------------- -The first thing you need to do is download the most recent MicroPython firmware -.bin file to load onto your ESP32 device. You can download it from the +The first thing you need to do is download the most recent MicroPython firmware +.bin file to load onto your ESP32 device. You can download it from the `MicroPython downloads page `_. From here, you have 3 main choices: @@ -59,7 +59,7 @@ bootloader mode, and second you need to copy across the firmware. The exact procedure for these steps is highly dependent on the particular board and you will need to refer to its documentation for details. -Fortunately, most boards have a USB connector, a USB-serial convertor, and the DTR +Fortunately, most boards have a USB connector, a USB-serial converter, and the DTR and RTS pins wired in a special way then deploying the firmware should be easy as all steps can be done automatically. Boards that have such features include the Adafruit Feather HUZZAH32, M5Stack, Wemos LOLIN32, and TinyPICO @@ -104,7 +104,7 @@ Serial prompt Once you have the firmware on the device you can access the REPL (Python prompt) over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial -convertor, depending on your board. The baudrate is 115200. +converter, depending on your board. The baudrate is 115200. From here you can now follow the ESP8266 tutorial, because these two Espressif chips are very similar when it comes to using MicroPython on them. The ESP8266 tutorial @@ -124,7 +124,7 @@ after it, here are troubleshooting recommendations: * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your - module/board, USB-UART convertor, cables, host OS, etc., the above baud + module/board, USB-UART converter, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. diff --git a/docs/esp32/tutorial/peripheral_access.rst b/docs/esp32/tutorial/peripheral_access.rst index 3304c341de873..ecdec101f7ef7 100644 --- a/docs/esp32/tutorial/peripheral_access.rst +++ b/docs/esp32/tutorial/peripheral_access.rst @@ -42,3 +42,83 @@ for this: The MCPWM0 peripheral is in bit position 17 of the above two registers, hence the value of ``DPORT_PWM0_CLK_EN``. + +Synchronous access to pins directly via registers +------------------------------------------------- + +The following code shows how to access pins directly via registers. It has been +tested on a generic ESP32 board. It configures pins 16, 17, 32 and 33 in output +mode via registers, and switches pin output values via registers. Pins 16 and +17 are switched simultaneously. + +.. code-block:: python3 + + from micropython import const + from machine import mem32, Pin + + GPIO_OUT_REG = const(0x3FF44004) # GPIO 0-31 output register + GPIO_OUT1_REG = const(0x3FF44010) # GPIO 32-39 output register + + GPIO_ENABLE_REG = const(0x3FF44020) # GPIO 0-31 output enable register + GPIO_ENABLE1_REG = const(0x3FF4402C) # GPIO 32-39 output enable register + + M16 = 1 << 16 # Pin(16) bit mask + M17 = 1 << 17 # Pin(17) bit mask + + M32 = 1 << (32-32) # Pin(32) bit mask + M33 = 1 << (33-32) # Pin(33) bit mask + + # Enable pin output mode like + # p16 = Pin(16, mode=Pin.OUT) + # p17 = Pin(17, mode=Pin.OUT) + # p32 = Pin(32, mode=Pin.OUT) + # p33 = Pin(33, mode=Pin.OUT) + mem32[GPIO_ENABLE_REG] = mem32[GPIO_ENABLE_REG] | M16 | M17 + mem32[GPIO_ENABLE1_REG] = mem32[GPIO_ENABLE1_REG] | M32 | M33 + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + # Set outputs to 1 like + # p16(1) + # p17(1) + # p32(1) + # p33(1) + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17 + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33 + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + # Set outputs to 0 like + # p16(0) + # p17(0) + # p32(0) + # p33(0) + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17) + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33) + + print(hex(mem32[GPIO_OUT_REG]), hex(mem32[GPIO_OUT1_REG])) + + while True: + # Set outputs to 1 + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] | M16 | M17 + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] | M32 | M33 + + # Set outputs to 0 + mem32[GPIO_OUT_REG] = mem32[GPIO_OUT_REG] & ~(M16 | M17) + mem32[GPIO_OUT1_REG] = mem32[GPIO_OUT1_REG] & ~(M32 | M33) + + +Output is:: + + 0x0 0x0 + 0x30000 0x3 + 0x0 0x0 + +Pins 16 and 17 are switched synchronously: + +.. image:: img/mem32_gpio_output.jpg + +Same image on pins 32 and 33. + +Note that pins 34-36 and 39 are inputs only. Also pins 1 and 3 are Tx, Rx of the REPL UART, +pins 6-11 are connected to the built-in SPI flash. diff --git a/docs/esp32/tutorial/pwm.rst b/docs/esp32/tutorial/pwm.rst index 0c1afb213b2df..2650284d35f41 100644 --- a/docs/esp32/tutorial/pwm.rst +++ b/docs/esp32/tutorial/pwm.rst @@ -1,4 +1,4 @@ -.. _esp32_pwm: +.. _esp32_pwm: Pulse Width Modulation ====================== @@ -11,7 +11,7 @@ compared with the length of a single period (low plus high time). Maximum duty cycle is when the pin is high all of the time, and minimum is when it is low all of the time. -More comprehensive example with all 16 PWM channels and 8 timers:: +* More comprehensive example with all 16 PWM channels and 8 timers:: from machine import Pin, PWM try: @@ -29,21 +29,87 @@ More comprehensive example with all 16 PWM channels and 8 timers:: except: pass -Output is:: - - PWM(pin=15, freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0) - PWM(pin=2, freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0) - PWM(pin=4, freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1) - PWM(pin=16, freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1) - PWM(pin=18, freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2) - PWM(pin=19, freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2) - PWM(pin=22, freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3) - PWM(pin=23, freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3) - PWM(pin=25, freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0) - PWM(pin=26, freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0) - PWM(pin=27, freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1) - PWM(pin=14, freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1) - PWM(pin=12, freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2) - PWM(pin=13, freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2) - PWM(pin=32, freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3) - PWM(pin=33, freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3) + Output is:: + + PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0) + PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0) + PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1) + PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1) + PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2) + PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2) + PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3) + PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3) + PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0) + PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0) + PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1) + PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1) + PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2) + PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2) + PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3) + PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3) + +* Example of a smooth frequency change:: + + from time import sleep + from machine import Pin, PWM + + F_MIN = 500 + F_MAX = 1000 + + f = F_MIN + delta_f = 1 + + p = PWM(Pin(5), f) + print(p) + + while True: + p.freq(f) + + sleep(10 / F_MIN) + + f += delta_f + if f >= F_MAX or f <= F_MIN: + delta_f = -delta_f + + See PWM wave at Pin(5) with an oscilloscope. + +* Example of a smooth duty change:: + + from time import sleep + from machine import Pin, PWM + + DUTY_MAX = 2**16 - 1 + + duty_u16 = 0 + delta_d = 16 + + p = PWM(Pin(5), 1000, duty_u16=duty_u16) + print(p) + + while True: + p.duty_u16(duty_u16) + + sleep(1 / 1000) + + duty_u16 += delta_d + if duty_u16 >= DUTY_MAX: + duty_u16 = DUTY_MAX + delta_d = -delta_d + elif duty_u16 <= 0: + duty_u16 = 0 + delta_d = -delta_d + + See PWM wave at Pin(5) with an oscilloscope. + +Note: the Pin.OUT mode does not need to be specified. The channel is initialized +to PWM mode internally once for each Pin that is passed to the PWM constructor. + +The following code is wrong:: + + pwm = PWM(Pin(5, Pin.OUT), freq=1000, duty=512) # Pin(5) in PWM mode here + pwm = PWM(Pin(5, Pin.OUT), freq=500, duty=256) # Pin(5) in OUT mode here, PWM is off + +Use this code instead:: + + pwm = PWM(Pin(5), freq=1000, duty=512) + pwm.init(freq=500, duty=256) diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index 9e64723b27c74..ed2199737099a 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -57,13 +57,13 @@ The :mod:`network` module:: wlan.active(True) # activate the interface wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP - wlan.connect('essid', 'password') # connect to an AP + wlan.connect('ssid', 'key') # connect to an AP wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface ap.active(True) # activate the interface - ap.config(essid='ESP-AP') # set the ESSID of the access point + ap.config(ssid='ESP-AP') # set the SSID of the access point A useful function for connecting to your local WiFi network is:: @@ -73,7 +73,7 @@ A useful function for connecting to your local WiFi network is:: wlan.active(True) if not wlan.isconnected(): print('connecting to network...') - wlan.connect('essid', 'password') + wlan.connect('ssid', 'key') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig()) @@ -374,17 +374,13 @@ Use the ``neopixel`` module:: np.write() # write data to all pixels r, g, b = np[0] # get first pixel colour -For low-level driving of a NeoPixel:: - - import esp - esp.neopixel_write(pin, grb_buf, is800khz) - .. Warning:: By default ``NeoPixel`` is configured to control the more popular *800kHz* units. It is possible to use alternative timing to control other (typically 400kHz) devices by passing ``timing=0`` when constructing the ``NeoPixel`` object. +For low-level driving of a NeoPixel see `machine.bitstream`. APA102 driver ------------- diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst index a5deb3532f6b2..0d4bc42e2daba 100644 --- a/docs/esp8266/tutorial/intro.rst +++ b/docs/esp8266/tutorial/intro.rst @@ -18,12 +18,12 @@ The first thing you need is a board with an ESP8266 chip. The MicroPython software supports the ESP8266 chip itself and any board should work. The main characteristic of a board is how much flash it has, how the GPIO pins are connected to the outside world, and whether it includes a built-in USB-serial -convertor to make the UART available to your PC. +converter to make the UART available to your PC. The minimum requirement for flash size is 1Mbyte. There is also a special build for boards with 512KB, but it is highly limited comparing to the normal build: there is no support for filesystem, and thus features which -depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will +depend on it won't work (WebREPL, mip, etc.). As such, 512KB build will be more interesting for users who build from source and fine-tune parameters for their particular application. @@ -41,8 +41,8 @@ Please refer to the documentation for your board for further details. Getting the firmware -------------------- -The first thing you need to do is download the most recent MicroPython firmware -.bin file to load onto your ESP8266 device. You can download it from the +The first thing you need to do is download the most recent MicroPython firmware +.bin file to load onto your ESP8266 device. You can download it from the `MicroPython downloads page `_. From here, you have 3 main choices @@ -64,13 +64,13 @@ such, only daily builds for 512kb modules are provided. Deploying the firmware ---------------------- -Once you have the MicroPython firmware (compiled code), you need to load it onto +Once you have the MicroPython firmware (compiled code), you need to load it onto your ESP8266 device. There are two main steps to do this: first you need to put your device in boot-loader mode, and second you need to copy across the firmware. The exact procedure for these steps is highly dependent on the particular board and you will need to refer to its documentation for details. -If you have a board that has a USB connector, a USB-serial convertor, and has +If you have a board that has a USB connector, a USB-serial converter, and has the DTR and RTS pins wired in a special way then deploying the firmware should be easy as all steps can be done automatically. Boards that have such features include the Adafruit Feather HUZZAH and NodeMCU boards. @@ -128,7 +128,7 @@ Serial prompt Once you have the firmware on the device you can access the REPL (Python prompt) over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial -convertor, depending on your board. The baudrate is 115200. The next part of +converter, depending on your board. The baudrate is 115200. The next part of the tutorial will discuss the prompt in more detail. WiFi @@ -137,7 +137,7 @@ WiFi After a fresh install and boot the device configures itself as a WiFi access point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx where the x's are replaced with part of the MAC address of your device (so will -be the same everytime, and most likely different for all ESP8266 chips). The +be the same every time, and most likely different for all ESP8266 chips). The password for the WiFi is micropythoN (note the upper-case N). Its IP address will be 192.168.4.1 once you connect to its network. WiFi configuration will be discussed in more detail later in the tutorial. @@ -169,7 +169,7 @@ after it, here are troubleshooting recommendations: * The flashing instructions above use flashing speed of 460800 baud, which is good compromise between speed and stability. However, depending on your - module/board, USB-UART convertor, cables, host OS, etc., the above baud + module/board, USB-UART converter, cables, host OS, etc., the above baud rate may be too high and lead to errors. Try a more common 115200 baud rate instead in such cases. diff --git a/docs/esp8266/tutorial/network_basics.rst b/docs/esp8266/tutorial/network_basics.rst index 95d8cba4f9fe0..dc3cd3dd5e070 100644 --- a/docs/esp8266/tutorial/network_basics.rst +++ b/docs/esp8266/tutorial/network_basics.rst @@ -37,7 +37,7 @@ First activate the station interface:: Then connect to your WiFi network:: - >>> sta_if.connect('', '') + >>> sta_if.connect('', '') To check if the connection is established use:: @@ -61,7 +61,7 @@ connect to your WiFi network:: if not sta_if.isconnected(): print('connecting to network...') sta_if.active(True) - sta_if.connect('', '') + sta_if.connect('', '') while not sta_if.isconnected(): pass print('network config:', sta_if.ifconfig()) diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst index 196541bd02cb6..bc0142aaef5f9 100644 --- a/docs/esp8266/tutorial/repl.rst +++ b/docs/esp8266/tutorial/repl.rst @@ -13,7 +13,7 @@ REPL over the serial port The REPL is always available on the UART0 serial peripheral, which is connected to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200. -If your board has a USB-serial convertor on it then you should be able to access +If your board has a USB-serial converter on it then you should be able to access the REPL directly from your PC. Otherwise you will need to have a way of communicating with the UART. diff --git a/docs/esp8266/tutorial/ssd1306.rst b/docs/esp8266/tutorial/ssd1306.rst index 4dca82afc48f6..8651522e06e91 100644 --- a/docs/esp8266/tutorial/ssd1306.rst +++ b/docs/esp8266/tutorial/ssd1306.rst @@ -66,8 +66,8 @@ Subclassing FrameBuffer provides support for graphics primitives:: display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1 display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1 display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63 - display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 107,43, colour=1 - display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 107,43, colour=1 + display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 117,53, colour=1 + display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 117,53, colour=1 display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1 display.scroll(20, 0) # scroll 20 pixels to the right diff --git a/docs/index.rst b/docs/index.rst index a97bff1c8408b..64b83618da149 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,9 @@ MicroPython documentation and references esp8266/quickref.rst esp32/quickref.rst rp2/quickref.rst + mimxrt/quickref.rst wipy/quickref.rst unix/quickref.rst zephyr/quickref.rst + renesas-ra/quickref.rst + samd/quickref.rst diff --git a/docs/library/array.rst b/docs/library/array.rst index 88d6d2263ca6b..f417a7046e2ff 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -27,3 +27,55 @@ Classes Append new elements as contained in *iterable* to the end of array, growing it. + + .. method:: __getitem__(index) + + Indexed read of the array, called as ``a[index]`` (where ``a`` is an ``array``). + Returns a value if *index* is an ``int`` and an ``array`` if *index* is a slice. + Negative indices count from the end and ``IndexError`` is thrown if the index is + out of range. + + **Note:** ``__getitem__`` cannot be called directly (``a.__getitem__(index)`` fails) and + is not present in ``__dict__``, however ``a[index]`` does work. + + .. method:: __setitem__(index, value) + + Indexed write into the array, called as ``a[index] = value`` (where ``a`` is an ``array``). + ``value`` is a single value if *index* is an ``int`` and an ``array`` if *index* is a slice. + Negative indices count from the end and ``IndexError`` is thrown if the index is out of range. + + **Note:** ``__setitem__`` cannot be called directly (``a.__setitem__(index, value)`` fails) and + is not present in ``__dict__``, however ``a[index] = value`` does work. + + .. method:: __len__() + + Returns the number of items in the array, called as ``len(a)`` (where ``a`` is an ``array``). + + **Note:** ``__len__`` cannot be called directly (``a.__len__()`` fails) and the + method is not present in ``__dict__``, however ``len(a)`` does work. + + .. method:: __add__(other) + + Return a new ``array`` that is the concatenation of the array with *other*, called as + ``a + other`` (where ``a`` and *other* are both ``arrays``). + + **Note:** ``__add__`` cannot be called directly (``a.__add__(other)`` fails) and + is not present in ``__dict__``, however ``a + other`` does work. + + .. method:: __iadd__(other) + + Concatenates the array with *other* in-place, called as ``a += other`` (where ``a`` and *other* + are both ``arrays``). Equivalent to ``extend(other)``. + + **Note:** ``__iadd__`` cannot be called directly (``a.__iadd__(other)`` fails) and + is not present in ``__dict__``, however ``a += other`` does work. + + .. method:: __repr__() + + Returns the string representation of the array, called as ``str(a)`` or ``repr(a)``` + (where ``a`` is an ``array``). Returns the string ``"array(, [])"``, + where ```` is the type code letter for the array and ```` is a comma + separated list of the elements of the array. + + **Note:** ``__repr__`` cannot be called directly (``a.__repr__()`` fails) and + is not present in ``__dict__``, however ``str(a)`` and ``repr(a)`` both work. diff --git a/docs/library/asyncio.rst b/docs/library/asyncio.rst new file mode 100644 index 0000000000000..b57f1ee04eaec --- /dev/null +++ b/docs/library/asyncio.rst @@ -0,0 +1,364 @@ +:mod:`asyncio` --- asynchronous I/O scheduler +============================================= + +.. module:: asyncio + :synopsis: asynchronous I/O scheduler for writing concurrent code + +|see_cpython_module| +`asyncio `_ + +Example:: + + import asyncio + + async def blink(led, period_ms): + while True: + led.on() + await asyncio.sleep_ms(5) + led.off() + await asyncio.sleep_ms(period_ms) + + async def main(led1, led2): + asyncio.create_task(blink(led1, 700)) + asyncio.create_task(blink(led2, 400)) + await asyncio.sleep_ms(10_000) + + # Running on a pyboard + from pyb import LED + asyncio.run(main(LED(1), LED(2))) + + # Running on a generic board + from machine import Pin + asyncio.run(main(Pin(1), Pin(2))) + +Core functions +-------------- + +.. function:: create_task(coro) + + Create a new task from the given coroutine and schedule it to run. + + Returns the corresponding `Task` object. + +.. function:: current_task() + + Return the `Task` object associated with the currently running task. + +.. function:: run(coro) + + Create a new task from the given coroutine and run it until it completes. + + Returns the value returned by *coro*. + +.. function:: sleep(t) + + Sleep for *t* seconds (can be a float). + + This is a coroutine. + +.. function:: sleep_ms(t) + + Sleep for *t* milliseconds. + + This is a coroutine, and a MicroPython extension. + +Additional functions +-------------------- + +.. function:: wait_for(awaitable, timeout) + + Wait for the *awaitable* to complete, but cancel it if it takes longer + than *timeout* seconds. If *awaitable* is not a task then a task will be + created from it. + + If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: + this should be trapped by the caller. The task receives + ``asyncio.CancelledError`` which may be ignored or trapped using ``try...except`` + or ``try...finally`` to run cleanup code. + + Returns the return value of *awaitable*. + + This is a coroutine. + +.. function:: wait_for_ms(awaitable, timeout) + + Similar to `wait_for` but *timeout* is an integer in milliseconds. + + This is a coroutine, and a MicroPython extension. + +.. function:: gather(*awaitables, return_exceptions=False) + + Run all *awaitables* concurrently. Any *awaitables* that are not tasks are + promoted to tasks. + + Returns a list of return values of all *awaitables*. + + This is a coroutine. + +class Task +---------- + +.. class:: Task() + + This object wraps a coroutine into a running task. Tasks can be waited on + using ``await task``, which will wait for the task to complete and return + the return value of the task. + + Tasks should not be created directly, rather use `create_task` to create them. + +.. method:: Task.cancel() + + Cancel the task by injecting ``asyncio.CancelledError`` into it. The task may + ignore this exception. Cleanup code may be run by trapping it, or via + ``try ... finally``. + +class Event +----------- + +.. class:: Event() + + Create a new event which can be used to synchronise tasks. Events start + in the cleared state. + +.. method:: Event.is_set() + + Returns ``True`` if the event is set, ``False`` otherwise. + +.. method:: Event.set() + + Set the event. Any tasks waiting on the event will be scheduled to run. + + Note: This must be called from within a task. It is not safe to call this + from an IRQ, scheduler callback, or other thread. See `ThreadSafeFlag`. + +.. method:: Event.clear() + + Clear the event. + +.. method:: Event.wait() + + Wait for the event to be set. If the event is already set then it returns + immediately. + + This is a coroutine. + +class ThreadSafeFlag +-------------------- + +.. class:: ThreadSafeFlag() + + Create a new flag which can be used to synchronise a task with code running + outside the asyncio loop, such as other threads, IRQs, or scheduler + callbacks. Flags start in the cleared state. The class does not currently + work under the Unix build of MicroPython. + +.. method:: ThreadSafeFlag.set() + + Set the flag. If there is a task waiting on the flag, it will be scheduled + to run. + +.. method:: ThreadSafeFlag.clear() + + Clear the flag. This may be used to ensure that a possibly previously-set + flag is clear before waiting for it. + +.. method:: ThreadSafeFlag.wait() + + Wait for the flag to be set. If the flag is already set then it returns + immediately. The flag is automatically reset upon return from ``wait``. + + A flag may only be waited on by a single task at a time. + + This is a coroutine. + +class Lock +---------- + +.. class:: Lock() + + Create a new lock which can be used to coordinate tasks. Locks start in + the unlocked state. + + In addition to the methods below, locks can be used in an ``async with`` statement. + +.. method:: Lock.locked() + + Returns ``True`` if the lock is locked, otherwise ``False``. + +.. method:: Lock.acquire() + + Wait for the lock to be in the unlocked state and then lock it in an atomic + way. Only one task can acquire the lock at any one time. + + This is a coroutine. + +.. method:: Lock.release() + + Release the lock. If any tasks are waiting on the lock then the next one in the + queue is scheduled to run and the lock remains locked. Otherwise, no tasks are + waiting an the lock becomes unlocked. + +TCP stream connections +---------------------- + +.. 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 + the connection could not be made. + + This is a coroutine. + +.. 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. + +.. class:: Stream() + + This represents a TCP stream connection. To minimise code this class implements + both a reader and a writer, and both ``StreamReader`` and ``StreamWriter`` alias to + this class. + +.. method:: Stream.get_extra_info(v) + + Get extra information about the stream, given by *v*. The valid values for *v* are: + ``peername``. + +.. method:: Stream.close() + + Close the stream. + +.. method:: Stream.wait_closed() + + Wait for the stream to close. + + This is a coroutine. + +.. method:: Stream.read(n=-1) + + Read up to *n* bytes and return them. If *n* is not provided or -1 then read all + bytes until EOF. The returned value will be an empty bytes object if EOF is + encountered before any bytes are read. + + This is a coroutine. + +.. method:: Stream.readinto(buf) + + Read up to n bytes into *buf* with n being equal to the length of *buf*. + + Return the number of bytes read into *buf*. + + This is a coroutine, and a MicroPython extension. + +.. method:: Stream.readexactly(n) + + Read exactly *n* bytes and return them as a bytes object. + + Raises an ``EOFError`` exception if the stream ends before reading *n* bytes. + + This is a coroutine. + +.. method:: Stream.readline() + + Read a line and return it. + + This is a coroutine. + +.. method:: Stream.write(buf) + + Accumulated *buf* to the output buffer. The data is only flushed when + `Stream.drain` is called. It is recommended to call `Stream.drain` immediately + after calling this function. + +.. method:: Stream.drain() + + Drain (write) all buffered output data out to the stream. + + This is a coroutine. + +.. class:: Server() + + This represents the server class returned from `start_server`. It can be used + in an ``async with`` statement to close the server upon exit. + +.. method:: Server.close() + + Close the server. + +.. method:: Server.wait_closed() + + Wait for the server to close. + + This is a coroutine. + +Event Loop +---------- + +.. function:: get_event_loop() + + Return the event loop used to schedule and run tasks. See `Loop`. + +.. function:: new_event_loop() + + Reset the event loop and return it. + + Note: since MicroPython only has a single event loop this function just + resets the loop's state, it does not create a new one. + +.. class:: Loop() + + This represents the object which schedules and runs tasks. It cannot be + created, use `get_event_loop` instead. + +.. method:: Loop.create_task(coro) + + Create a task from the given *coro* and return the new `Task` object. + +.. method:: Loop.run_forever() + + Run the event loop until `stop()` is called. + +.. method:: Loop.run_until_complete(awaitable) + + Run the given *awaitable* until it completes. If *awaitable* is not a task + then it will be promoted to one. + +.. method:: Loop.stop() + + Stop the event loop. + +.. method:: Loop.close() + + Close the event loop. + +.. method:: Loop.set_exception_handler(handler) + + Set the exception handler to call when a Task raises an exception that is not + caught. The *handler* should accept two arguments: ``(loop, context)``. + +.. method:: Loop.get_exception_handler() + + Get the current exception handler. Returns the handler, or ``None`` if no + custom handler is set. + +.. method:: Loop.default_exception_handler(context) + + The default exception handler that is called. + +.. method:: Loop.call_exception_handler(context) + + Call the current exception handler. The argument *context* is passed through and + is a dictionary containing keys: ``'message'``, ``'exception'``, ``'future'``. diff --git a/docs/library/binascii.rst b/docs/library/binascii.rst index fc621a8abee24..6c02f019aaa58 100644 --- a/docs/library/binascii.rst +++ b/docs/library/binascii.rst @@ -31,8 +31,8 @@ Functions Conforms to `RFC 2045 s.6.8 `_. Returns a bytes object. -.. function:: b2a_base64(data) +.. function:: b2a_base64(data, *, newline=True) Encode binary data in base64 format, as in `RFC 3548 `_. Returns the encoded data - followed by a newline character, as a bytes object. + followed by a newline character if newline is true, as a bytes object. diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index cfec804eafbf7..fb3c23400e51d 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -13,6 +13,9 @@ concurrently. Pairing (and bonding) is supported on some ports. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. +.. note:: For most applications, we recommend using the higher-level + `aioble library `_. + .. note:: This module is still under development and its classes, functions, methods and constants are subject to change. @@ -41,7 +44,7 @@ Configuration Get or set configuration values of the BLE interface. To get a value the parameter name should be quoted as a string, and just one parameter is - queried at a time. To set values use the keyword syntax, and one ore more + queried at a time. To set values use the keyword syntax, and one or more parameter can be set at a time. Currently supported values are: @@ -163,7 +166,7 @@ Event Handling conn_handle, status = data elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: # Called for each characteristic found by gattc_discover_services(). - conn_handle, def_handle, value_handle, properties, uuid = data + conn_handle, end_handle, value_handle, properties, uuid = data elif event == _IRQ_GATTC_CHARACTERISTIC_DONE: # Called once service discovery is complete. # Note: Status will be zero on success, implementation-specific value otherwise. @@ -180,12 +183,10 @@ Event Handling conn_handle, value_handle, char_data = data elif event == _IRQ_GATTC_READ_DONE: # A gattc_read() has completed. - # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_WRITE_DONE: # A gattc_write() has completed. - # Note: The value_handle will be zero on btstack (but present on NimBLE). # Note: Status will be zero on success, implementation-specific value otherwise. conn_handle, value_handle, status = data elif event == _IRQ_GATTC_NOTIFY: @@ -311,7 +312,7 @@ Broadcaster Role (Advertiser) in all broadcasts, and *resp_data* is send in reply to an active scan. **Note:** if *adv_data* (or *resp_data*) is ``None``, then the data passed - to the previous call to ``gap_advertise`` will be re-used. This allows a + to the previous call to ``gap_advertise`` will be reused. This allows a broadcaster to resume advertising with just ``gap_advertise(interval_us)``. To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``. @@ -365,7 +366,12 @@ A central device can connect to peripherals that it has discovered using the obs See :meth:`gap_scan ` for details about address types. - On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. + To cancel an outstanding connection attempt early, call + ``gap_connect(None)``. + + On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. If + cancelling a connection attempt, the ``_IRQ_PERIPHERAL_DISCONNECT`` event + will be raised. The device will wait up to *scan_duration_ms* to receive an advertising payload from the device. @@ -506,19 +512,24 @@ writes from a client to a given characteristic, use Sends a notification request to a connected client. - If *data* is not ``None``, then that value is sent to the client as part of - the notification. The local value will not be modified. + If *data* is ``None`` (the default), then the current local value (as set + with :meth:`gatts_write `) will be sent. - Otherwise, if *data* is ``None``, then the current local value (as - set with :meth:`gatts_write `) will be sent. + Otherwise, if *data* is not ``None``, then that value is sent to the client + as part of the notification. The local value will not be modified. **Note:** The notification will be sent regardless of the subscription status of the client to this characteristic. -.. method:: BLE.gatts_indicate(conn_handle, value_handle, /) +.. method:: BLE.gatts_indicate(conn_handle, value_handle, data=None, /) + + Sends a indication request to a connected client. + + If *data* is ``None`` (the default), then the current local value (as set + with :meth:`gatts_write `) will be sent. - Sends an indication request containing the characteristic's current value to - a connected client. + Otherwise, if *data* is not ``None``, then that value is sent to the client + as part of the indication. The local value will not be modified. On acknowledgment (or failure, e.g. timeout), the ``_IRQ_GATTS_INDICATE_DONE`` event will be raised. diff --git a/docs/library/btree.rst b/docs/library/btree.rst index c093f970fabaa..9d1dcf1110dc7 100644 --- a/docs/library/btree.rst +++ b/docs/library/btree.rst @@ -11,8 +11,9 @@ value, a database also supports efficient ordered range scans (retrieval of values with the keys in a given range). On the application interface side, BTree database work as close a possible to a way standard `dict` type works, one notable difference is that both keys and values must -be `bytes` objects (so, if you want to store objects of other types, you -need to serialize them to `bytes` first). +be `bytes`-like objects (so, if you want to store objects of other types, you +need to first serialize them to `str` or `bytes` or another type that supports +the buffer protocol). The module is based on the well-known BerkelyDB library, version 1.xx. diff --git a/docs/library/collections.rst b/docs/library/collections.rst index 21f06fded71cd..6cf2c096ffc62 100644 --- a/docs/library/collections.rst +++ b/docs/library/collections.rst @@ -12,7 +12,7 @@ hold/accumulate various objects. Classes ------- -.. function:: deque(iterable, maxlen[, flags]) +.. class:: deque(iterable, maxlen[, flags]) Deques (double-ended queues) are a list-like container that support O(1) appends and pops from either side of the deque. New deques are created @@ -57,7 +57,7 @@ Classes print(t1.name) assert t2.name == t2[1] -.. function:: OrderedDict(...) +.. class:: OrderedDict(...) ``dict`` type subclass which remembers and preserves the order of keys added. When ordered dict is iterated over, keys/items are returned in diff --git a/docs/library/deflate.rst b/docs/library/deflate.rst new file mode 100644 index 0000000000000..fad577870518d --- /dev/null +++ b/docs/library/deflate.rst @@ -0,0 +1,182 @@ +:mod:`deflate` -- deflate compression & decompression +===================================================== + +.. module:: deflate + :synopsis: deflate compression & decompression + +This module allows compression and decompression of binary data with the +`DEFLATE algorithm `_ +(commonly used in the zlib library and gzip archiver). + +**Availability:** + +* Added in MicroPython v1.21. + +* Decompression: Enabled via the ``MICROPY_PY_DEFLATE`` build option, on by default + on ports with the "extra features" level or higher (which is most boards). + +* Compression: Enabled via the ``MICROPY_PY_DEFLATE_COMPRESS`` build option, on + by default on ports with the "full features" level or higher (generally this means + you need to build your own firmware to enable this). + +Classes +------- + +.. class:: DeflateIO(stream, format=AUTO, wbits=0, close=False, /) + + This class can be used to wrap a *stream* which is any + :term:`stream-like ` object such as a file, socket, or stream + (including :class:`io.BytesIO`). It is itself a stream and implements the + standard read/readinto/write/close methods. + + The *stream* must be a blocking stream. Non-blocking streams are currently + not supported. + + The *format* can be set to any of the constants defined below, and defaults + to ``AUTO`` which for decompressing will auto-detect gzip or zlib streams, + and for compressing it will generate a raw stream. + + The *wbits* parameter sets the base-2 logarithm of the DEFLATE dictionary + window size. So for example, setting *wbits* to ``10`` sets the window size + to 1024 bytes. Valid values are ``5`` to ``15`` inclusive (corresponding to + window sizes of 32 to 32k bytes). + + If *wbits* is set to ``0`` (the default), then for compression a window size + of 256 bytes will be used (as if *wbits* was set to 8). For decompression, it + depends on the format: + + * ``RAW`` will use 256 bytes (corresponding to *wbits* set to 8). + * ``ZLIB`` (or ``AUTO`` with zlib detected) will use the value from the zlib + header. + * ``GZIP`` (or ``AUTO`` with gzip detected) will use 32 kilobytes + (corresponding to *wbits* set to 15). + + See the :ref:`window size ` notes below for more information + about the window size, zlib, and gzip streams. + + If *close* is set to ``True`` then the underlying stream will be closed + automatically when the :class:`deflate.DeflateIO` stream is closed. This is + useful if you want to return a :class:`deflate.DeflateIO` stream that wraps + another stream and not have the caller need to know about managing the + underlying stream. + + If compression is enabled, a given :class:`deflate.DeflateIO` instance + supports both reading and writing. For example, a bidirectional stream like + a socket can be wrapped, which allows for compression/decompression in both + directions. + +Constants +--------- + +.. data:: deflate.AUTO + deflate.RAW + deflate.ZLIB + deflate.GZIP + + Supported values for the *format* parameter. + +Examples +-------- + +A typical use case for :class:`deflate.DeflateIO` is to read or write a compressed +file from storage: + +.. code:: python + + import deflate + + # Writing a zlib-compressed stream (uses the default window size of 256 bytes). + with open("data.gz", "wb") as f: + with deflate.DeflateIO(f, deflate.ZLIB) as d: + # Use d.write(...) etc + + # Reading a zlib-compressed stream (auto-detect window size). + with open("data.z", "rb") as f: + with deflate.DeflateIO(f, deflate.ZLIB) as d: + # Use d.read(), d.readinto(), etc. + +Because :class:`deflate.DeflateIO` is a stream, it can be used for example +with :meth:`json.dump` and :meth:`json.load` (and any other places streams can +be used): + +.. code:: python + + import deflate, json + + # Write a dictionary as JSON in gzip format, with a + # small (64 byte) window size. + config = { ... } + with open("config.gz", "wb") as f: + with deflate.DeflateIO(f, deflate.GZIP, 6) as f: + json.dump(config, f) + + # Read back that dictionary. + with open("config.gz", "rb") as f: + with deflate.DeflateIO(f, deflate.GZIP, 6) as f: + config = json.load(f) + +If your source data is not in a stream format, you can use :class:`io.BytesIO` +to turn it into a stream suitable for use with :class:`deflate.DeflateIO`: + +.. code:: python + + import deflate, io + + # Decompress a bytes/bytearray value. + compressed_data = get_data_z() + with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d: + decompressed_data = d.read() + + # Compress a bytes/bytearray value. + uncompressed_data = get_data() + stream = io.BytesIO() + with deflate.DeflateIO(stream, deflate.ZLIB) as d: + d.write(uncompressed_data) + compressed_data = stream.getvalue() + +.. _deflate_wbits: + +Deflate window size +------------------- + +The window size limits how far back in the stream the (de)compressor can +reference. Increasing the window size will improve compression, but will require +more memory and make the compressor slower. + +If an input stream was compressed a given window size, then `DeflateIO` +using a smaller window size will fail mid-way during decompression with +:exc:`OSError`, but only if a back-reference actually refers back further +than the decompressor's window size. This means it may be possible to decompress +with a smaller window size. For example, this would trivially be the case if the +original uncompressed data is shorter than the window size. + +Decompression +~~~~~~~~~~~~~ + +The zlib format includes a header which specifies the window size that was used +to compress the data. This indicates the maximum window size required to +decompress this stream. If this header value is less than the specified *wbits* +value (or if *wbits* is unset), then the header value will be used. + +The gzip format does not include the window size in the header, and assumes that +all gzip compressors (e.g. the ``gzip`` utility, or CPython's implementation of +:class:`gzip.GzipFile`) use the maximum window size of 32kiB. For this reason, +if the *wbits* parameter is not set, the decompressor will use a 32 kiB window +size (corresponding to *wbits* set to 15). This means that to be able to +decompress an arbitrary gzip stream, you must have at least this much RAM +available. If you control the source data, consider instead using the zlib +format with a smaller window size. + +The raw format has no header and therefore does not include any information +about the window size. If *wbits* is not set, then it will default to a window +size of 256 bytes, which may not be large enough for a given stream. Therefore +it is recommended that you should always explicitly set *wbits* if using the raw +format. + +Compression +~~~~~~~~~~~ + +For compression, MicroPython will default to a window size of 256 bytes for all +formats. This provides a reasonable amount of compression with minimal memory +usage and fast compression time, and will generate output that will work with +any decompressor. diff --git a/docs/library/esp.rst b/docs/library/esp.rst index b9ae57bd9757f..9c20b5e8b2d89 100644 --- a/docs/library/esp.rst +++ b/docs/library/esp.rst @@ -4,7 +4,7 @@ .. module:: esp :synopsis: functions related to the ESP8266 and ESP32 -The ``esp`` module contains specific functions related to both the ESP8266 and +The ``esp`` module contains specific functions related to both the ESP8266 and ESP32 modules. Some functions are only available on one or the other of these ports. @@ -62,6 +62,53 @@ Functions .. function:: flash_erase(sector_no) +.. function:: osdebug(uart_no) + + .. note:: This is the ESP8266 form of this function. + + 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 + * ``LOG_WARN`` -- Error conditions from which recovery measures have been taken + * ``LOG_INFO`` -- Information messages which describe normal flow of events + * ``LOG_DEBUG`` -- Extra information which is not necessary for normal use (values, pointers, sizes, etc) + * ``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 diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index e3c25d2653db1..dc35e7905e162 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -18,6 +18,11 @@ Functions Configure whether or not a touch will wake the device from sleep. *wake* should be a boolean value. +.. function:: wake_on_ulp(wake) + + Configure whether or not the Ultra-Low-Power co-processor can wake the + device from sleep. *wake* should be a boolean value. + .. function:: wake_on_ext0(pin, level) Configure how EXT0 wakes the device from sleep. *pin* can be ``None`` @@ -30,13 +35,14 @@ Functions or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW`` or ``esp32.WAKEUP_ANY_HIGH``. -.. function:: raw_temperature() +.. function:: gpio_deep_sleep_hold(enable) - Read the raw value of the internal temperature sensor, returning an integer. + Configure whether non-RTC GPIO pin configuration is retained during + deep-sleep mode for held pads. *enable* should be a boolean value. -.. function:: hall_sensor() +.. function:: raw_temperature() - Read the raw value of the internal Hall sensor, returning an integer. + Read the raw value of the internal temperature sensor, returning an integer. .. function:: idf_heap_info(capabilities) @@ -45,8 +51,6 @@ Functions buffers and other data. This data is useful to get a sense of how much memory is available to ESP-IDF and the networking stack in particular. It may shed some light on situations where ESP-IDF operations fail due to allocation failures. - The information returned is *not* useful to troubleshoot Python allocation failures, - use `micropython.mem_info()` instead. The capabilities parameter corresponds to ESP-IDF's ``MALLOC_CAP_XXX`` values but the two most useful ones are predefined as `esp32.HEAP_DATA` for data heap regions and @@ -62,23 +66,42 @@ Functions [(240, 0, 0, 0), (7288, 0, 0, 0), (16648, 4, 4, 4), (79912, 35712, 35512, 35108), (15072, 15036, 15036, 15036), (113840, 0, 0, 0)] + .. note:: Free IDF heap memory in the `esp32.HEAP_DATA` region is available + to be automatically added to the MicroPython heap to prevent a + MicroPython allocation from failing. However, the information returned + here is otherwise *not* useful to troubleshoot Python allocation + failures. :func:`micropython.mem_info()` and :func:`gc.mem_free()` should + be used instead: + + The "max new split" value in :func:`micropython.mem_info()` output + corresponds to the largest free block of ESP-IDF heap that could be + automatically added on demand to the MicroPython heap. + + The result of :func:`gc.mem_free()` is the total of the current "free" + and "max new split" values printed by :func:`micropython.mem_info()`. + + Flash partitions ---------------- This class gives access to the partitions in the device's flash memory and includes methods to enable over-the-air (OTA) updates. -.. class:: Partition(id) +.. class:: Partition(id, block_size=4096, /) Create an object representing a partition. *id* can be a string which is the label of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``. + *block_size* specifies the byte size of an individual block. -.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None) +.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None, block_size=4096) Find a partition specified by *type*, *subtype* and *label*. Returns a (possibly empty) list of Partition objects. Note: ``subtype=0xff`` matches any subtype and ``label=None`` matches any label. + *block_size* specifies the byte size of an individual block used by the returned + objects. + .. method:: Partition.info() Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``. @@ -91,12 +114,17 @@ methods to enable over-the-air (OTA) updates. These methods implement the simple and :ref:`extended ` block protocol defined by - :class:`os.AbstractBlockDev`. + :class:`vfs.AbstractBlockDev`. .. method:: Partition.set_boot() Sets the partition as the boot partition. + .. note:: Do not enter :func:`deepsleep` after changing + the OTA boot partition, without first performing a hard + :func:`reset` or power cycle. This ensures the bootloader + will validate the new image before booting. + .. method:: Partition.get_next_update() Gets the next update partition after this one, and returns a new Partition object. @@ -112,7 +140,7 @@ methods to enable over-the-air (OTA) updates. and an ``OSError(-261)`` is raised if called on firmware that doesn't have the feature enabled. It is OK to call ``mark_app_valid_cancel_rollback`` on every boot and it is not - necessary when booting firmare that was loaded using esptool. + necessary when booting firmware that was loaded using esptool. Constants ~~~~~~~~~ @@ -165,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 @@ -198,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. @@ -236,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. @@ -250,10 +278,36 @@ For more details see Espressif's `ESP-IDF RMT documentation. new sequence of pulses. Looping sequences longer than 126 pulses is not supported by the hardware. +.. staticmethod:: RMT.bitstream_channel([value]) + + Select which RMT channel is used by the `machine.bitstream` implementation. + *value* can be ``None`` or a valid RMT channel number. The default RMT + channel is the highest numbered one. + + Passing in ``None`` disables the use of RMT and instead selects a bit-banging + implementation for `machine.bitstream`. + + 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 ---------------------------- +This class gives access to the Ultra Low Power (ULP) co-processor on the ESP32, +ESP32-S2 and ESP32-S3 chips. + +.. warning:: + + This class does not provide access to the RISCV ULP co-processor available + on the ESP32-S2 and ESP32-S3 chips. + .. class:: ULP() This class provides access to the Ultra-Low-Power co-processor. diff --git a/docs/library/espnow.rst b/docs/library/espnow.rst new file mode 100644 index 0000000000000..f0b592dffc8ab --- /dev/null +++ b/docs/library/espnow.rst @@ -0,0 +1,936 @@ +:mod:`espnow` --- support for the ESP-NOW wireless protocol +=========================================================== + +.. module:: espnow + :synopsis: ESP-NOW wireless protocol support + +This module provides an interface to the `ESP-NOW `_ protocol provided by Espressif on +ESP32 and ESP8266 devices (`API docs `_). + +Table of Contents: +------------------ + + - `Introduction`_ + - `Configuration`_ + - `Sending and Receiving Data`_ + - `Peer Management`_ + - `Callback Methods`_ + - `Exceptions`_ + - `Constants`_ + - `Wifi Signal Strength (RSSI) - (ESP32 Only)`_ + - `Supporting asyncio`_ + - `Broadcast and Multicast`_ + - `ESPNow and Wifi Operation`_ + - `ESPNow and Sleep Modes`_ + +Introduction +------------ + +ESP-NOW is a connection-less wireless communication protocol supporting: + +- Direct communication between up to 20 registered peers: + + - Without the need for a wireless access point (AP), + +- Encrypted and unencrypted communication (up to 6 encrypted peers), + +- Message sizes up to 250 bytes, + +- Can operate alongside Wifi operation (:doc:`network.WLAN`) on + ESP32 and ESP8266 devices. + +It is especially useful for small IoT networks, latency sensitive or power +sensitive applications (such as battery operated devices) and for long-range +communication between devices (hundreds of metres). + +This module also supports tracking the Wifi signal strength (RSSI) of peer +devices. + +A simple example would be: + +**Sender:** :: + + import network + import espnow + + # A WLAN interface must be active to send()/recv() + sta = network.WLAN(network.STA_IF) # Or network.AP_IF + sta.active(True) + sta.disconnect() # For ESP8266 + + e = espnow.ESPNow() + e.active(True) + peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' # MAC address of peer's wifi interface + e.add_peer(peer) # Must add_peer() before send() + + e.send(peer, "Starting...") + for i in range(100): + e.send(peer, str(i)*20, True) + e.send(peer, b'end') + +**Receiver:** :: + + import network + import espnow + + # A WLAN interface must be active to send()/recv() + sta = network.WLAN(network.STA_IF) + sta.active(True) + sta.disconnect() # Because ESP8266 auto-connects to last Access Point + + e = espnow.ESPNow() + e.active(True) + + while True: + host, msg = e.recv() + if msg: # msg == None if timeout in recv() + print(host, msg) + if msg == b'end': + break + +class ESPNow +------------ + +Constructor +----------- + +.. class:: ESPNow() + + Returns the singleton ESPNow object. As this is a singleton, all calls to + `espnow.ESPNow()` return a reference to the same object. + + .. note:: + Some methods are available only on the ESP32 due to code size + restrictions on the ESP8266 and differences in the Espressif API. + +Configuration +------------- + +.. method:: ESPNow.active([flag]) + + Initialise or de-initialise the ESP-NOW communication protocol depending on + the value of the ``flag`` optional argument. + + .. data:: Arguments: + + - *flag*: Any python value which can be converted to a boolean type. + + - ``True``: Prepare the software and hardware for use of the ESP-NOW + communication protocol, including: + + - initialise the ESPNow data structures, + - allocate the recv data buffer, + - invoke esp_now_init() and + - register the send and recv callbacks. + + - ``False``: De-initialise the Espressif ESP-NOW software stack + (esp_now_deinit()), disable callbacks, deallocate the recv + data buffer and deregister all peers. + + If *flag* is not provided, return the current status of the ESPNow + interface. + + .. data:: Returns: + + ``True`` if interface is currently *active*, else ``False``. + +.. method:: ESPNow.config(param=value, ...) + ESPNow.config('param') (ESP32 only) + + Set or get configuration values of the ESPNow interface. To set values, use + the keyword syntax, and one or more parameters can be set at a time. To get + a value the parameter name should be quoted as a string, and just one + parameter is queried at a time. + + **Note:** *Getting* parameters is not supported on the ESP8266. + + .. data:: Options: + + *rxbuf*: (default=526) Get/set the size in bytes of the internal + buffer used to store incoming ESPNow packet data. The default size is + selected to fit two max-sized ESPNow packets (250 bytes) with associated + mac_address (6 bytes), a message byte count (1 byte) and RSSI data plus + buffer overhead. Increase this if you expect to receive a lot of large + packets or expect bursty incoming traffic. + + **Note:** The recv buffer is allocated by `ESPNow.active()`. Changing + this value will have no effect until the next call of + `ESPNow.active(True)`. + + *timeout_ms*: (default=300,000) Default timeout (in milliseconds) + for receiving ESPNow messages. If *timeout_ms* is less than zero, then + wait forever. The timeout can also be provided as arg to + `recv()`/`irecv()`/`recvinto()`. + + *rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for + ESPNow packets. Must be set to a number from the allowed numeric values + in `enum wifi_phy_rate_t + `_. + + .. data:: Returns: + + ``None`` or the value of the parameter being queried. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``ValueError()`` on invalid configuration options or values. + +Sending and Receiving Data +-------------------------- + +A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be +`active()` before messages can be sent or received, +but it is not necessary to connect or configure the WLAN interface. +For example:: + + import network + + sta = network.WLAN(network.STA_IF) + sta.active(True) + sta.disconnect() # For ESP8266 + +**Note:** The ESP8266 has a *feature* that causes it to automatically reconnect +to the last wifi Access Point when set `active(True)` (even +after reboot/reset). This reduces the reliability of receiving ESP-NOW messages +(see `ESPNow and Wifi Operation`_). You can avoid this by calling +`disconnect()` after +`active(True)`. + +.. method:: ESPNow.send(mac, msg[, sync]) + ESPNow.send(msg) (ESP32 only) + + Send the data contained in ``msg`` to the peer with given network ``mac`` + address. In the second form, ``mac=None`` and ``sync=True``. The peer must + be registered with `ESPNow.add_peer()` before the + message can be sent. + + .. data:: Arguments: + + - *mac*: byte string exactly ``espnow.ADDR_LEN`` (6 bytes) long or + ``None``. If *mac* is ``None`` (ESP32 only) the message will be sent + to all registered peers, except any broadcast or multicast MAC + addresses. + + - *msg*: string or byte-string up to ``espnow.MAX_DATA_LEN`` (250) + bytes long. + + - *sync*: + + - ``True``: (default) send ``msg`` to the peer(s) and wait for a + response (or not). + + - ``False`` send ``msg`` and return immediately. Responses from the + peers will be discarded. + + .. data:: Returns: + + ``True`` if ``sync=False`` or if ``sync=True`` and *all* peers respond, + else ``False``. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if peer is not registered. + - ``OSError(num, "ESP_ERR_ESPNOW_IF")`` the wifi interface is not + `active()`. + - ``OSError(num, "ESP_ERR_ESPNOW_NO_MEM")`` internal ESP-NOW buffers are + full. + - ``ValueError()`` on invalid values for the parameters. + + **Note**: A peer will respond with success if its wifi interface is + `active()` and set to the same channel as the sender, + regardless of whether it has initialised it's ESP-NOW system or is + actively listening for ESP-NOW traffic (see the Espressif ESP-NOW docs). + +.. method:: ESPNow.recv([timeout_ms]) + + Wait for an incoming message and return the ``mac`` address of the peer and + the message. **Note**: It is **not** necessary to register a peer (using + `add_peer()`) to receive a message from that peer. + + .. data:: Arguments: + + - *timeout_ms*: (Optional): May have the following values. + + - ``0``: No timeout. Return immediately if no data is available; + - ``> 0``: Specify a timeout value in milliseconds; + - ``< 0``: Do not timeout, ie. wait forever for new messages; or + - ``None`` (or not provided): Use the default timeout value set with + `ESPNow.config()`. + + .. data:: Returns: + + - ``(None, None)`` if timeout is reached before a message is received, or + + - ``[mac, msg]``: where: + + - ``mac`` is a bytestring containing the address of the device which + sent the message, and + - ``msg`` is a bytestring containing the message. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_IF")`` if the wifi interface is not + `active()`. + - ``ValueError()`` on invalid *timeout_ms* values. + + `ESPNow.recv()` will allocate new storage for the returned list and the + ``peer`` and ``msg`` bytestrings. This can lead to memory fragmentation if + the data rate is high. See `ESPNow.irecv()` for a memory-friendly + alternative. + + +.. method:: ESPNow.irecv([timeout_ms]) + + Works like `ESPNow.recv()` but will reuse internal bytearrays to store the + return values: ``[mac, msg]``, so that no new memory is allocated on each + call. + + .. data:: Arguments: + + *timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`). + + .. data:: Returns: + + - As for `ESPNow.recv()`, except that ``msg`` is a bytearray, instead of + a bytestring. On the ESP8266, ``mac`` will also be a bytearray. + + .. data:: Raises: + + - See `ESPNow.recv()`. + + **Note:** You may also read messages by iterating over the ESPNow object, + which will use the `irecv()` method for alloc-free reads, eg: :: + + import espnow + e = espnow.ESPNow(); e.active(True) + for mac, msg in e: + print(mac, msg) + if mac is None: # mac, msg will equal (None, None) on timeout + break + +.. method:: ESPNow.recvinto(data[, timeout_ms]) + + Wait for an incoming message and return the length of the message in bytes. + This is the low-level method used by both `recv()` and + `irecv()` to read messages. + + .. data:: Arguments: + + *data*: A list of at least two elements, ``[peer, msg]``. ``msg`` must + be a bytearray large enough to hold the message (250 bytes). On the + ESP8266, ``peer`` should be a bytearray of 6 bytes. The MAC address of + the sender and the message will be stored in these bytearrays (see Note + on ESP32 below). + + *timeout_ms*: (Optional) Timeout in milliseconds (see `ESPNow.recv()`). + + .. data:: Returns: + + - Length of message in bytes or 0 if *timeout_ms* is reached before a + message is received. + + .. data:: Raises: + + - See `ESPNow.recv()`. + + **Note:** On the ESP32: + + - It is unnecessary to provide a bytearray in the first element of the + ``data`` list because it will be replaced by a reference to a unique + ``peer`` address in the **peer device table** (see `ESPNow.peers_table`). + - If the list is at least 4 elements long, the rssi and timestamp values + will be saved as the 3rd and 4th elements. + +.. method:: ESPNow.any() + + Check if data is available to be read with `ESPNow.recv()`. + + For more sophisticated querying of available characters use `select.poll()`:: + + import select + import espnow + + e = espnow.ESPNow() + poll = select.poll() + poll.register(e, select.POLLIN) + poll.poll(timeout) + + .. data:: Returns: + + ``True`` if data is available to be read, else ``False``. + +.. method:: ESPNow.stats() (ESP32 only) + + .. data:: Returns: + + A 5-tuple containing the number of packets sent/received/lost: + + ``(tx_pkts, tx_responses, tx_failures, rx_packets, rx_dropped_packets)`` + + Incoming packets are *dropped* when the recv buffers are full. To reduce + packet loss, increase the ``rxbuf`` config parameters and ensure you are + reading messages as quickly as possible. + + **Note**: Dropped packets will still be acknowledged to the sender as + received. + +Peer Management +--------------- + +On ESP32 devices, the Espressif ESP-NOW software requires that other devices +(peers) must be *registered* using `add_peer()` before we can +`send()` them messages (this is *not* enforced on ESP8266 +devices). It is **not** necessary to register a peer to receive an +un-encrypted message from that peer. + +**Encrypted messages**: To receive an *encrypted* message, the receiving device +must first register the sender and use the same encryption keys as the sender +(PMK and LMK) (see `set_pmk()` and `add_peer()`. + +.. method:: ESPNow.set_pmk(pmk) + + Set the Primary Master Key (PMK) which is used to encrypt the Local Master + Keys (LMK) for encrypting messages. If this is not set, a default PMK is + used by the underlying Espressif ESP-NOW software stack. + + **Note:** messages will only be encrypted if *lmk* is also set in + `ESPNow.add_peer()` (see `Security + `_ in the Espressif API + docs). + + .. data:: Arguments: + + *pmk*: Must be a byte string, bytearray or string of length + `espnow.KEY_LEN` (16 bytes). + + .. data:: Returns: + + ``None`` + + .. data:: Raises: + + ``ValueError()`` on invalid *pmk* values. + +.. method:: ESPNow.add_peer(mac, [lmk], [channel], [ifidx], [encrypt]) + ESPNow.add_peer(mac, param=value, ...) (ESP32 only) + + Add/register the provided *mac* address as a peer. Additional parameters may + also be specified as positional or keyword arguments (any parameter set to + ``None`` will be set to it's default value): + + .. data:: Arguments: + + - *mac*: The MAC address of the peer (as a 6-byte byte-string). + + - *lmk*: The Local Master Key (LMK) key used to encrypt data + transfers with this peer (unless the *encrypt* parameter is set to + ``False``). Must be: + + - a byte-string or bytearray or string of length ``espnow.KEY_LEN`` + (16 bytes), or + + - any non ``True`` python value (default= ``b''``), signifying an + *empty* key which will disable encryption. + + - *channel*: The wifi channel (2.4GHz) to communicate with this peer. + Must be an integer from 0 to 14. If channel is set to 0 the current + channel of the wifi device will be used. (default=0) + + - *ifidx*: (ESP32 only) Index of the wifi interface which will be + used to send data to this peer. Must be an integer set to + ``network.STA_IF`` (=0) or ``network.AP_IF`` (=1). + (default=0/``network.STA_IF``). See `ESPNow and Wifi Operation`_ + below for more information. + + - *encrypt*: (ESP32 only) If set to ``True`` data exchanged with + this peer will be encrypted with the PMK and LMK. (default = + ``True`` if *lmk* is set to a valid key, else ``False``) + + **ESP8266**: Keyword args may not be used on the ESP8266. + + **Note:** The maximum number of peers which may be registered is 20 + (`espnow.MAX_TOTAL_PEER_NUM`), with a maximum of 6 + (`espnow.MAX_ENCRYPT_PEER_NUM`) of those peers with encryption enabled + (see `ESP_NOW_MAX_ENCRYPT_PEER_NUM `_ in the Espressif API + docs). + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_EXIST")`` if *mac* is already + registered. + - ``OSError(num, "ESP_ERR_ESPNOW_FULL")`` if too many peers are + already registered. + - ``ValueError()`` on invalid keyword args or values. + +.. method:: ESPNow.del_peer(mac) + + Deregister the peer associated with the provided *mac* address. + + .. data:: Returns: + + ``None`` + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not + registered. + - ``ValueError()`` on invalid *mac* values. + +.. method:: ESPNow.get_peer(mac) (ESP32 only) + + Return information on a registered peer. + + .. data:: Returns: + + ``(mac, lmk, channel, ifidx, encrypt)``: a tuple of the "peer + info" associated with the given *mac* address. + + .. data:: Raises: + + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_INIT")`` if not initialised. + - ``OSError(num, "ESP_ERR_ESPNOW_NOT_FOUND")`` if *mac* is not + registered. + - ``ValueError()`` on invalid *mac* values. + +.. method:: ESPNow.peer_count() (ESP32 only) + + Return the number of registered peers: + + - ``(peer_num, encrypt_num)``: where + + - ``peer_num`` is the number of peers which are registered, and + - ``encrypt_num`` is the number of encrypted peers. + +.. method:: ESPNow.get_peers() (ESP32 only) + + Return the "peer info" parameters for all the registered peers (as a tuple + of tuples). + +.. method:: ESPNow.mod_peer(mac, lmk, [channel], [ifidx], [encrypt]) (ESP32 only) + ESPNow.mod_peer(mac, 'param'=value, ...) (ESP32 only) + + Modify the parameters of the peer associated with the provided *mac* + address. Parameters may be provided as positional or keyword arguments + (see `ESPNow.add_peer()`). Any parameter that is not set (or set to + ``None``) will retain the existing value for that parameter. + +Callback Methods +---------------- + +.. method:: ESPNow.irq(callback) (ESP32 only) + + Set a callback function to be called *as soon as possible* after a message has + been received from another ESPNow device. The callback function will be called + with the `ESPNow` instance object as an argument. For more reliable operation, + it is recommended to read out as many messages as are available when the + callback is invoked and to set the read timeout to zero, eg: :: + + def recv_cb(e): + while True: # Read out all messages waiting in the buffer + mac, msg = e.irecv(0) # Don't wait if no messages left + if mac is None: + return + print(mac, msg) + e.irq(recv_cb) + + The `irq()` callback method is an alternative method for + processing incoming messages, especially if the data rate is moderate + and the device is *not too busy* but there are some caveats: + + - The scheduler stack *can* overflow and callbacks will be missed if + packets are arriving at a sufficient rate or if other MicroPython components + (eg, bluetooth, machine.Pin.irq(), machine.timer, i2s, ...) are exercising + the scheduler stack. This method may be less reliable for dealing with + bursts of messages, or high throughput or on a device which is busy dealing + with other hardware operations. + + - For more information on *scheduled* function callbacks see: + `micropython.schedule()`. + +Constants +--------- + +.. data:: espnow.MAX_DATA_LEN(=250) + espnow.KEY_LEN(=16) + espnow.ADDR_LEN(=6) + espnow.MAX_TOTAL_PEER_NUM(=20) + espnow.MAX_ENCRYPT_PEER_NUM(=6) + +Exceptions +---------- + +If the underlying Espressif ESP-NOW software stack returns an error code, +the MicroPython espnow module will raise an ``OSError(errnum, errstring)`` +exception where ``errstring`` is set to the name of one of the error codes +identified in the +`Espressif ESP-NOW docs +`_. For example:: + + try: + e.send(peer, 'Hello') + except OSError as err: + if len(err.args) < 2: + raise err + if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT': + e.active(True) + elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + e.add_peer(peer) + elif err.args[1] == 'ESP_ERR_ESPNOW_IF': + network.WLAN(network.STA_IF).active(True) + else: + raise err + +Wifi Signal Strength (RSSI) - (ESP32 only) +------------------------------------------ + +The ESPNow object maintains a **peer device table** which contains the signal +strength and timestamp of the last received message from all hosts. The **peer +device table** can be accessed using `ESPNow.peers_table` and can be used to +track device proximity and identify *nearest neighbours* in a network of peer +devices. This feature is **not** available on ESP8266 devices. + +.. data:: ESPNow.peers_table + + A reference to the **peer device table**: a dict of known peer devices + and rssi values:: + + {peer: [rssi, time_ms], ...} + + where: + + - ``peer`` is the peer MAC address (as `bytes`); + - ``rssi`` is the wifi signal strength in dBm (-127 to 0) of the last + message received from the peer; and + - ``time_ms`` is the time the message was received (in milliseconds since + system boot - wraps every 12 days). + + Example:: + + >>> e.peers_table + {b'\xaa\xaa\xaa\xaa\xaa\xaa': [-31, 18372], + b'\xbb\xbb\xbb\xbb\xbb\xbb': [-43, 12541]} + + **Note**: the ``mac`` addresses returned by `recv()` are references to + the ``peer`` key values in the **peer device table**. + + **Note**: RSSI and timestamp values in the device table are updated only + when the message is read by the application. + +Supporting asyncio +------------------ + +A supplementary module (`aioespnow`) is available to provide +:doc:`asyncio` support. + +**Note:** Asyncio support is available on all ESP32 targets as well as those +ESP8266 boards which include the asyncio module (ie. ESP8266 devices with at +least 2MB flash memory). + +A small async server example:: + + import network + import aioespnow + import asyncio + + # A WLAN interface must be active to send()/recv() + network.WLAN(network.STA_IF).active(True) + + e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support + e.active(True) + peer = b'\xbb\xbb\xbb\xbb\xbb\xbb' + e.add_peer(peer) + + # Send a periodic ping to a peer + async def heartbeat(e, peer, period=30): + while True: + if not await e.asend(peer, b'ping'): + print("Heartbeat: peer not responding:", peer) + else: + print("Heartbeat: ping", peer) + await asyncio.sleep(period) + + # Echo any received messages back to the sender + async def echo_server(e): + async for mac, msg in e: + print("Echo:", msg) + try: + await e.asend(mac, msg) + except OSError as err: + if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + e.add_peer(mac) + await e.asend(mac, msg) + + async def main(e, peer, timeout, period): + asyncio.create_task(heartbeat(e, peer, period)) + asyncio.create_task(echo_server(e)) + await asyncio.sleep(timeout) + + asyncio.run(main(e, peer, 120, 10)) + +.. module:: aioespnow + :synopsis: ESP-NOW :doc:`asyncio` support + +.. class:: AIOESPNow() + + The `AIOESPNow` class inherits all the methods of `ESPNow` + and extends the interface with the following async methods. + +.. method:: async AIOESPNow.arecv() + + Asyncio support for `ESPNow.recv()`. Note that this method does not take a + timeout value as argument. + +.. method:: async AIOESPNow.airecv() + + Asyncio support for `ESPNow.irecv()`. Note that this method does not take a + timeout value as argument. + +.. method:: async AIOESPNow.asend(mac, msg, sync=True) + async AIOESPNow.asend(msg) + + Asyncio support for `ESPNow.send()`. + +.. method:: AIOESPNow._aiter__() / async AIOESPNow.__anext__() + + `AIOESPNow` also supports reading incoming messages by asynchronous + iteration using ``async for``; eg:: + + e = AIOESPNow() + e.active(True) + async def recv_till_halt(e): + async for mac, msg in e: + print(mac, msg) + if msg == b'halt': + break + asyncio.run(recv_till_halt(e)) + +Broadcast and Multicast +----------------------- + +All active ESPNow clients will receive messages sent to their MAC address and +all devices (**except ESP8266 devices**) will also receive messages sent to the +*broadcast* MAC address (``b'\xff\xff\xff\xff\xff\xff'``) or any multicast +MAC address. + +All ESPNow devices (including ESP8266 devices) can also send messages to the +broadcast MAC address or any multicast MAC address. + +To `send()` a broadcast message, the broadcast (or +multicast) MAC address must first be registered using +`add_peer()`. `send()` will always return +``True`` for broadcasts, regardless of whether any devices receive the +message. It is not permitted to encrypt messages sent to the broadcast +address or any multicast address. + +**Note**: `ESPNow.send(None, msg)` will send to all registered +peers *except* the broadcast address. To send a broadcast or multicast +message, you must specify the broadcast (or multicast) MAC address as the +peer. For example:: + + bcast = b'\xff' * 6 + e.add_peer(bcast) + e.send(bcast, "Hello World!") + +ESPNow and Wifi Operation +------------------------- + +ESPNow messages may be sent and received on any `active()` +`WLAN` interface (``network.STA_IF`` or ``network.AP_IF``), even +if that interface is also connected to a wifi network or configured as an access +point. When an ESP32 or ESP8266 device connects to a Wifi Access Point (see +`ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things +happen which affect ESPNow communications: + +1. Wifi Power-saving Mode (`network.WLAN.PM_PERFORMANCE`) + is automatically activated and +2. The radio on the esp device changes wifi ``channel`` to match the channel + used by the Access Point. + +**Wifi Power-saving Mode:** (see `Espressif Docs `_) The power saving mode causes the +device to turn off the radio periodically (typically for hundreds of +milliseconds), making it unreliable in receiving ESPNow messages. This can be +resolved by either of: + +1. Disabling the power-saving mode on the STA_IF interface; + + - Use ``sta.config(pm=sta.PM_NONE)`` + +2. Turning on the AP_IF interface, which will disable the power saving mode. + However, the device will then be advertising an active wifi access point. + + - You **may** also choose to send your messages via the AP_IF interface, but + this is not necessary. + - ESP8266 peers must send messages to this AP_IF interface (see below). + +3. Configuring ESPNow clients to retry sending messages. + +**Receiving messages from an ESP8266 device:** Strangely, an ESP32 device +connected to a wifi network using method 1 or 2 above, will receive ESPNow +messages sent to the STA_IF MAC address from another ESP32 device, but will +**reject** messages from an ESP8266 device!!!. To receive messages from an +ESP8266 device, the AP_IF interface must be set to ``active(True)`` **and** +messages must be sent to the AP_IF MAC address. + +**Managing wifi channels:** Any other ESPNow devices wishing to communicate with +a device which is also connected to a Wifi Access Point MUST use the same +channel. A common scenario is where one ESPNow device is connected to a wifi +router and acts as a proxy for messages from a group of sensors connected via +ESPNow: + +**Proxy:** :: + + import network, time, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.connect('myssid', 'mypassword') + while not sta.isconnected(): # Wait until connected... + time.sleep(0.1) + sta.config(pm=sta.PM_NONE) # ..then disable power saving + + # Print the wifi channel used AFTER finished connecting to access point + print("Proxy running on channel:", sta.config("channel")) + e = espnow.ESPNow(); e.active(True) + for peer, msg in e: + # Receive espnow messages and forward them to MQTT broker over wifi + +**Sensor:** :: + + import network, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.config(channel=6) # Change to the channel used by the proxy above. + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of proxy + e = espnow.ESPNow(); e.active(True); + e.add_peer(peer) + while True: + msg = read_sensor() + e.send(peer, msg) + time.sleep(1) + +Other issues to take care with when using ESPNow with wifi are: + +- **Set WIFI to known state on startup:** MicroPython does not reset the wifi + peripheral after a soft reset. This can lead to unexpected behaviour. To + guarantee the wifi is reset to a known state after a soft reset make sure you + deactivate the STA_IF and AP_IF before setting them to the desired state at + startup, eg.:: + + import network, time + + def wifi_reset(): # Reset wifi to AP_IF off, STA_IF on and disconnected + sta = network.WLAN(network.STA_IF); sta.active(False) + ap = network.WLAN(network.AP_IF); ap.active(False) + sta.active(True) + while not sta.active(): + time.sleep(0.1) + sta.disconnect() # For ESP8266 + while sta.isconnected(): + time.sleep(0.1) + return sta, ap + + sta, ap = wifi_reset() + + Remember that a soft reset occurs every time you connect to the device REPL + and when you type ``ctrl-D``. + +- **STA_IF and AP_IF always operate on the same channel:** the AP_IF will change + channel when you connect to a wifi network; regardless of the channel you set + for the AP_IF (see `Attention Note 3 + `_ + ). After all, there is really only one wifi radio on the device, which is + shared by the STA_IF and AP_IF virtual devices. + +- **Disable automatic channel assignment on your wifi router:** If the wifi + router for your wifi network is configured to automatically assign the wifi + channel, it may change the channel for the network if it detects interference + from other wifi routers. When this occurs, the ESP devices connected to the + wifi network will also change channels to match the router, but other + ESPNow-only devices will remain on the previous channel and communication will + be lost. To mitigate this, either set your wifi router to use a fixed wifi + channel or configure your devices to re-scan the wifi channels if they are + unable to find their expected peers on the current channel. + +- **MicroPython re-scans wifi channels when trying to reconnect:** If the esp + device is connected to a Wifi Access Point that goes down, MicroPython will + automatically start scanning channels in an attempt to reconnect to the + Access Point. This means ESPNow messages will be lost while scanning for the + AP. This can be disabled by ``sta.config(reconnects=0)``, which will also + disable the automatic reconnection after losing connection. + +- Some versions of the ESP IDF only permit sending ESPNow packets from the + STA_IF interface to peers which have been registered on the same wifi + channel as the STA_IF:: + + ESPNOW: Peer channel is not equal to the home channel, send fail! + +ESPNow and Sleep Modes +---------------------- + +The `machine.lightsleep([time_ms])` and +`machine.deepsleep([time_ms])` functions can be used to put +the ESP32 and peripherals (including the WiFi and Bluetooth radios) to sleep. +This is useful in many applications to conserve battery power. However, +applications must disable the WLAN peripheral (using +`active(False)`) before entering light or deep sleep (see +`Sleep Modes `_). +Otherwise the WiFi radio may not be initialised properly after wake from +sleep. If the ``STA_IF`` and ``AP_IF`` interfaces have both been set +`active(True)` then both interfaces should be set +`active(False)` before entering any sleep mode. + +**Example:** deep sleep:: + + import network, machine, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer + e = espnow.ESPNow() + e.active(True) + e.add_peer(peer) # Register peer on STA_IF + + print('Sending ping...') + if not e.send(peer, b'ping'): + print('Ping failed!') + e.active(False) + sta.active(False) # Disable the wifi before sleep + print('Going to sleep...') + machine.deepsleep(10000) # Sleep for 10 seconds then reboot + +**Example:** light sleep:: + + import network, machine, espnow + + sta, ap = wifi_reset() # Reset wifi to AP off, STA on and disconnected + sta.config(channel=6) + peer = b'0\xaa\xaa\xaa\xaa\xaa' # MAC address of peer + e = espnow.ESPNow() + e.active(True) + e.add_peer(peer) # Register peer on STA_IF + + while True: + print('Sending ping...') + if not e.send(peer, b'ping'): + print('Ping failed!') + sta.active(False) # Disable the wifi before sleep + print('Going to sleep...') + machine.lightsleep(10000) # Sleep for 10 seconds + sta.active(True) + sta.config(channel=6) # Wifi loses config after lightsleep() + diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 13502cc7aef38..149f4d6609be9 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -11,19 +11,19 @@ class FrameBuffer ----------------- The FrameBuffer class provides a pixel buffer which can be drawn upon with -pixels, lines, rectangles, text and even other FrameBuffer's. It is useful -when generating output for displays. +pixels, lines, rectangles, ellipses, polygons, text and even other +FrameBuffers. It is useful when generating output for displays. For example:: import framebuf # FrameBuffer needs 2 bytes for every RGB565 pixel - fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) + fbuf = framebuf.FrameBuffer(bytearray(100 * 10 * 2), 100, 10, framebuf.RGB565) fbuf.fill(0) fbuf.text('MicroPython!', 0, 0, 0xffff) - fbuf.hline(0, 10, 96, 0xffff) + fbuf.hline(0, 9, 96, 0xffff) Constructors ------------ @@ -77,12 +77,37 @@ The following methods draw shapes onto the FrameBuffer. methods draw horizontal and vertical lines respectively up to a given length. -.. method:: FrameBuffer.rect(x, y, w, h, c) -.. method:: FrameBuffer.fill_rect(x, y, w, h, c) +.. method:: FrameBuffer.rect(x, y, w, h, c[, f]) - Draw a rectangle at the given location, size and color. The `rect` - method draws only a 1 pixel outline whereas the `fill_rect` method - draws both the outline and interior. + Draw a rectangle at the given location, size and color. + + The optional *f* parameter can be set to ``True`` to fill the rectangle. + Otherwise just a one pixel outline is drawn. + +.. method:: FrameBuffer.ellipse(x, y, xr, yr, c[, f, m]) + + Draw an ellipse at the given location. Radii *xr* and *yr* define the + geometry; equal values cause a circle to be drawn. The *c* parameter + defines the color. + + The optional *f* parameter can be set to ``True`` to fill the ellipse. + Otherwise just a one pixel outline is drawn. + + The optional *m* parameter enables drawing to be restricted to certain + quadrants of the ellipse. The LS four bits determine which quadrants are + to be drawn, with bit 0 specifying Q1, b1 Q2, b2 Q3 and b3 Q4. Quadrants + are numbered counterclockwise with Q1 being top right. + +.. method:: FrameBuffer.poly(x, y, coords, c[, f]) + + Given a list of coordinates, draw an arbitrary (convex or concave) closed + polygon at the given x, y location using the given color. + + The *coords* must be specified as a :mod:`array` of integers, e.g. + ``array('h', [x0, y0, x1, y1, ... xn, yn])``. + + The optional *f* parameter can be set to ``True`` to fill the polygon. + Otherwise just a one pixel outline is drawn. Drawing text ------------ @@ -108,7 +133,9 @@ Other methods Draw another FrameBuffer on top of the current one at the given coordinates. If *key* is specified then it should be a color integer and the corresponding color will be considered transparent: all pixels with that - color value will not be drawn. + color value will not be drawn. (If the *palette* is specified then the *key* + is compared to the value from *palette*, not to the value directly from + *fbuf*.) The *palette* argument enables blitting between FrameBuffers with differing formats. Typical usage is to render a monochrome or grayscale glyph/icon to diff --git a/docs/library/gc.rst b/docs/library/gc.rst index c823aed3e688b..2ba204e2293c0 100644 --- a/docs/library/gc.rst +++ b/docs/library/gc.rst @@ -24,7 +24,7 @@ Functions .. function:: mem_alloc() - Return the number of bytes of heap RAM that are allocated. + Return the number of bytes of heap RAM that are allocated by Python code. .. admonition:: Difference to CPython :class: attention @@ -33,8 +33,8 @@ Functions .. function:: mem_free() - Return the number of bytes of available heap RAM, or -1 if this amount - is not known. + Return the number of bytes of heap RAM that is available for Python + code to allocate, or -1 if this amount is not known. .. admonition:: Difference to CPython :class: attention diff --git a/docs/library/gzip.rst b/docs/library/gzip.rst new file mode 100644 index 0000000000000..f36f896db3a11 --- /dev/null +++ b/docs/library/gzip.rst @@ -0,0 +1,106 @@ +:mod:`gzip` -- gzip compression & decompression +=============================================== + +.. module:: gzip + :synopsis: gzip compression & decompression + +|see_cpython_module| :mod:`python:gzip`. + +This module allows compression and decompression of binary data with the +`DEFLATE algorithm `_ used by the gzip +file format. + +.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this + module as it provides a streaming interface to compression and decompression + which is convenient and more memory efficient when working with reading or + writing compressed data to a file, socket, or stream. + +**Availability:** + +* This module is **not present by default** in official MicroPython firmware + releases as it duplicates functionality available in the :mod:`deflate + ` module. + +* A copy of this module can be installed (or frozen) + from :term:`micropython-lib` (`source `_). + See :ref:`packages` for more information. This documentation describes that module. + +* Compression support will only be available if compression support is enabled + in the built-in :mod:`deflate ` module. + +Functions +--------- + +.. function:: open(filename, mode, /) + + Wrapper around built-in :func:`open` returning a GzipFile instance. + +.. function:: decompress(data, /) + + Decompresses *data* into a bytes object. + +.. function:: compress(data, /) + + Compresses *data* into a bytes object. + +Classes +------- + +.. class:: GzipFile(*, fileobj, mode) + + This class can be used to wrap a *fileobj* which is any + :term:`stream-like ` object such as a file, socket, or stream + (including :class:`io.BytesIO`). It is itself a stream and implements the + standard read/readinto/write/close methods. + + When the *mode* argument is ``"rb"``, reads from the GzipFile instance will + decompress the data in the underlying stream and return decompressed data. + + If compression support is enabled then the *mode* argument can be set to + ``"wb"``, and writes to the GzipFile instance will be compressed and written + to the underlying stream. + + By default the GzipFile class will read and write data using the gzip file + format, including a header and footer with checksum and a window size of 512 + bytes. + + The **file**, **compresslevel**, and **mtime** arguments are not + supported. **fileobj** and **mode** must always be specified as keyword + arguments. + +Examples +-------- + +A typical use case for :class:`gzip.GzipFile` is to read or write a compressed +file from storage: + +.. code:: python + + import gzip + + # Reading: + with open("data.gz", "rb") as f: + with gzip.GzipFile(fileobj=f, mode="rb") as g: + # Use g.read(), g.readinto(), etc. + + # Same, but using gzip.open: + with gzip.open("data.gz", "rb") as f: + # Use f.read(), f.readinto(), etc. + + # Writing: + with open("data.gz", "wb") as f: + with gzip.GzipFile(fileobj=f, mode="wb") as g: + # Use g.write(...) etc + + # Same, but using gzip.open: + with gzip.open("data.gz", "wb") as f: + # Use f.write(...) etc + + # Write a dictionary as JSON in gzip format, with a + # small (64 byte) window size. + config = { ... } + with gzip.open("config.gz", "wb") as f: + json.dump(config, f) + +For guidance on working with gzip sources and choosing the window size see the +note at the :ref:`end of the deflate documentation `. diff --git a/docs/library/heapq.rst b/docs/library/heapq.rst index 5e808d544aed7..673871c5fc277 100644 --- a/docs/library/heapq.rst +++ b/docs/library/heapq.rst @@ -23,7 +23,7 @@ Functions Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if ``heap`` is empty. - + The returned item will be the smallest item in the ``heap``. .. function:: heapify(x) diff --git a/docs/library/index.rst b/docs/library/index.rst index 2b1d6b9651343..eb29b7680542e 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -8,15 +8,17 @@ MicroPython libraries Important summary of this section * MicroPython provides built-in modules that mirror the functionality of the - Python standard library (e.g. :mod:`os`, :mod:`time`), as well as - MicroPython-specific modules (e.g. :mod:`bluetooth`, :mod:`machine`). - * Most standard library modules implement a subset of the functionality of - the equivalent Python module, and in a few cases provide some - MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`) + :ref:`Python standard library ` (e.g. :mod:`os`, + :mod:`time`), as well as :ref:`MicroPython-specific modules ` + (e.g. :mod:`bluetooth`, :mod:`machine`). + * Most Python standard library modules implement a subset of the + functionality of the equivalent Python module, and in a few cases provide + some MicroPython-specific extensions (e.g. :mod:`array`, :mod:`os`) * Due to resource constraints or other limitations, some ports or firmware versions may not include all the functionality documented here. - * To allow for extensibility, the built-in modules can be extended from - Python code loaded onto the device. + * To allow for extensibility, some built-in modules can be + :ref:`extended from Python code ` loaded onto + the device filesystem. This chapter describes modules (function and class libraries) which are built into MicroPython. This documentation in general aspires to describe all modules @@ -41,6 +43,8 @@ Beyond the built-in libraries described in this documentation, many more modules from the Python standard library, as well as further MicroPython extensions to it, can be found in :term:`micropython-lib`. +.. _micropython_lib_python: + Python standard libraries and micro-libraries --------------------------------------------- @@ -53,18 +57,21 @@ library. :maxdepth: 1 array.rst + asyncio.rst binascii.rst builtins.rst cmath.rst collections.rst errno.rst gc.rst + gzip.rst hashlib.rst heapq.rst io.rst json.rst math.rst os.rst + platform.rst random.rst re.rst select.rst @@ -73,10 +80,10 @@ library. struct.rst sys.rst time.rst - uasyncio.rst zlib.rst _thread.rst +.. _micropython_lib_micropython: MicroPython-specific libraries ------------------------------ @@ -90,12 +97,21 @@ the following libraries. bluetooth.rst btree.rst cryptolib.rst + deflate.rst framebuf.rst machine.rst micropython.rst neopixel.rst network.rst uctypes.rst + vfs.rst + +The following libraries provide drivers for hardware components. + +.. toctree:: + :maxdepth: 1 + + wm8960.rst Port-specific libraries @@ -148,6 +164,11 @@ The following libraries are specific to the ESP8266 and ESP32. esp.rst esp32.rst +.. toctree:: + :maxdepth: 1 + + espnow.rst + Libraries specific to the RP2040 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -169,23 +190,60 @@ The following libraries are specific to the Zephyr port. zephyr.rst +.. _micropython_lib_extending: + Extending built-in libraries from Python ---------------------------------------- -In most cases, the above modules are actually named ``umodule`` rather than -``module``, but MicroPython will alias any module prefixed with a ``u`` to the -non-``u`` version. However a file (or :term:`frozen module`) named -``module.py`` will take precedence over this alias. +A subset of the built-in modules are able to be extended by Python code by +providing a module of the same name in the filesystem. This extensibility +applies to the following Python standard library modules which are built-in to +the firmware: ``array``, ``binascii``, ``collections``, ``errno``, ``gzip``, +``hashlib``, ``heapq``, ``io``, ``json``, ``os``, ``platform``, ``random``, +``re``, ``select``, ``socket``, ``ssl``, ``struct``, ``time`` ``zlib``, as well +as the MicroPython-specific ``machine`` module. All other built-in modules +cannot be extended from the filesystem. This allows the user to provide an extended implementation of a built-in library -(perhaps to provide additional CPython compatibility). The user-provided module -(in ``module.py``) can still use the built-in functionality by importing -``umodule`` directly. This is used extensively in :term:`micropython-lib`. See -:ref:`packages` for more information. - -This applies to both the Python standard libraries (e.g. ``os``, ``time``, etc), -but also the MicroPython libraries too (e.g. ``machine``, ``bluetooth``, etc). -The main exception is the port-specific libraries (``pyb``, ``esp``, etc). - -*Other than when you specifically want to force the use of the built-in module, -we recommend always using ``import module`` rather than ``import umodule``.* +(perhaps to provide additional CPython compatibility or missing functionality). +This is used extensively in :term:`micropython-lib`, see :ref:`packages` for +more information. The filesystem module will typically do a wildcard import of +the built-in module in order to inherit all the globals (classes, functions and +variables) from the built-in. + +In MicroPython v1.21.0 and higher, to prevent the filesystem module from +importing itself, it can force an import of the built-in module it by +temporarily clearing ``sys.path`` during the import. For example, to extend the +``time`` module from Python, a file named ``time.py`` on the filesystem would +do the following:: + + _path = sys.path + sys.path = () + try: + from time import * + finally: + sys.path = _path + del _path + + def extra_method(): + pass + +The result is that ``time.py`` contains all the globals of the built-in ``time`` +module, but adds ``extra_method``. + +In earlier versions of MicroPython, you can force an import of a built-in module +by appending a ``u`` to the start of its name. For example, ``import utime`` +instead of ``import time``. For example, ``time.py`` on the filesystem could +look like:: + + from utime import * + + def extra_method(): + pass + +This way is still supported, but the ``sys.path`` method described above is now +preferred as the ``u``-prefix will be removed from the names of built-in +modules in a future version of MicroPython. + +*Other than when it specifically needs to force the use of the built-in module, +code should always use* ``import module`` *rather than* ``import umodule``. diff --git a/docs/library/io.rst b/docs/library/io.rst index 6b4b9f1a476f6..caa59895227d4 100644 --- a/docs/library/io.rst +++ b/docs/library/io.rst @@ -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]) diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst index 85e4b8f07a1f6..25903eb22bf71 100644 --- a/docs/library/lcd160cr.rst +++ b/docs/library/lcd160cr.rst @@ -313,7 +313,7 @@ Advanced commands specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner. The `framebuf `_ module can be used to construct frame buffers - and provides drawing primitives. Using a frame buffer will improve + and provides drawing primitives. Using a frame buffer will improve performance of animations when compared to drawing directly to the screen. .. method:: LCD160CR.set_scroll(on) diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADC.rst index 1404b454ae7f5..65225ea8788da 100644 --- a/docs/library/machine.ADC.rst +++ b/docs/library/machine.ADC.rst @@ -4,32 +4,63 @@ class ADC -- analog to digital conversion ========================================= -The ADC class provides an interface to analog-to-digital convertors, and +The ADC class provides an interface to analog-to-digital converters, and represents a single endpoint that can sample a continuous voltage and convert it to a discretised value. +For extra control over ADC sampling see :ref:`machine.ADCBlock `. + Example usage:: - import machine + from machine import ADC - adc = machine.ADC(pin) # create an ADC object acting on a pin - val = adc.read_u16() # read a raw analog value in the range 0-65535 + adc = ADC(pin) # create an ADC object acting on a pin + val = adc.read_u16() # read a raw analog value in the range 0-65535 + val = adc.read_uv() # read an analog value in microvolts Constructors ------------ -.. class:: ADC(id) +.. class:: ADC(id, *, sample_ns, atten) Access the ADC associated with a source identified by *id*. This *id* may be an integer (usually specifying a channel number), a :ref:`Pin ` object, or other value supported by the underlying machine. + If additional keyword-arguments are given then they will configure + various aspects of the ADC. If not given, these settings will take + previous or default values. The settings are: + + - *sample_ns* is the sampling time in nanoseconds. + + - *atten* specifies the input attenuation. + Methods ------- +.. method:: ADC.init(*, sample_ns, atten) + + Apply the given settings to the ADC. Only those arguments that are + specified will be changed. See the ADC constructor above for what the + arguments are. + +.. method:: ADC.block() + + Return the :ref:`ADCBlock ` instance associated with + this ADC object. + + This method only exists if the port supports the + :ref:`ADCBlock ` class. + .. method:: ADC.read_u16() Take an analog reading and return an integer in the range 0-65535. The return value represents the raw reading taken by the ADC, scaled such that the minimum value is 0 and the maximum value is 65535. + +.. method:: ADC.read_uv() + + Take an analog reading and return an integer value with units of + microvolts. It is up to the particular port whether or not this value + is calibrated, and how calibration is done. diff --git a/docs/library/machine.ADCBlock.rst b/docs/library/machine.ADCBlock.rst new file mode 100644 index 0000000000000..eb94362d5597c --- /dev/null +++ b/docs/library/machine.ADCBlock.rst @@ -0,0 +1,61 @@ +.. currentmodule:: machine +.. _machine.ADCBlock: + +class ADCBlock -- control ADC peripherals +========================================= + +The ADCBlock class provides access to an ADC peripheral which has a +number of channels that can be used to sample analog values. It allows +finer control over configuration of :ref:`machine.ADC ` +objects, which do the actual sampling. + +This class is not always available. + +Example usage:: + + from machine import ADCBlock + + block = ADCBlock(id, bits=12) # create an ADCBlock with 12-bit resolution + adc = block.connect(4, pin) # connect channel 4 to the given pin + val = adc.read_uv() # read an analog value + +Constructors +------------ + +.. class:: ADCBlock(id, *, bits) + + Access the ADC peripheral identified by *id*, which may be an integer + or string. + + The *bits* argument, if given, sets the resolution in bits of the + conversion process. If not specified then the previous or default + resolution is used. + +Methods +------- + +.. method:: ADCBlock.init(*, bits) + + Configure the ADC peripheral. *bits* will set the resolution of the + conversion process. + +.. 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 ` object that represents that connection. + + The *channel* argument must be an integer, and *source* must be an object + (for example a :ref:`Pin `) which can be connected up for sampling. + + If only *channel* is given then it is configured for sampling. + + If only *source* is given then that object is connected to a default + channel ready for sampling. + + 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 ` method. diff --git a/docs/library/machine.ADCWiPy.rst b/docs/library/machine.ADCWiPy.rst index e500d00890f3a..d4ccde2056aac 100644 --- a/docs/library/machine.ADCWiPy.rst +++ b/docs/library/machine.ADCWiPy.rst @@ -27,13 +27,13 @@ Constructors Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. For more info check the `pinout and alternate functions - table. `_ + table. `_ - .. warning:: + .. warning:: - ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it - can withstand). When GP2, GP3, GP4 or GP5 are remapped to the - ADC block, 1.8 V is the maximum. If these pins are used in digital mode, + ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it + can withstand). When GP2, GP3, GP4 or GP5 are remapped to the + ADC block, 1.8 V is the maximum. If these pins are used in digital mode, then the maximum allowed input is 3.6V. Methods diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index f46d64ef51d4d..635d5873444b5 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -20,6 +20,17 @@ Software I2C is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed. +.. Note:: + + The I2C bus requires pull-up circuitry on both SDA and SCL for it's operation. + Usually these are resistors in the range of 1 - 10 kOhm, connected from each SDA/SCL + to Vcc. Without these, the behaviour is undefined and may range from blocking, + unexpected watchdog reset to just wrong values. Often, this pull-up circuitry + is built-in already to the MCU board or sensor breakout boards, but there is + no rule for that. So please check in case of trouble. See also this excellent + `learning guide `_ + by Adafruit about I2C wiring. + Example usage:: from machine import I2C @@ -41,7 +52,7 @@ Example usage:: Constructors ------------ -.. class:: I2C(id, *, scl, sda, freq=400000) +.. class:: I2C(id, *, scl, sda, freq=400000, timeout=50000) Construct and return a new I2C object using the following parameters: @@ -51,13 +62,15 @@ Constructors - *sda* should be a pin object specifying the pin to use for SDA. - *freq* should be an integer which sets the maximum frequency for SCL. + - *timeout* is the maximum time in microseconds to allow for I2C + transactions. This parameter is not allowed on some ports. Note that some ports/boards will have default values of *scl* and *sda* that can be changed in this constructor. Others will have fixed values of *scl* and *sda* that cannot be changed. .. _machine.SoftI2C: -.. class:: SoftI2C(scl, sda, *, freq=400000, timeout=255) +.. class:: SoftI2C(scl, sda, *, freq=400000, timeout=50000) Construct a new software I2C object. The parameters are: @@ -80,6 +93,10 @@ General Methods - *sda* is a pin object for the SDA line - *freq* is the SCL clock rate + In the case of hardware I2C the actual clock frequency may be lower than the + requested frequency. This is dependent on the platform hardware. The actual + rate may be determined by printing the I2C object. + .. method:: I2C.deinit() Turn off the I2C bus. diff --git a/docs/library/machine.I2S.rst b/docs/library/machine.I2S.rst index d64fba33e4529..84edb94e78dbf 100644 --- a/docs/library/machine.I2S.rst +++ b/docs/library/machine.I2S.rst @@ -4,102 +4,106 @@ class I2S -- Inter-IC Sound bus protocol ======================================== -I2S is a synchronous serial protocol used to connect digital audio devices. +I2S is a synchronous serial protocol used to connect digital audio devices. At the physical level, a bus consists of 3 lines: SCK, WS, SD. The I2S class supports controller operation. Peripheral operation is not supported. -The I2S class is currently available as a Technical Preview. During the preview period, feedback from +The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. I2S objects can be created and initialized using:: from machine import I2S from machine import Pin - + # ESP32 sck_pin = Pin(14) # Serial clock output ws_pin = Pin(13) # Word clock output sd_pin = Pin(12) # Serial data output - + or - + # PyBoards sck_pin = Pin("Y6") # Serial clock output ws_pin = Pin("Y5") # Word clock output sd_pin = Pin("Y8") # Serial data output - - audio_out = I2S(2, + + audio_out = I2S(2, sck=sck_pin, ws=ws_pin, sd=sd_pin, - mode=I2S.TX, - bits=16, + mode=I2S.TX, + bits=16, format=I2S.MONO, - rate=44100, + rate=44100, ibuf=20000) - - audio_in = I2S(2, + + audio_in = I2S(2, sck=sck_pin, ws=ws_pin, sd=sd_pin, - mode=I2S.RX, - bits=32, + mode=I2S.RX, + bits=32, format=I2S.STEREO, - rate=22050, + rate=22050, ibuf=20000) - + 3 modes of operation are supported: - - blocking - - non-blocking - - uasyncio - + - blocking + - non-blocking + - asyncio + blocking:: - + num_written = audio_out.write(buf) # blocks until buf emptied num_read = audio_in.readinto(buf) # blocks until buf filled - + non-blocking:: - + audio_out.irq(i2s_callback) # i2s_callback is called when buf is emptied num_written = audio_out.write(buf) # returns immediately - + audio_in.irq(i2s_callback) # i2s_callback is called when buf is filled - num_read = audio_in.readinto(buf) # returns immediately - -uasyncio:: - - swriter = uasyncio.StreamWriter(audio_out) + num_read = audio_in.readinto(buf) # returns immediately + +asyncio:: + + swriter = asyncio.StreamWriter(audio_out) swriter.write(buf) await swriter.drain() - - sreader = uasyncio.StreamReader(audio_in) + + sreader = asyncio.StreamReader(audio_in) num_read = await sreader.readinto(buf) - + +Some codec devices like the WM8960 or SGTL5000 require separate initialization +before they can operate with the I2S class. For these, separate drivers are +supplied, which also offer methods for controlling volume, audio processing and +other things. For these drivers see: + +- :ref:`wm8960` + Constructor ----------- -.. class:: I2S(id, *, sck, ws, sd, mode, bits, format, rate, ibuf) +.. class:: I2S(id, *, sck, ws, sd, mck=None, mode, bits, format, rate, ibuf) Construct an I2S object of the given id: - - - ``id`` identifies a particular I2S bus. - - ``id`` is board and port specific: - - - PYBv1.0/v1.1: has one I2S bus with id=2. - - PYBD-SFxW: has two I2S buses with id=1 and id=2. - - ESP32: has two I2S buses with id=0 and id=1. - + + - ``id`` identifies a particular I2S bus; it is board and port specific + Keyword-only parameters that are supported on all ports: - + - ``sck`` is a pin object for the serial clock line - ``ws`` is a pin object for the word select line - ``sd`` is a pin object for the serial data line + - ``mck`` is a pin object for the master clock line; + master clock frequency is sampling rate * 256 - ``mode`` specifies receive or transmit - ``bits`` specifies sample size (bits), 16 or 32 - ``format`` specifies channel format, STEREO or MONO - - ``rate`` specifies audio sampling rate (samples/s) + - ``rate`` specifies audio sampling rate (Hz); + this is the frequency of the ``ws`` signal - ``ibuf`` specifies internal buffer length (bytes) - - For all ports, DMA runs continuously in the background and allows user applications to perform other operations while - sample data is transfered between the internal buffer and the I2S peripheral unit. + + For all ports, DMA runs continuously in the background and allows user applications to perform other operations while + sample data is transferred between the internal buffer and the I2S peripheral unit. Increasing the size of the internal buffer has the potential to increase the time that user applications can perform non-I2S operations before underflow (e.g. ``write`` method) or overflow (e.g. ``readinto`` method). @@ -109,37 +113,37 @@ Methods .. method:: I2S.init(sck, ...) see Constructor for argument descriptions - + .. method:: I2S.deinit() Deinitialize the I2S bus - + .. method:: I2S.readinto(buf) - Read audio samples into the buffer specified by ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. - "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, + Read audio samples into the buffer specified by ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. + "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, the left channel sample data is used. - Returns number of bytes read - + Returns number of bytes read + .. method:: I2S.write(buf) Write audio samples contained in ``buf``. ``buf`` must support the buffer protocol, such as bytearray or array. - "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, + "buf" byte ordering is little-endian. For Stereo format, left channel sample precedes right channel sample. For Mono format, the sample data is written to both the right and left channels. - Returns number of bytes written - + Returns number of bytes written + .. method:: I2S.irq(handler) - Set a callback. ``handler`` is called when ``buf`` is emptied (``write`` method) or becomes full (``readinto`` method). + Set a callback. ``handler`` is called when ``buf`` is emptied (``write`` method) or becomes full (``readinto`` method). Setting a callback changes the ``write`` and ``readinto`` methods to non-blocking operation. ``handler`` is called in the context of the MicroPython scheduler. - + .. staticmethod:: I2S.shift(*, buf, bits, shift) - bitwise shift of all samples contained in ``buf``. ``bits`` specifies sample size in bits. ``shift`` specifies the number of bits to shift each sample. - Positive for left shift, negative for right shift. + bitwise shift of all samples contained in ``buf``. ``bits`` specifies sample size in bits. ``shift`` specifies the number of bits to shift each sample. + Positive for left shift, negative for right shift. Typically used for volume control. Each bit shift changes sample volume by 6dB. - + Constants --------- diff --git a/docs/library/machine.PWM.rst b/docs/library/machine.PWM.rst index f2273d8b453da..b9cf00240314c 100644 --- a/docs/library/machine.PWM.rst +++ b/docs/library/machine.PWM.rst @@ -10,7 +10,8 @@ Example usage:: from machine import PWM - pwm = PWM(pin) # create a PWM object on a pin + pwm = PWM(pin, freq=50, duty_u16=8192) # create a PWM object on a pin + # and set freq and duty pwm.duty_u16(32768) # set duty to 50% # reinitialise with a period of 200us, duty of 5us @@ -23,7 +24,7 @@ Example usage:: Constructors ------------ -.. class:: PWM(dest, \*, freq, duty_u16, duty_ns) +.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert) Construct and return a new PWM object using the following parameters: @@ -34,15 +35,17 @@ Constructors PWM cycle. - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``. - *duty_ns* sets the pulse width in nanoseconds. + - *invert* inverts the respective output if the value is True Setting *freq* may affect other PWM objects if the objects share the same underlying PWM generator (this is hardware specific). Only one of *duty_u16* and *duty_ns* should be specified at a time. + *invert* is not available at all ports. Methods ------- -.. method:: PWM.init(\*, freq, duty_u16, duty_ns) +.. method:: PWM.init(*, freq, duty_u16, duty_ns) Modify settings for the PWM object. See the above constructor for details about the parameters. @@ -77,3 +80,46 @@ Methods With no arguments the pulse width in nanoseconds is returned. With a single *value* argument the pulse width is set to that value. + +Specific PWM class implementations +---------------------------------- + +The following concrete class(es) implement enhancements to the PWM class. + + | :ref:`pyb.Timer for PyBoard ` + +Limitations of PWM +------------------ + +* Not all frequencies can be generated with absolute accuracy due to + the discrete nature of the computing hardware. Typically the PWM frequency + is obtained by dividing some integer base frequency by an integer divider. + For example, if the base frequency is 80MHz and the required PWM frequency is + 300kHz the divider must be a non-integer number 80000000 / 300000 = 266.67. + After rounding the divider is set to 267 and the PWM frequency will be + 80000000 / 267 = 299625.5 Hz, not 300kHz. If the divider is set to 266 then + the PWM frequency will be 80000000 / 266 = 300751.9 Hz, but again not 300kHz. + + Some ports like the RP2040 one use a fractional divider, which allow a finer + granularity of the frequency at higher frequencies by switching the PWM + pulse duration between two adjacent values, such that the resulting average + frequency is more close to the intended one, at the cost of spectral purity. + +* The duty cycle has the same discrete nature and its absolute accuracy is not + achievable. On most hardware platforms the duty will be applied at the next + frequency period. Therefore, you should wait more than "1/frequency" before + measuring the duty. + +* The frequency and the duty cycle resolution are usually interdependent. + The higher the PWM frequency the lower the duty resolution which is available, + and vice versa. For example, a 300kHz PWM frequency can have a duty cycle + resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest + 8 bits of *duty_u16* are insignificant. So:: + + pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2) + + and:: + + pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2 + 255) + + will generate PWM with the same 50% duty cycle. diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst index f8e9e1054d65b..49fb66beb38ea 100644 --- a/docs/library/machine.Pin.rst +++ b/docs/library/machine.Pin.rst @@ -42,7 +42,7 @@ Usage Model:: Constructors ------------ -.. class:: Pin(id, mode=-1, pull=-1, *, value, drive, alt) +.. class:: Pin(id, mode=-1, pull=-1, *, value=None, drive=0, alt=-1) Access the pin peripheral (GPIO pin) associated with the given ``id``. If additional arguments are given in the constructor then they are used to initialise @@ -74,6 +74,8 @@ Constructors - ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as open-drain. Not all ports implement this mode. + - ``Pin.ANALOG`` - Pin is configured for analog input, see the :class:`ADC` class. + - ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be one of: @@ -85,9 +87,9 @@ Constructors output pin value if given, otherwise the state of the pin peripheral remains unchanged. - - ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``, - ``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities - are port dependent. Not all ports implement this argument. + - ``drive`` specifies the output power of the pin and can be one of: ``Pin.DRIVE_0``, + ``Pin.DRIVE_1``, etc., increasing in drive strength. The actual current driving + capabilities are port dependent. Not all ports implement this argument. - ``alt`` specifies an alternate function for the pin and the values it can take are port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN`` @@ -106,7 +108,7 @@ Constructors Methods ------- -.. method:: Pin.init(mode=-1, pull=-1, *, value, drive, alt) +.. method:: Pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1) Re-initialise the pin using the given parameters. Only those arguments that are specified will be set. The rest of the pin peripheral state will remain @@ -247,6 +249,7 @@ not all constants are available on all ports. Pin.OPEN_DRAIN Pin.ALT Pin.ALT_OPEN_DRAIN + Pin.ANALOG Selects the pin mode. @@ -257,11 +260,13 @@ not all constants are available on all ports. Selects whether there is a pull up/down resistor. Use the value ``None`` for no pull. -.. data:: Pin.LOW_POWER - Pin.MED_POWER - Pin.HIGH_POWER +.. data:: Pin.DRIVE_0 + Pin.DRIVE_1 + Pin.DRIVE_2 - Selects the pin drive strength. + Selects the pin drive strength. A port may define additional drive + constants with increasing number corresponding to increasing drive + strength. .. data:: Pin.IRQ_FALLING Pin.IRQ_RISING diff --git a/docs/library/machine.SD.rst b/docs/library/machine.SD.rst index d985db231aa44..b10b407a2f65e 100644 --- a/docs/library/machine.SD.rst +++ b/docs/library/machine.SD.rst @@ -20,11 +20,11 @@ more info regarding the pins which can be remapped to be used with a SD card. Example usage:: from machine import SD - import os + import vfs # clk cmd and dat0 pins must be passed along with # their respective alternate functions sd = machine.SD(pins=('GP10', 'GP11', 'GP15')) - os.mount(sd, '/sd') + vfs.mount(sd, '/sd') # do normal file operations Constructors @@ -32,7 +32,7 @@ Constructors .. class:: SD(id,... ) - Create a SD card object. See ``init()`` for parameters if initialization. + Create a SD card object. See ``init()`` for parameters if initialization. Methods ------- diff --git a/docs/library/machine.SDCard.rst b/docs/library/machine.SDCard.rst index 96fb5b01c8a81..e4bb25dfc0377 100644 --- a/docs/library/machine.SDCard.rst +++ b/docs/library/machine.SDCard.rst @@ -27,10 +27,10 @@ vary from platform to platform. This class provides access to SD or MMC storage cards using either a dedicated SD/MMC interface hardware or through an SPI channel. - The class implements the block protocol defined by :class:`os.AbstractBlockDev`. + The class implements the block protocol defined by :class:`vfs.AbstractBlockDev`. This allows the mounting of an SD card to be as simple as:: - os.mount(machine.SDCard(), "/sd") + vfs.mount(machine.SDCard(), "/sd") The constructor takes the following parameters: @@ -50,7 +50,7 @@ vary from platform to platform. - *mosi* can be used to specify an SPI mosi pin. - *cs* can be used to specify an SPI chip select pin. - + - *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32). Implementation-specific details @@ -122,3 +122,46 @@ You can set the pins used for SPI access by passing a tuple as the *Note:* The current cc3200 SD card implementation names the this class :class:`machine.SD` rather than :class:`machine.SDCard` . + +mimxrt +`````` + +The SDCard module for the mimxrt port only supports access via dedicated SD/MMC +peripheral (USDHC) in 4-bit mode with 50MHz clock frequency exclusively. +Unfortunately the MIMXRT1011 controller does not support the USDHC peripheral. +Hence this controller does not feature the ``machine.SDCard`` module. + +Due to the decision to only support 4-bit mode with 50MHz clock frequency the +interface has been simplified, and the constructor signature is: + +.. class:: SDCard(slot=1) + :noindex: + +The pins used for the USDHC peripheral have to be configured in ``mpconfigboard.h``. +Most of the controllers supported by the mimxrt port provide up to two USDHC +peripherals. Therefore the pin configuration is performed using the macro +``MICROPY_USDHCx`` with x being 1 or 2 respectively. + +The following shows an example configuration for USDHC1:: + + #define MICROPY_USDHC1 \ + { \ + .cmd = { GPIO_SD_B0_02_USDHC1_CMD}, \ + .clk = { GPIO_SD_B0_03_USDHC1_CLK }, \ + .cd_b = { GPIO_SD_B0_06_USDHC1_CD_B },\ + .data0 = { GPIO_SD_B0_04_USDHC1_DATA0 },\ + .data1 = { GPIO_SD_B0_05_USDHC1_DATA1 },\ + .data2 = { GPIO_SD_B0_00_USDHC1_DATA2 },\ + .data3 = { GPIO_SD_B0_01_USDHC1_DATA3 },\ + } + +If the card detect pin is not used (cb_b pin) then the respective entry has to be +filled with the following dummy value:: + + #define USDHC_DUMMY_PIN NULL , 0 + +Based on the definition of macro ``MICROPY_USDHC1`` and/or ``MICROPY_USDHC2`` +the ``machine.SDCard`` module either supports one or two slots. If only one of +the defines is provided, calling ``machine.SDCard()`` or ``machine.SDCard(1)`` +will return an instance using the respective USDHC peripheral. When both macros +are defined, calling ``machine.SDCard(2)`` returns an instance using USDHC2. diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst index 46ac2ec74ceba..7c3c4b583265a 100644 --- a/docs/library/machine.SPI.rst +++ b/docs/library/machine.SPI.rst @@ -19,6 +19,42 @@ Software SPI is implemented by bit-banging and can be used on any pin but is not as efficient. These classes have the same methods available and differ primarily in the way they are constructed. +Example usage:: + + from machine import SPI, Pin + + spi = SPI(0, baudrate=400000) # Create SPI peripheral 0 at frequency of 400kHz. + # Depending on the use case, extra parameters may be required + # to select the bus characteristics and/or pins to use. + cs = Pin(4, mode=Pin.OUT, value=1) # Create chip-select on pin 4. + + try: + cs(0) # Select peripheral. + spi.write(b"12345678") # Write 8 bytes, and don't care about received data. + finally: + cs(1) # Deselect peripheral. + + try: + cs(0) # Select peripheral. + rxdata = spi.read(8, 0x42) # Read 8 bytes while writing 0x42 for each byte. + finally: + cs(1) # Deselect peripheral. + + rxdata = bytearray(8) + try: + cs(0) # Select peripheral. + spi.readinto(rxdata, 0x42) # Read 8 bytes inplace while writing 0x42 for each byte. + finally: + cs(1) # Deselect peripheral. + + txdata = b"12345678" + rxdata = bytearray(len(txdata)) + try: + cs(0) # Select peripheral. + spi.write_readinto(txdata, rxdata) # Simultaneously write and read bytes. + finally: + cs(1) # Deselect peripheral. + Constructors ------------ @@ -62,7 +98,7 @@ Methods specify them as a tuple of ``pins`` parameter. In the case of hardware SPI the actual clock frequency may be lower than the - requested baudrate. This is dependant on the platform hardware. The actual + requested baudrate. This is dependent on the platform hardware. The actual rate may be determined by printing the SPI object. .. method:: SPI.deinit() @@ -107,9 +143,11 @@ Constants for initialising the SPI bus to controller; this is only used for the WiPy .. data:: SPI.MSB + SoftSPI.MSB set the first bit to be the most significant bit .. data:: SPI.LSB + SoftSPI.LSB set the first bit to be the least significant bit diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 77a549b40b5e9..44e6594080558 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -27,22 +27,32 @@ instead of this class. Constructors ------------ -.. class:: Timer(id, ...) +.. class:: Timer(id, /, ...) - Construct a new timer object of the given id. Id of -1 constructs a + Construct a new timer object of the given ``id``. ``id`` of -1 constructs a virtual timer (if supported by a board). - + ``id`` shall not be passed as a keyword argument. + See ``init`` for parameters of initialisation. Methods ------- -.. method:: Timer.init(*, mode=Timer.PERIODIC, period=-1, callback=None) +.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None) Initialise the timer. Example:: - tim.init(period=100) # periodic with 100ms period - tim.init(mode=Timer.ONE_SHOT, period=1000) # one shot firing after 1000ms + def mycallback(t): + pass + + # periodic at 1kHz + tim.init(mode=Timer.PERIODIC, freq=1000, callback=mycallback) + + # periodic with 100ms period + tim.init(period=100, callback=mycallback) + + # one shot firing after 1000ms + tim.init(mode=Timer.ONE_SHOT, period=1000, callback=mycallback) Keyword arguments: @@ -53,6 +63,19 @@ Methods - ``Timer.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. + - ``freq`` - The timer frequency, in units of Hz. The upper bound of + the frequency is dependent on the port. When both the ``freq`` and + ``period`` arguments are given, ``freq`` has a higher priority and + ``period`` is ignored. + + - ``period`` - The timer period, in milliseconds. + + - ``callback`` - The callable to call upon expiration of the timer period. + The callback must take one argument, which is passed the Timer object. + The ``callback`` argument shall be specified. Otherwise an exception + will occur upon timer expiration: + ``TypeError: 'NoneType' object isn't callable`` + .. method:: Timer.deinit() Deinitialises the timer. Stops the timer, and disables the timer peripheral. diff --git a/docs/library/machine.TimerWiPy.rst b/docs/library/machine.TimerWiPy.rst index 39afc23bc529e..f8c8bb29da7fb 100644 --- a/docs/library/machine.TimerWiPy.rst +++ b/docs/library/machine.TimerWiPy.rst @@ -50,9 +50,9 @@ Methods - ``mode`` can be one of: - - ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured + - ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured period of the channel expires. - - ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured + - ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. - ``TimerWiPy.PWM`` - Output a PWM signal on a pin. @@ -74,7 +74,7 @@ Methods The operating mode is is the one configured to the Timer object that was used to create the channel. - - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. + - ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``. If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``. Keyword only arguments: diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst index 2eb2e20cb3200..072bdb7188a3d 100644 --- a/docs/library/machine.UART.rst +++ b/docs/library/machine.UART.rst @@ -63,8 +63,14 @@ Methods - *timeout* specifies the time to wait for the first character (in ms). - *timeout_char* specifies the time to wait between characters (in ms). - *invert* specifies which lines to invert. + + - ``0`` will not invert lines (idle state of both lines is logic high). + - ``UART.INV_TX`` will invert TX line (idle state of TX line now logic low). + - ``UART.INV_RX`` will invert RX line (idle state of RX line now logic low). + - ``UART.INV_TX | UART.INV_RX`` will invert both lines (idle state at logic low). + - *flow* specifies which hardware flow control signals to use. The value - is a bitmask. + is a bitmask. - ``0`` will ignore hardware flow control signals. - ``UART.RTS`` will enable receive flow control by using the RTS output pin to @@ -81,10 +87,22 @@ Methods When no pins are given, then the default set of TX and RX pins is taken, and hardware flow control will be disabled. If *pins* is ``None``, no pin assignment will be made. + .. note:: + It is possible to call ``init()`` multiple times on the same object in + order to reconfigure UART on the fly. That allows using single UART + peripheral to serve different devices attached to different GPIO pins. + Only one device can be served at a time in that case. + Also do not call ``deinit()`` as it will prevent calling ``init()`` + again. + .. method:: UART.deinit() Turn off the UART bus. + .. note:: + You will not be able to call ``init()`` on the object after ``deinit()``. + A new instance needs to be created in that case. + .. method:: UART.any() Returns an integer counting the number of characters that can be read without @@ -159,6 +177,32 @@ Methods Availability: WiPy. +.. method:: UART.flush() + + Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout + duration depends on the tx buffer size and the baud rate. Unless flow control is enabled, a timeout + should not occur. + + .. note:: + + For the rp2, esp8266 and nrf ports the call returns while the last byte is sent. + If required, a one character wait time has to be added in the calling script. + + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra + +.. method:: UART.txdone() + + Tells whether all data has been sent or no data transfer is happening. In this case, + it returns ``True``. If a data transmission is ongoing it returns ``False``. + + .. note:: + + For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte + of a transfer is still being sent. If required, a one character wait time has to be + added in the calling script. + + Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra + Constants --------- diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst index 612f23ba38620..cf77df9632088 100644 --- a/docs/library/machine.WDT.rst +++ b/docs/library/machine.WDT.rst @@ -15,7 +15,7 @@ Example usage:: wdt = WDT(timeout=2000) # enable it with a timeout of 2s wdt.feed() -Availability of this class: pyboard, WiPy, esp8266, esp32. +Availability of this class: pyboard, WiPy, esp8266, esp32, rp2040, mimxrt. Constructors ------------ @@ -24,14 +24,14 @@ Constructors Create a WDT object and start it. The timeout must be given in milliseconds. Once it is running the timeout cannot be changed and the WDT cannot be stopped either. - - Notes: On the esp32 the minimum timeout is 1 second. On the esp8266 a timeout - cannot be specified, it is determined by the underlying system. + + Notes: On the esp8266 a timeout cannot be specified, it is determined by the underlying system. + On rp2040 devices, the maximum timeout is 8388 ms. Methods ------- -.. method:: wdt.feed() +.. method:: WDT.feed() Feed the WDT to prevent it from resetting the system. The application should place this call in a sensible place ensuring that the WDT is diff --git a/docs/library/machine.rst b/docs/library/machine.rst index c2a6b39001626..3f5cd6f13c72b 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -19,6 +19,44 @@ This is true for both physical devices with IDs >= 0 and "virtual" devices with negative IDs like -1 (these "virtual" devices are still thin shims on top of real hardware and real hardware interrupts). See :ref:`isr_rules`. +Memory access +------------- + +The module exposes three objects used for raw memory access. + +.. data:: mem8 + + Read/write 8 bits of memory. + +.. data:: mem16 + + Read/write 16 bits of memory. + +.. data:: mem32 + + Read/write 32 bits of memory. + +Use subscript notation ``[...]`` to index these objects with the address of +interest. Note that the address is the byte address, regardless of the size of +memory being accessed. + +Example use (registers are specific to an stm32 microcontroller): + +.. code-block:: python3 + + import machine + from micropython import const + + GPIOA = const(0x48000000) + GPIO_BSRR = const(0x18) + GPIO_IDR = const(0x10) + + # set PA2 high + machine.mem32[GPIOA + GPIO_BSRR] = 1 << 2 + + # read PA3 + value = (machine.mem32[GPIOA + GPIO_IDR] >> 3) & 1 + Reset related functions ----------------------- @@ -48,6 +86,23 @@ Reset related functions Interrupt related functions --------------------------- +The following functions allow control over interrupts. Some systems require +interrupts to operate correctly so disabling them for long periods may +compromise core functionality, for example watchdog timers may trigger +unexpectedly. Interrupts should only be disabled for a minimum amount of time +and then re-enabled to their previous state. For example:: + + import machine + + # Disable interrupts + state = machine.disable_irq() + + # Do a small amount of time-critical work here + + # Enable interrupts + machine.enable_irq(state) + + .. function:: disable_irq() Disable interrupt requests. @@ -199,11 +254,12 @@ Classes machine.Pin.rst machine.Signal.rst machine.ADC.rst + machine.ADCBlock.rst machine.PWM.rst machine.UART.rst machine.SPI.rst machine.I2C.rst - machine.I2S.rst + machine.I2S.rst machine.RTC.rst machine.Timer.rst machine.WDT.rst diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst index 7106a1a2ff16d..b17dfa9a75a48 100644 --- a/docs/library/micropython.rst +++ b/docs/library/micropython.rst @@ -9,7 +9,7 @@ Functions .. function:: const(expr) - Used to declare that the expression is a constant so that the compile can + Used to declare that the expression is a constant so that the compiler can optimise it. The use of this function should be as follows:: from micropython import const diff --git a/docs/library/neopixel.rst b/docs/library/neopixel.rst index 1b37f088baa71..edcbc9345c304 100644 --- a/docs/library/neopixel.rst +++ b/docs/library/neopixel.rst @@ -6,10 +6,10 @@ This module provides a driver for WS2818 / NeoPixel LEDs. -.. note:: This module is only included by default on the ESP8266 and ESP32 - ports. On STM32 / Pyboard, you can `download the module - `_ - and copy it to the filesystem. +.. note:: This module is only included by default on the ESP8266, ESP32 and RP2 + ports. On STM32 / Pyboard and others, you can either install the + ``neopixel`` package using :term:`mip`, or you can download the module + directly from :term:`micropython-lib` and copy it to the filesystem. class NeoPixel -------------- diff --git a/docs/library/network.CC3K.rst b/docs/library/network.CC3K.rst deleted file mode 100644 index 41d3fb437e992..0000000000000 --- a/docs/library/network.CC3K.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. currentmodule:: network -.. _network.CC3K: - -class CC3K -- control CC3000 WiFi modules -========================================= - -This class provides a driver for CC3000 WiFi modules. Example usage:: - - import network - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - nic.connect('your-ssid', 'your-password') - while not nic.isconnected(): - pyb.delay(50) - print(nic.ifconfig()) - - # now use socket as usual - ... - -For this example to work the CC3000 module must have the following connections: - - - MOSI connected to Y8 - - MISO connected to Y7 - - CLK connected to Y6 - - CS connected to Y5 - - VBEN connected to Y4 - - IRQ connected to Y3 - -It is possible to use other SPI buses and other pins for CS, VBEN and IRQ. - -Constructors ------------- - -.. class:: CC3K(spi, pin_cs, pin_en, pin_irq) - - Create a CC3K driver object, initialise the CC3000 module using the given SPI bus - and pins, and return the CC3K object. - - Arguments are: - - - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is - connected to (the MOSI, MISO and CLK pins). - - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. - - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. - - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin. - - All of these objects will be initialised by the driver, so there is no need to - initialise them yourself. For example, you can use:: - - nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) - -Methods -------- - -.. method:: CC3K.connect(ssid, key=None, *, security=WPA2, bssid=None) - - Connect to a WiFi access point using the given SSID, and other security - parameters. - -.. method:: CC3K.disconnect() - - Disconnect from the WiFi access point. - -.. method:: CC3K.isconnected() - - Returns True if connected to a WiFi access point and has a valid IP address, - False otherwise. - -.. method:: CC3K.ifconfig() - - Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, - MAC address, SSID). - -.. method:: CC3K.patch_version() - - Return the version of the patch program (firmware) on the CC3000. - -.. method:: CC3K.patch_program('pgm') - - Upload the current firmware to the CC3000. You must pass 'pgm' as the first - argument in order for the upload to proceed. - -Constants ---------- - -.. data:: CC3K.WEP -.. data:: CC3K.WPA -.. data:: CC3K.WPA2 - - security type to use diff --git a/docs/library/network.LAN.rst b/docs/library/network.LAN.rst new file mode 100644 index 0000000000000..375e02cefecd0 --- /dev/null +++ b/docs/library/network.LAN.rst @@ -0,0 +1,95 @@ +.. currentmodule:: network +.. _network.LAN: + +class LAN -- control an Ethernet module +======================================= + +This class allows you to control the Ethernet interface. The PHY hardware type is board-specific. + +Example usage:: + + import network + nic = network.LAN(0) + print(nic.ifconfig()) + + # now use socket as usual + ... + + +Constructors +------------ + +.. class:: LAN(id, *, phy_type=, phy_addr=, ref_clk_mode=) + + Create a LAN driver object, initialise the LAN module using the given + PHY driver name, and return the LAN object. + + Arguments are: + + - *id* is the number of the Ethernet port, either 0 or 1. + - *phy_type* is the name of the PHY driver. For most board the on-board PHY has to be used and + is the default. Suitable values are port specific. + - *phy_addr* specifies the address of the PHY interface. As with *phy_type*, the hardwired value has + to be used for most boards and that value is the default. + - *ref_clk_mode* specifies, whether the data clock is provided by the Ethernet controller or + the PYH interface. + The default value is the one that matches the board. If set to ``LAN.OUT`` or ``Pin.OUT`` + or ``True``, the clock is driven by the Ethernet controller, if set to ``LAN.IN`` + or ``Pin.IN`` or ``False``, the clock is driven by the PHY interface. + + For example, with the Seeed Arch Mix board you can use:: + + nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=1, ref_clk_mode=Pin.IN) + +Methods +------- + +.. method:: LAN.active([state]) + + With a parameter, it sets the interface active if *state* is true, otherwise it + sets it inactive. + Without a parameter, it returns the state. + +.. method:: LAN.isconnected() + + Returns ``True`` if the physical Ethernet link is connected and up. + Returns ``False`` otherwise. + +.. method:: LAN.status() + + Returns the LAN status. + +.. method:: LAN.ifconfig([(ip, subnet, gateway, dns)]) + + Get/set IP address, subnet mask, gateway and DNS. + + When called with no arguments, this method returns a 4-tuple with the above information. + + To set the above values, pass a 4-tuple with the required information. For example:: + + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + +.. method:: LAN.config(config_parameters) + + Sets or gets parameters of the LAN interface. The only parameter that can be + retrieved is the MAC address, using:: + + mac = LAN.config("mac") + + The parameters that can be set are: + + - ``trace=n`` sets trace levels; suitable values are: + + - 2: trace TX + - 4: trace RX + - 8: full trace + + - ``low_power=bool`` sets or clears low power mode, valid values being ``False`` + or ``True``. + + +Specific LAN class implementations +---------------------------------- + +On the mimxrt port, suitable values for the *phy_type* constructor argument are: +``PHY_KSZ8081``, ``PHY_DP83825``, ``PHY_DP83848``, ``PHY_LAN8720``, ``PHY_RTL8211F``. diff --git a/docs/library/network.WIZNET5K.rst b/docs/library/network.WIZNET5K.rst index 9e2c40f7f3932..c13d43a376ece 100644 --- a/docs/library/network.WIZNET5K.rst +++ b/docs/library/network.WIZNET5K.rst @@ -6,7 +6,7 @@ class WIZNET5K -- control WIZnet5x00 Ethernet modules This class allows you to control WIZnet5x00 Ethernet adaptors based on the W5200 and W5500 chipsets. The particular chipset that is supported -by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K +by the firmware is selected at compile-time via the MICROPY_PY_NETWORK_WIZNET5K option. Example usage:: diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst index 72091d0ea5a0f..68cd49769afff 100644 --- a/docs/library/network.WLAN.rst +++ b/docs/library/network.WLAN.rst @@ -10,7 +10,7 @@ This class provides a driver for WiFi network processors. Example usage:: # enable station interface and connect to WiFi access point nic = network.WLAN(network.STA_IF) nic.active(True) - nic.connect('your-ssid', 'your-password') + nic.connect('your-ssid', 'your-key') # now use sockets as usual Constructors @@ -32,9 +32,9 @@ Methods argument is passed. Otherwise, query current state if no argument is provided. Most other methods require active interface. -.. method:: WLAN.connect(ssid=None, password=None, *, bssid=None) +.. method:: WLAN.connect(ssid=None, key=None, *, bssid=None) - Connect to the specified wireless network, using the specified password. + Connect to the specified wireless network, using the specified key. If *bssid* is given then the connection will be restricted to the access-point with that MAC address (the *ssid* must also be specified in this case). @@ -52,12 +52,12 @@ Methods Scanning is only possible on STA interface. Returns list of tuples with the information about WiFi access points: - (ssid, bssid, channel, RSSI, authmode, hidden) + (ssid, bssid, channel, RSSI, security, hidden) *bssid* is hardware address of an access point, in binary form, returned as bytes object. You can use `binascii.hexlify()` to convert it to ASCII form. - There are five values for authmode: + There are five values for security: * 0 -- open * 1 -- WEP @@ -112,10 +112,10 @@ Methods multiple parameters can be set at once. For querying, parameters name should be quoted as a string, and only one parameter can be queries at time:: - # Set WiFi access point name (formally known as ESSID) and WiFi channel - ap.config(essid='My AP', channel=11) + # Set WiFi access point name (formally known as SSID) and WiFi channel + ap.config(ssid='My AP', channel=11) # Query params one by one - print(ap.config('essid')) + print(ap.config('ssid')) print(ap.config('channel')) Following are commonly supported parameters (availability of a specific parameter @@ -125,11 +125,28 @@ Methods Parameter Description ============= =========== mac MAC address (bytes) - essid WiFi access point name (string) + ssid WiFi access point name (string) channel WiFi channel (integer) - hidden Whether ESSID is hidden (boolean) - authmode Authentication mode supported (enumeration, see module constants) - password Access password (string) - dhcp_hostname The DHCP hostname to use + hidden Whether SSID is hidden (boolean) + security Security protocol supported (enumeration, see module constants) + key Access key (string) + hostname The hostname that will be sent to DHCP (STA interfaces) and mDNS (if supported, both STA and AP). (Deprecated, use :func:`network.hostname` instead) reconnects Number of reconnect attempts to make (integer, 0=none, -1=unlimited) + txpower Maximum transmit power in dBm (integer or float) + pm WiFi Power Management setting (see below for allowed values) ============= =========== + +Constants +--------- + +.. data:: WLAN.PM_PERFORMANCE + WLAN.PM_POWERSAVE + WLAN.PM_NONE + + Allowed values for the ``WLAN.config(pm=...)`` network interface parameter: + + * ``PM_PERFORMANCE``: enable WiFi power management to balance power + savings and WiFi performance + * ``PM_POWERSAVE``: enable WiFi power management with additional power + savings and reduced WiFi performance + * ``PM_NONE``: disable wifi power management diff --git a/docs/library/network.rst b/docs/library/network.rst index 1bd7e303bb636..cc508842942a5 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -89,7 +89,7 @@ parameter should be `id`. network media, there are different variants of predefined/ recommended tuple formats, among them: - * WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There + * WiFi: (ssid, bssid, channel, RSSI, security, hidden). There may be further fields, specific to a particular device. The function may accept additional keyword arguments to filter scan @@ -133,10 +133,10 @@ parameter should be `id`. querying, a parameter name should be quoted as a string, and only one parameter can be queried at a time:: - # Set WiFi access point name (formally known as ESSID) and WiFi channel - ap.config(essid='My AP', channel=11) + # Set WiFi access point name (formally known as SSID) and WiFi channel + ap.config(ssid='My AP', channel=11) # Query params one by one - print(ap.config('essid')) + print(ap.config('ssid')) print(ap.config('channel')) Specific network class implementations @@ -150,20 +150,58 @@ provide a way to control networking interfaces of various kinds. network.WLAN.rst network.WLANWiPy.rst - network.CC3K.rst network.WIZNET5K.rst + network.LAN.rst Network functions ================= The following are functions available in the network module. +.. function:: country([code]) + + Get or set the two-letter ISO 3166-1 Alpha-2 country code to be used for + radio compliance. + + If the *code* parameter is provided, the country will be set to this value. + If the function is called without parameters, it returns the current + country. + + The default code ``"XX"`` represents the "worldwide" region. + +.. function:: hostname([name]) + + Get or set the hostname that will identify this device on the network. It will + be used by all interfaces. + + This hostname is used for: + * Sending to the DHCP server in the client request. (If using DHCP) + * Broadcasting via mDNS. (If enabled) + + If the *name* parameter is provided, the hostname will be set to this value. + If the function is called without parameters, it returns the current + hostname. + + A change in hostname is typically only applied during connection. For DHCP + this is because the hostname is part of the DHCP client request, and the + implementation of mDNS in most ports only initialises the hostname once + during connection. For this reason, you must set the hostname before + activating/connecting your network interfaces. + + The length of the hostname is limited to 32 characters. + :term:`MicroPython ports ` may choose to set a lower + limit for memory reasons. If the given name does not fit, a `ValueError` + is raised. + + The default hostname is typically the name of the board. + .. function:: phy_mode([mode]) Get or set the PHY mode. - If the *mode* parameter is provided, sets the mode to its value. If - the function is called without parameters, returns the current mode. + If the *mode* parameter is provided, the PHY mode will be set to this value. + If the function is called without parameters, it returns the current PHY + mode. The possible modes are defined as constants: * ``MODE_11B`` -- IEEE 802.11b, diff --git a/docs/library/os.rst b/docs/library/os.rst index 19652ee2bc5ef..710875e34c39b 100644 --- a/docs/library/os.rst +++ b/docs/library/os.rst @@ -86,7 +86,7 @@ Filesystem access .. function:: statvfs(path) - Get the status of a fileystem. + Get the status of a filesystem. Returns a tuple with the filesystem information in the following order: @@ -136,192 +136,30 @@ Terminal redirection and duplication Filesystem mounting ------------------- -Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple -"real" filesystems within this VFS. Filesystem objects can be mounted at either -the root of the VFS, or at a subdirectory that lives in the root. This allows -dynamic and flexible configuration of the filesystem that is seen by Python -programs. Ports that have this functionality provide the :func:`mount` and -:func:`umount` functions, and possibly various filesystem implementations -represented by VFS classes. +The following functions and classes have been moved to the :mod:`vfs` module. +They are provided in this module only for backwards compatibility and will be +removed in version 2 of MicroPython. .. function:: mount(fsobj, mount_point, *, readonly) - Mount the filesystem object *fsobj* at the location in the VFS given by the - *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` - method, or a block device. If it's a block device then the filesystem type - is automatically detected (an exception is raised if no filesystem was - recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, - or ``'/'`` to mount it at a subdirectory under the root. - - If *readonly* is ``True`` then the filesystem is mounted read-only. - - During the mount process the method ``mount()`` is called on the filesystem - object. - - Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. + See `vfs.mount`. .. function:: umount(mount_point) - Unmount a filesystem. *mount_point* can be a string naming the mount location, - or a previously-mounted filesystem object. During the unmount process the - method ``umount()`` is called on the filesystem object. - - Will raise ``OSError(EINVAL)`` if *mount_point* is not found. + See `vfs.umount`. .. class:: VfsFat(block_dev) - Create a filesystem object that uses the FAT filesystem format. Storage of - the FAT filesystem is provided by *block_dev*. - Objects created by this constructor can be mounted using :func:`mount`. - - .. staticmethod:: mkfs(block_dev) - - Build a FAT filesystem on *block_dev*. + See `vfs.VfsFat`. .. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32) - Create a filesystem object that uses the `littlefs v1 filesystem format`_. - Storage of the littlefs filesystem is provided by *block_dev*, which must - support the :ref:`extended interface `. - Objects created by this constructor can be mounted using :func:`mount`. - - See :ref:`filesystem` for more information. - - .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) - - Build a Lfs1 filesystem on *block_dev*. - - .. note:: There are reports of littlefs v1 failing in certain situations, - for details see `littlefs issue 347`_. + See `vfs.VfsLfs1`. .. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True) - Create a filesystem object that uses the `littlefs v2 filesystem format`_. - Storage of the littlefs filesystem is provided by *block_dev*, which must - support the :ref:`extended interface `. - Objects created by this constructor can be mounted using :func:`mount`. + See `vfs.VfsLfs2`. + +.. class:: VfsPosix(root=None) - The *mtime* argument enables modification timestamps for files, stored using - littlefs attributes. This option can be disabled or enabled differently each - mount time and timestamps will only be added or updated if *mtime* is enabled, - otherwise the timestamps will remain untouched. Littlefs v2 filesystems without - timestamps will work without reformatting and timestamps will be added - transparently to existing files once they are opened for writing. When *mtime* - is enabled `os.stat` on files without timestamps will return 0 for the timestamp. - - See :ref:`filesystem` for more information. - - .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) - - Build a Lfs2 filesystem on *block_dev*. - - .. note:: There are reports of littlefs v2 failing in certain situations, - for details see `littlefs issue 295`_. - -.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1 -.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs -.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 -.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 - -Block devices -------------- - -A block device is an object which implements the block protocol. This enables a -device to support MicroPython filesystems. The physical hardware is represented -by a user defined class. The :class:`AbstractBlockDev` class is a template for -the design of such a class: MicroPython does not actually provide that class, -but an actual block device class must implement the methods described below. - -A concrete implementation of this class will usually allow access to the -memory-like functionality of a piece of hardware (like flash memory). A block -device can be formatted to any supported filesystem and mounted using ``os`` -methods. - -See :ref:`filesystem` for example implementations of block devices using the -two variants of the block protocol described below. - -.. _block-device-interface: - -Simple and extended interface -............................. - -There are two compatible signatures for the ``readblocks`` and ``writeblocks`` -methods (see below), in order to support a variety of use cases. A given block -device may implement one form or the other, or both at the same time. The second -form (with the offset parameter) is referred to as the "extended interface". - -Some filesystems (such as littlefs) that require more control over write -operations, for example writing to sub-block regions without erasing, may require -that the block device supports the extended interface. - -.. class:: AbstractBlockDev(...) - - Construct a block device object. The parameters to the constructor are - dependent on the specific block device. - - .. method:: readblocks(block_num, buf) - readblocks(block_num, buf, offset) - - The first form reads aligned, multiples of blocks. - Starting at the block given by the index *block_num*, read blocks from - the device into *buf* (an array of bytes). - The number of blocks to read is given by the length of *buf*, - which will be a multiple of the block size. - - The second form allows reading at arbitrary locations within a block, - and arbitrary lengths. - Starting at block index *block_num*, and byte offset within that block - of *offset*, read bytes from the device into *buf* (an array of bytes). - The number of bytes to read is given by the length of *buf*. - - .. method:: writeblocks(block_num, buf) - writeblocks(block_num, buf, offset) - - The first form writes aligned, multiples of blocks, and requires that the - blocks that are written to be first erased (if necessary) by this method. - Starting at the block given by the index *block_num*, write blocks from - *buf* (an array of bytes) to the device. - The number of blocks to write is given by the length of *buf*, - which will be a multiple of the block size. - - The second form allows writing at arbitrary locations within a block, - and arbitrary lengths. Only the bytes being written should be changed, - and the caller of this method must ensure that the relevant blocks are - erased via a prior ``ioctl`` call. - Starting at block index *block_num*, and byte offset within that block - of *offset*, write bytes from *buf* (an array of bytes) to the device. - The number of bytes to write is given by the length of *buf*. - - Note that implementations must never implicitly erase blocks if the offset - argument is specified, even if it is zero. - - .. method:: ioctl(op, arg) - - Control the block device and query its parameters. The operation to - perform is given by *op* which is one of the following integers: - - - 1 -- initialise the device (*arg* is unused) - - 2 -- shutdown the device (*arg* is unused) - - 3 -- sync the device (*arg* is unused) - - 4 -- get a count of the number of blocks, should return an integer - (*arg* is unused) - - 5 -- get the number of bytes in a block, should return an integer, - or ``None`` in which case the default value of 512 is used - (*arg* is unused) - - 6 -- erase a block, *arg* is the block number to erase - - As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs - ``ioctl(6, ...)`` must also be intercepted. The need for others is - hardware dependent. - - Prior to any call to ``writeblocks(block, ...)`` littlefs issues - ``ioctl(6, block)``. This enables a device driver to erase the block - prior to a write if the hardware requires it. Alternatively a driver - might intercept ``ioctl(6, block)`` and return 0 (success). In this case - the driver assumes responsibility for detecting the need for erasure. - - Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. - Consequently an implementation can ignore unused values of ``op``. Where - ``op`` is intercepted, the return value for operations 4 and 5 are as - detailed above. Other operations should return 0 on success and non-zero - for failure, with the value returned being an ``OSError`` errno code. + See `vfs.VfsPosix`. diff --git a/docs/library/platform.rst b/docs/library/platform.rst new file mode 100644 index 0000000000000..c091477d84cb1 --- /dev/null +++ b/docs/library/platform.rst @@ -0,0 +1,38 @@ +:mod:`platform` -- access to underlying platform’s identifying data +=================================================================== + +.. module:: platform + :synopsis: access to underlying platform’s identifying data + +|see_cpython_module| :mod:`python:platform`. + +This module tries to retrieve as much platform-identifying data as possible. It +makes this information available via function APIs. + +Functions +--------- + +.. function:: platform() + + Returns a string identifying the underlying platform. This string is composed + of several substrings in the following order, delimited by dashes (``-``): + + - the name of the platform system (e.g. Unix, Windows or MicroPython) + - the MicroPython version + - the architecture of the platform + - the version of the underlying platform + - the concatenation of the name of the libc that MicroPython is linked to + and its corresponding version. + + For example, this could be + ``"MicroPython-1.20.0-xtensa-IDFv4.2.4-with-newlib3.0.0"``. + +.. function:: python_compiler() + + Returns a string identifying the compiler used for compiling MicroPython. + +.. function:: libc_ver() + + Returns a tuple of strings *(lib, version)*, where *lib* is the name of the + libc that MicroPython is linked to, and *version* the corresponding version + of this libc. diff --git a/docs/library/pyb.ADC.rst b/docs/library/pyb.ADC.rst index 1b16e0c2fcccb..9410e5194bf89 100644 --- a/docs/library/pyb.ADC.rst +++ b/docs/library/pyb.ADC.rst @@ -23,7 +23,7 @@ Usage:: Constructors ------------ -.. class:: pyb.ADC(pin) +.. class:: ADC(pin) Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. diff --git a/docs/library/pyb.Accel.rst b/docs/library/pyb.Accel.rst index d5c0ca8634598..7f5c60f4cea5f 100644 --- a/docs/library/pyb.Accel.rst +++ b/docs/library/pyb.Accel.rst @@ -16,7 +16,7 @@ Raw values are between -32 and 31. Constructors ------------ -.. class:: pyb.Accel() +.. class:: Accel() Create and return an accelerometer object. diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst index bcaeeba9df955..57a85d54b7714 100644 --- a/docs/library/pyb.CAN.rst +++ b/docs/library/pyb.CAN.rst @@ -4,13 +4,12 @@ class CAN -- controller area network communication bus ====================================================== -CAN implements the standard CAN communications protocol. At -the physical level it consists of 2 lines: RX and TX. Note that -to connect the pyboard to a CAN bus you must use a CAN transceiver -to convert the CAN logic signals from the pyboard to the correct +CAN implements support for classic CAN (available on F4, F7 MCUs) and CAN FD (H7 series) controllers. +At the physical level CAN bus consists of 2 lines: RX and TX. Note that to connect the pyboard to a +CAN bus you must use a CAN transceiver to convert the CAN logic signals from the pyboard to the correct voltage levels on the bus. -Example usage (works without anything connected):: +Example usage for classic CAN controller in Loopback (transceiver-less) mode:: from pyb import CAN can = CAN(1, CAN.LOOPBACK) @@ -18,11 +17,21 @@ Example usage (works without anything connected):: can.send('message!', 123) # send a message with id 123 can.recv(0) # receive message on FIFO 0 +Example usage for CAN FD controller with all of the possible options enabled:: + + # FD frame + BRS mode + Extended frame ID. 500 Kbit/s for arbitration phase, 1Mbit/s for data phase. + can = CAN(1, CAN.NORMAL, baudrate=500_000, brs_baudrate=1_000_000, sample_point=80) + can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF)) + can.send('a'*64, 0xFFFF, fdf=True, brs=True, extframe=True) + can.recv(0) + +The following CAN module functions and their arguments are available +for both classic and FD CAN controllers, unless otherwise stated. Constructors ------------ -.. class:: pyb.CAN(bus, ...) +.. class:: CAN(bus, ...) Construct a CAN object on the given bus. *bus* can be 1-2, or ``'YA'`` or ``'YB'``. With no additional parameters, the CAN object is created but not @@ -35,43 +44,48 @@ Constructors - ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)`` - ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)`` -Class Methods -------------- -.. classmethod:: CAN.initfilterbanks(nr) - - Reset and disable all filter banks and assign how many banks should be available for CAN(1). - - STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. - This function configures how many filter banks should be assigned to each. *nr* is the number of banks - that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). - At boot, 14 banks are assigned to each controller. - Methods ------- -.. method:: CAN.init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False, baudrate=0, sample_point=75) +.. method:: CAN.init(mode, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False, baudrate=0, sample_point=75, + num_filter_banks=14, brs_sjw=1, brs_bs1=8, brs_bs2=3, brs_baudrate=0, brs_sample_point=75) Initialise the CAN bus with the given parameters: - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK - - if *extframe* is True then the bus uses extended identifiers in the frames - (29 bits); otherwise it uses standard 11 bit identifiers - - *prescaler* is used to set the duration of 1 time quanta; the time quanta - will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler - - *sjw* is the resynchronisation jump width in units of the time quanta; - it can be 1, 2, 3, 4 - - *bs1* defines the location of the sample point in units of the time quanta; - it can be between 1 and 1024 inclusive - - *bs2* defines the location of the transmit point in units of the time quanta; - it can be between 1 and 16 inclusive + - *prescaler* is the value by which the CAN input clock is divided to generate the + nominal bit time quanta. The prescaler can be a value between 1 and 1024 inclusive + for classic CAN, and between 1 and 512 inclusive for CAN FD. + - *sjw* is the resynchronisation jump width in units of time quanta for nominal bits; + it can be a value between 1 and 4 inclusive for classic CAN, and between 1 and 128 inclusive for CAN FD. + - *bs1* defines the location of the sample point in units of the time quanta for nominal bits; + it can be a value between 1 and 16 inclusive for classic CAN, and between 2 and 256 inclusive for CAN FD. + - *bs2* defines the location of the transmit point in units of the time quanta for nominal bits; + it can be a value between 1 and 8 inclusive for classic CAN, and between 2 and 128 inclusive for CAN FD. - *auto_restart* sets whether the controller will automatically try and restart communications after entering the bus-off state; if this is disabled then :meth:`~CAN.restart()` can be used to leave the bus-off state - *baudrate* if a baudrate other than 0 is provided, this function will try to automatically - calculate a CAN bit-timing (overriding *prescaler*, *bs1* and *bs2*) that satisfies both - the baudrate and the desired *sample_point*. - - *sample_point* given in a percentage of the bit time, the *sample_point* specifies the position - of the last bit sample with respect to the whole bit time. The default *sample_point* is 75%. + calculate the CAN nominal bit time (overriding *prescaler*, *bs1* and *bs2*) that satisfies + both the baudrate and the desired *sample_point*. + - *sample_point* given in a percentage of the nominal bit time, the *sample_point* specifies the position + of the bit sample with respect to the whole nominal bit time. The default *sample_point* is 75%. + - *num_filter_banks* for classic CAN, this is the number of banks that will be assigned to CAN(1), + the rest of the 28 are assigned to CAN(2). + - *brs_prescaler* is the value by which the CAN FD input clock is divided to generate the + data bit time quanta. The prescaler can be a value between 1 and 32 inclusive. + - *brs_sjw* is the resynchronisation jump width in units of time quanta for data bits; + it can be a value between 1 and 16 inclusive + - *brs_bs1* defines the location of the sample point in units of the time quanta for data bits; + it can be a value between 1 and 32 inclusive + - *brs_bs2* defines the location of the transmit point in units of the time quanta for data bits; + it can be a value between 1 and 16 inclusive + - *brs_baudrate* if a baudrate other than 0 is provided, this function will try to automatically + calculate the CAN data bit time (overriding *brs_prescaler*, *brs_bs1* and *brs_bs2*) that satisfies + both the baudrate and the desired *brs_sample_point*. + - *brs_sample_point* given in a percentage of the data bit time, the *brs_sample_point* specifies the position + of the bit sample with respect to the whole data bit time. The default *brs_sample_point* is 75%. + The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1); @@ -140,17 +154,17 @@ Methods - number of pending RX messages on fifo 0 - number of pending RX messages on fifo 1 -.. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr) +.. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr, extframe=False) Configure a filter bank: - - *bank* is the filter bank that is to be configured. - - *mode* is the mode the filter should operate in. + - *bank* is the classic CAN controller filter bank, or CAN FD filter index, to configure. + - *mode* is the mode the filter should operate in, see the tables below. - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. +-----------+---------------------------------------------------------+ - |*mode* |contents of *params* array | + |*mode* |Contents of *params* array for classic CAN controller | +===========+=========================================================+ |CAN.LIST16 |Four 16 bit ids that will be accepted | +-----------+---------------------------------------------------------+ @@ -165,10 +179,20 @@ Methods |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| +-----------+---------------------------------------------------------+ - - *rtr* is an array of booleans that states if a filter should accept a - remote transmission request message. If this argument is not given - then it defaults to ``False`` for all entries. The length of the array - depends on the *mode* argument. + +-----------+---------------------------------------------------------+ + |*mode* |Contents of *params* array for CAN FD controller | + +===========+=========================================================+ + |CAN.RANGE |Two ids that represent a range of accepted ids. | + +-----------+---------------------------------------------------------+ + |CAN.DUAL |Two ids that will be accepted. For example (1, 2) | + +-----------+---------------------------------------------------------+ + |CAN.MASK |One filter ID and a mask. For example (0x111, 0x7FF) | + +-----------+---------------------------------------------------------+ + + - *rtr* For classic CAN controllers, this is an array of booleans that states if + a filter should accept a remote transmission request message. If this argument + is not given then it defaults to ``False`` for all entries. The length of the + array depends on the *mode* argument. For CAN FD, this argument is ignored. +-----------+----------------------+ |*mode* |length of *rtr* array | @@ -182,11 +206,17 @@ Methods |CAN.MASK32 |1 | +-----------+----------------------+ -.. method:: CAN.clearfilter(bank) + - *extframe* If True the frame will have an extended identifier (29 bits), + otherwise a standard identifier (11 bits) is used. + + +.. method:: CAN.clearfilter(bank, extframe=False) Clear and disables a filter bank: - - *bank* is the filter bank that is to be cleared. + - *bank* is the classic CAN controller filter bank, or CAN FD filter index, to clear. + - *extframe* For CAN FD controllers, if True, clear an extended filter (configured with extframe=True), + otherwise the clear a standard identifier (configured with extframe=False). .. method:: CAN.any(fifo) @@ -200,32 +230,33 @@ Methods - *list* is an optional list object to be used as the return value - *timeout* is the timeout in milliseconds to wait for the receive. - Return value: A tuple containing four values. + Return value: A tuple containing five values. - The id of the message. + - A boolean that indicates if the message ID is standard or extended. - A boolean that indicates if the message is an RTR message. - The FMI (Filter Match Index) value. - An array containing the data. If *list* is ``None`` then a new tuple will be allocated, as well as a new - bytes object to contain the data (as the fourth element in the tuple). + bytes object to contain the data (as the fifth element in the tuple). - If *list* is not ``None`` then it should be a list object with a least four - elements. The fourth element should be a memoryview object which is created + If *list* is not ``None`` then it should be a list object with a least five + elements. The fifth element should be a memoryview object which is created from either a bytearray or an array of type 'B' or 'b', and this array must have enough room for at least 8 bytes. The list object will then be - populated with the first three return values above, and the memoryview object + populated with the first four return values above, and the memoryview object will be resized inplace to the size of the data and filled in with that data. The same list and memoryview objects can be reused in subsequent calls to this method, providing a way of receiving data without using the heap. For example:: buf = bytearray(8) - lst = [0, 0, 0, memoryview(buf)] + lst = [0, 0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call can.recv(0, lst) -.. method:: CAN.send(data, id, *, timeout=0, rtr=False) +.. method:: CAN.send(data, id, *, timeout=0, rtr=False, extframe=False, fdf=False, brs=False) Send a message on the bus: @@ -236,6 +267,13 @@ Methods a remote transmission request. If *rtr* is True then only the length of *data* is used to fill in the DLC slot of the frame; the actual bytes in *data* are unused. + - *extframe* if True the frame will have an extended identifier (29 bits), + otherwise a standard identifier (11 bits) is used. + - *fdf* for CAN FD controllers, if set to True, the frame will have an FD + frame format, which supports data payloads up to 64 bytes. + - *brs* for CAN FD controllers, if set to True, the bitrate switching mode + is enabled, in which the data phase is transmitted at a different bitrate. + See :meth:`CAN.init` for the data bit timing configuration parameters. If timeout is 0 the message is placed in a buffer in one of three hardware buffers and the method returns immediately. If all three buffers are in use @@ -302,4 +340,10 @@ Constants CAN.LIST32 CAN.MASK32 - The operation mode of a filter used in :meth:`~CAN.setfilter()`. + The operation mode of a filter used in :meth:`~CAN.setfilter()` for classic CAN. + +.. data:: CAN.DUAL + CAN.RANGE + CAN.MASK + + The operation mode of a filter used in :meth:`~CAN.setfilter()` for CAN FD. diff --git a/docs/library/pyb.DAC.rst b/docs/library/pyb.DAC.rst index bf07119ada166..aa79342895eb3 100644 --- a/docs/library/pyb.DAC.rst +++ b/docs/library/pyb.DAC.rst @@ -49,7 +49,7 @@ To output a continuous sine-wave at 12-bit resolution:: Constructors ------------ -.. class:: pyb.DAC(port, bits=8, *, buffering=None) +.. class:: DAC(port, bits=8, *, buffering=None) Construct a new DAC object. @@ -122,3 +122,15 @@ Methods dac2 = DAC(2) dac1.write_timed(buf1, pyb.Timer(6, freq=100), mode=DAC.CIRCULAR) dac2.write_timed(buf2, pyb.Timer(7, freq=200), mode=DAC.CIRCULAR) + +Constants +--------- + +.. data:: DAC.NORMAL + + NORMAL mode does a single transmission of the waveform in the data buffer, + +.. data:: DAC.CIRCULAR + + CIRCULAR mode does a transmission of the waveform in the data buffer, and wraps around + to the start of the data buffer every time it reaches the end of the table. diff --git a/docs/library/pyb.ExtInt.rst b/docs/library/pyb.ExtInt.rst index 7741cc51e2381..f49fbb1a14913 100644 --- a/docs/library/pyb.ExtInt.rst +++ b/docs/library/pyb.ExtInt.rst @@ -51,7 +51,7 @@ usrsw.h for an example of using this. Constructors ------------ -.. class:: pyb.ExtInt(pin, mode, pull, callback) +.. class:: ExtInt(pin, mode, pull, callback) Create an ExtInt object: diff --git a/docs/library/pyb.Flash.rst b/docs/library/pyb.Flash.rst index 01b3a0ac9e0a3..562bcf1e2466e 100644 --- a/docs/library/pyb.Flash.rst +++ b/docs/library/pyb.Flash.rst @@ -15,7 +15,7 @@ application. Constructors ------------ -.. class:: pyb.Flash() +.. class:: Flash() Create and return a block device that represents the flash device presented to the USB mass storage interface. @@ -25,7 +25,7 @@ Constructors This constructor is deprecated and will be removed in a future version of MicroPython. -.. class:: pyb.Flash(*, start=-1, len=-1) +.. class:: Flash(*, start=-1, len=-1) :noindex: Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining size of the device. @@ -43,7 +43,7 @@ Methods These methods implement the simple and :ref:`extended ` block protocol defined by - :class:`os.AbstractBlockDev`. + :class:`vfs.AbstractBlockDev`. Hardware Note ------------- diff --git a/docs/library/pyb.I2C.rst b/docs/library/pyb.I2C.rst index f60b506861c3a..71d043aa6d4f9 100644 --- a/docs/library/pyb.I2C.rst +++ b/docs/library/pyb.I2C.rst @@ -56,7 +56,7 @@ Master also has other methods:: Constructors ------------ -.. class:: pyb.I2C(bus, ...) +.. class:: I2C(bus, ...) Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or 'Y'. With no additional parameters, the I2C object is created but not @@ -96,6 +96,10 @@ Methods that DMA transfers have more precise timing but currently do not handle bus errors properly) + The actual clock frequency may be lower than the requested frequency. + This is dependent on the platform hardware. The actual rate may be determined + by printing the I2C object. + .. method:: I2C.is_ready(addr) Check if an I2C device responds to the given address. Only valid when in controller mode. diff --git a/docs/library/pyb.LCD.rst b/docs/library/pyb.LCD.rst index 018902ca6896a..ba394d36a8318 100644 --- a/docs/library/pyb.LCD.rst +++ b/docs/library/pyb.LCD.rst @@ -41,7 +41,7 @@ For example, to make a bouncing dot, try:: Constructors ------------ -.. class:: pyb.LCD(skin_position) +.. class:: LCD(skin_position) Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and should match the position where the LCD pyskin is plugged in. diff --git a/docs/library/pyb.LED.rst b/docs/library/pyb.LED.rst index d3ab965e7e7c8..de07c7d1c3454 100644 --- a/docs/library/pyb.LED.rst +++ b/docs/library/pyb.LED.rst @@ -10,7 +10,7 @@ The LED object controls an individual LED (Light Emitting Diode). Constructors ------------ -.. class:: pyb.LED(id) +.. class:: LED(id) Create an LED object associated with the given LED: diff --git a/docs/library/pyb.Pin.rst b/docs/library/pyb.Pin.rst index 6465653f74cba..b93924508b943 100644 --- a/docs/library/pyb.Pin.rst +++ b/docs/library/pyb.Pin.rst @@ -58,23 +58,13 @@ an ordinal pin number: You can set ``pyb.Pin.debug(True)`` to get some debug information about how a particular object gets mapped to a pin. -When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, -that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND -respectively (except pin Y5 which has 11k Ohm resistors). - -Now every time a falling edge is seen on the gpio pin, the callback will be -executed. Caution: mechanical push buttons have "bounce" and pushing or -releasing a switch will often generate multiple edges. -See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed -explanation, along with various techniques for debouncing. - All pin objects go through the pin mapper to come up with one of the gpio pins. Constructors ------------ -.. class:: pyb.Pin(id, ...) +.. class:: Pin(id, ...) Create a new Pin object associated with the id. If additional arguments are given, they are used to initialise the pin. See :meth:`pin.init`. @@ -98,7 +88,7 @@ Class methods Methods ------- -.. method:: Pin.init(mode, pull=Pin.PULL_NONE, \*, value=None, alt=-1) +.. method:: Pin.init(mode, pull=Pin.PULL_NONE, *, value=None, alt=-1) Initialise the pin: @@ -107,7 +97,8 @@ Methods - ``Pin.IN`` - configure the pin for input; - ``Pin.OUT_PP`` - configure the pin for output, with push-pull control; - ``Pin.OUT_OD`` - configure the pin for output, with open-drain control; - - ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull; + - ``Pin.ALT`` - configure the pin for alternate function, input or output; + - ``Pin.AF_PP`` - configure the pin for alternate function, push-pull; - ``Pin.AF_OD`` - configure the pin for alternate function, open-drain; - ``Pin.ANALOG`` - configure the pin for analog. @@ -117,10 +108,14 @@ Methods - ``Pin.PULL_UP`` - enable the pull-up resistor; - ``Pin.PULL_DOWN`` - enable the pull-down resistor. + When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled, + that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND + respectively (except pin Y5 which has 11k Ohm resistors). + - *value* if not None will set the port output value before enabling the pin. - - *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the - index or name of one of the alternate functions associated with a pin. + - *alt* can be used when mode is ``Pin.ALT`` , ``Pin.AF_PP`` or ``Pin.AF_OD`` to + set the index or name of one of the alternate functions associated with a pin. This arg was previously called *af* which can still be used if needed. Returns: ``None``. @@ -183,6 +178,10 @@ Methods Constants --------- +.. data:: Pin.ALT + + initialise the pin to alternate-function mode for input or output + .. data:: Pin.AF_OD initialise the pin to alternate-function mode with an open-drain drive @@ -237,17 +236,17 @@ pin X3. For the pyboard, x3_af would contain: [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] -Normally, each peripheral would configure the af automatically, but sometimes -the same function is available on multiple pins, and having more control -is desired. +Normally, each peripheral would configure the alternate function automatically, +but sometimes the same function is available on multiple pins, and having more +control is desired. To configure X3 to expose TIM2_CH3, you could use:: - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2) + pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.ALT, alt=pyb.Pin.AF1_TIM2) or:: - pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) + pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.ALT, alt=1) Methods ------- diff --git a/docs/library/pyb.RTC.rst b/docs/library/pyb.RTC.rst index c477e7f035c87..040b1fe6b25ea 100644 --- a/docs/library/pyb.RTC.rst +++ b/docs/library/pyb.RTC.rst @@ -17,7 +17,7 @@ Example usage:: Constructors ------------ -.. class:: pyb.RTC() +.. class:: RTC() Create an RTC object. diff --git a/docs/library/pyb.SPI.rst b/docs/library/pyb.SPI.rst index 1bdb73a5dd170..4903a2c33f534 100644 --- a/docs/library/pyb.SPI.rst +++ b/docs/library/pyb.SPI.rst @@ -28,7 +28,7 @@ Additional methods for SPI:: Constructors ------------ -.. class:: pyb.SPI(bus, ...) +.. class:: SPI(bus, ...) Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or 'X' or 'Y'. With no additional parameters, the SPI object is created but @@ -51,7 +51,7 @@ Methods Turn off the SPI bus. -.. method:: SPI.init(mode, baudrate=328125, *, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) +.. method:: SPI.init(mode, baudrate=328125, *, prescaler=-1, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) Initialise the SPI bus with the given parameters: diff --git a/docs/library/pyb.Servo.rst b/docs/library/pyb.Servo.rst index b3ce71d11ac80..c52ee705f6f6c 100644 --- a/docs/library/pyb.Servo.rst +++ b/docs/library/pyb.Servo.rst @@ -30,7 +30,7 @@ Example usage:: Constructors ------------ -.. class:: pyb.Servo(id) +.. class:: Servo(id) Create a servo object. ``id`` is 1-4, and corresponds to pins X1 through X4. diff --git a/docs/library/pyb.Switch.rst b/docs/library/pyb.Switch.rst index 1edcbf8488a14..9ddf8c4170a3b 100644 --- a/docs/library/pyb.Switch.rst +++ b/docs/library/pyb.Switch.rst @@ -23,7 +23,7 @@ Example:: Constructors ------------ -.. class:: pyb.Switch() +.. class:: Switch() Create and return a switch object. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index 34fe71155fc15..1749efce2d508 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -53,7 +53,7 @@ limitation. Constructors ------------ -.. class:: pyb.Timer(id, ...) +.. class:: Timer(id, ...) Construct a new timer object of the given id. If additional arguments are given, then the timer is initialised by ``init(...)``. @@ -62,7 +62,7 @@ Constructors Methods ------- -.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0) +.. method:: Timer.init(*, freq, prescaler, period, mode=Timer.UP, div=1, callback=None, deadtime=0, brk=Timer.BRK_OFF) Initialise the timer. Initialisation must be either by frequency (in Hz) or by prescaler and period:: @@ -107,6 +107,14 @@ Methods measures ticks of ``source_freq`` divided by ``div`` clock ticks. ``deadtime`` is only available on timers 1 and 8. + - ``brk`` - specifies if the break mode is used to kill the output of + the PWM when the ``BRK_IN`` input is asserted. The value of this + argument determines if break is enabled and what the polarity is, and + can be one of ``Timer.BRK_OFF``, ``Timer.BRK_LOW`` or + ``Timer.BRK_HIGH``. To select the ``BRK_IN`` pin construct a Pin object with + ``mode=Pin.ALT, alt=Pin.AFn_TIMx``. The pin's GPIO input features are + available in alt mode - ``pull=`` , ``value()`` and ``irq()``. + You must either specify freq or both of period and prescaler. .. method:: Timer.deinit() @@ -198,6 +206,17 @@ Methods ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=8000) ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=16000) + PWM Motor Example with complementary outputs, dead time, break input and break callback:: + + from pyb import Timer + from machine import Pin # machine.Pin supports alt mode and irq on the same pin. + pin_t8_1 = Pin(Pin.board.Y1, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PC6, TIM8_CH1 + pin_t8_1n = Pin(Pin.board.X8, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PA7, TIM8_CH1N + pin_bkin = Pin(Pin.board.X7, mode=Pin.ALT, af=Pin.AF3_TIM8) # Pin PA6, TIM8_BKIN + pin_bkin.irq(handler=break_callabck, trigger=Pin.IRQ_FALLING) + timer = pyb.Timer(8, freq=1000, deadtime=1008, brk=Timer.BRK_LOW) + ch1 = timer.channel(1, pyb.Timer.PWM, pulse_width_percent=30) + .. method:: Timer.counter([value]) Get or set the timer counter. @@ -262,3 +281,18 @@ Methods for which the pulse is active. The value can be an integer or floating-point number for more accuracy. For example, a value of 25 gives a duty cycle of 25%. + +Constants +--------- + +.. data:: Timer.UP + Timer.DOWN + Timer.CENTER + + Configures the timer to count Up, Down, or from 0 to ARR and then back down to 0. + +.. data:: Timer.BRK_OFF + Timer.BRK_LOW + Timer.BRK_HIGH + + Configures the break mode when passed to the ``brk`` keyword argument. diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index e1735403c44a8..2bd9c6b34ef9a 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -46,7 +46,7 @@ Earlier versions use ``uart.send`` and ``uart.recv``. Constructors ------------ -.. class:: pyb.UART(bus, ...) +.. class:: UART(bus, ...) Construct a UART object on the given bus. For Pyboard ``bus`` can be 1-4, 6, 'XA', 'XB', 'YA', or 'YB'. diff --git a/docs/library/pyb.USB_HID.rst b/docs/library/pyb.USB_HID.rst index 7e23d1313d0da..80162cc56554c 100644 --- a/docs/library/pyb.USB_HID.rst +++ b/docs/library/pyb.USB_HID.rst @@ -13,7 +13,7 @@ Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the Constructors ------------ -.. class:: pyb.USB_HID() +.. class:: USB_HID() Create a new USB_HID object. diff --git a/docs/library/pyb.USB_VCP.rst b/docs/library/pyb.USB_VCP.rst index 1cca8dcadf6fc..17d2ecff4a6d7 100644 --- a/docs/library/pyb.USB_VCP.rst +++ b/docs/library/pyb.USB_VCP.rst @@ -12,7 +12,7 @@ the connected host. Constructors ------------ -.. class:: pyb.USB_VCP(id=0) +.. class:: USB_VCP(id=0) Create a new USB_VCP object. The *id* argument specifies which USB VCP port to use. diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst index 880d68c531f88..f169a77f3a6ca 100644 --- a/docs/library/pyb.rst +++ b/docs/library/pyb.rst @@ -213,11 +213,11 @@ Miscellaneous functions .. function:: mount(device, mountpoint, *, readonly=False, mkfs=False) .. note:: This function is deprecated. Mounting and unmounting devices should - be performed by :meth:`os.mount` and :meth:`os.umount` instead. + be performed by :meth:`vfs.mount` and :meth:`vfs.umount` instead. Mount a block device and make it available as part of the filesystem. ``device`` must be an object that provides the block protocol. (The - following is also deprecated. See :class:`os.AbstractBlockDev` for the + following is also deprecated. See :class:`vfs.AbstractBlockDev` for the correct way to create a block device.) - ``readblocks(self, blocknum, buf)`` @@ -298,6 +298,15 @@ Miscellaneous functions The *high_speed* parameter, when set to ``True``, enables USB HS mode if it is supported by the hardware. +Constants +--------- + +.. data:: pyb.hid_mouse + pyb.hid_keyboard + + A tuple of (subclass, protocol, max packet length, polling interval, report + descriptor) to set appropriate values for a USB mouse or keyboard. + Classes ------- diff --git a/docs/library/random.rst b/docs/library/random.rst index dd8b47c80f084..be56eb088eae7 100644 --- a/docs/library/random.rst +++ b/docs/library/random.rst @@ -24,7 +24,7 @@ This module implements a pseudo-random number generator (PRNG). .. note:: The :func:`randrange`, :func:`randint` and :func:`choice` functions are only - available if the ``MICROPY_PY_URANDOM_EXTRA_FUNCS`` configuration option is + available if the ``MICROPY_PY_RANDOM_EXTRA_FUNCS`` configuration option is enabled. @@ -73,7 +73,7 @@ Other Functions supported by the port) initialise the PRNG with a true random number (usually a hardware generated random number). - The ``None`` case only works if ``MICROPY_PY_URANDOM_SEED_INIT_FUNC`` is + The ``None`` case only works if ``MICROPY_PY_RANDOM_SEED_INIT_FUNC`` is enabled by the port, otherwise it raises ``ValueError``. .. function:: choice(sequence) diff --git a/docs/library/rp2.Flash.rst b/docs/library/rp2.Flash.rst index 1e94cf519c844..70cb127a192da 100644 --- a/docs/library/rp2.Flash.rst +++ b/docs/library/rp2.Flash.rst @@ -32,5 +32,5 @@ Methods These methods implement the simple and extended :ref:`block protocol ` defined by - :class:`os.AbstractBlockDev`. + :class:`vfs.AbstractBlockDev`. diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst index 8d73ccf772a7f..e8c167c09f573 100644 --- a/docs/library/rp2.StateMachine.rst +++ b/docs/library/rp2.StateMachine.rst @@ -32,7 +32,7 @@ Methods The program is added to the instruction memory of this PIO instance. If the instruction memory already contains this program, then its offset is - re-used so as to save on instruction memory. + reused so as to save on instruction memory. - *freq* is the frequency in Hz to run the state machine at. Defaults to the system clock frequency. @@ -55,8 +55,8 @@ Methods `PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`. - *push_thresh* is the threshold in bits before auto-push or conditional re-pushing is triggered. - - *pull_thresh* is the threshold in bits before auto-push or conditional - re-pushing is triggered. + - *pull_thresh* is the threshold in bits before auto-pull or conditional + re-pulling is triggered. .. method:: StateMachine.active([value]) @@ -82,11 +82,18 @@ Methods .. method:: StateMachine.exec(instr) - Execute a single PIO instruction. Uses `asm_pio_encode` to encode the - instruction from the given string *instr*. + Execute a single PIO instruction. + + If *instr* is a string then uses `asm_pio_encode` to encode the instruction + from the given string. >>> sm.exec("set(0, 1)") + If *instr* is an integer then it is treated as an already encoded PIO + machine code instruction to be executed. + + >>> sm.exec(rp2.asm_pio_encode("out(y, 8)", 0)) + .. method:: StateMachine.get(buf=None, shift=0) Pull a word from the state machine's RX FIFO. @@ -99,13 +106,17 @@ Methods .. method:: StateMachine.put(value, shift=0) - Push a word onto the state machine's TX FIFO. + Push words onto the state machine's TX FIFO. + + *value* can be an integer, an array of type ``B``, ``H`` or ``I``, or a + `bytearray`. - If the FIFO is full, it blocks until there is space (i.e. the state machine - pulls a word). + This method will block until all words have been written to the FIFO. If + the FIFO is, or becomes, full, the method will block until the state machine + pulls enough words to complete the write. - The value is first shifted left by *shift* bits, i.e. the state machine - receives ``value << shift``. + Each word is first shifted left by *shift* bits, i.e. the state machine + receives ``word << shift``. .. method:: StateMachine.rx_fifo() diff --git a/docs/library/rp2.rst b/docs/library/rp2.rst index 43143fe08977c..7a473387b4a81 100644 --- a/docs/library/rp2.rst +++ b/docs/library/rp2.rst @@ -10,7 +10,7 @@ The ``rp2`` module contains functions and classes specific to the RP2040, as used in the Raspberry Pi Pico. See the `RP2040 Python datasheet -`_ +`_ for more information, and `pico-micropython-examples `_ for example code. @@ -47,8 +47,8 @@ For running PIO programs, see :class:`rp2.StateMachine`. `PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`. - *push_thresh* is the threshold in bits before auto-push or conditional re-pushing is triggered. - - *pull_thresh* is the threshold in bits before auto-push or conditional - re-pushing is triggered. + - *pull_thresh* is the threshold in bits before auto-pull or conditional + re-pulling is triggered. The remaining parameters are: @@ -58,7 +58,7 @@ For running PIO programs, see :class:`rp2.StateMachine`. combined into a single 8-word FIFO for one direction only. The options are `PIO.JOIN_NONE`, `PIO.JOIN_RX` and `PIO.JOIN_TX`. -.. function:: asm_pio_encode(instr, sideset_count) +.. function:: asm_pio_encode(instr, sideset_count, sideset_opt=False) Assemble a single PIO instruction. You usually want to use `asm_pio()` instead. @@ -66,6 +66,17 @@ For running PIO programs, see :class:`rp2.StateMachine`. >>> rp2.asm_pio_encode("set(0, 1)", 0) 57345 +.. function:: bootsel_button() + + Temporarily turns the QSPI_SS pin into an input and reads its value, + returning 1 for low and 0 for high. + On a typical RP2040 board with a BOOTSEL button, a return value of 1 + indicates that the button is pressed. + + Since this function temporarily disables access to the external flash + memory, it also temporarily disables interrupts and the other core to + prevent them from trying to execute code from flash. + .. class:: PIOASMError This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is diff --git a/docs/library/socket.rst b/docs/library/socket.rst index 704b614ab1c50..944e7e631ac76 100644 --- a/docs/library/socket.rst +++ b/docs/library/socket.rst @@ -29,7 +29,7 @@ returned by `getaddrinfo` function, which must be used to resolve textual addres # You must use getaddrinfo() even for numeric addresses sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1] # Now you can use that address - sock.connect(addr) + sock.connect(sockaddr) Using `getaddrinfo` is the most efficient (both in terms of memory and processing power) and portable way to work with addresses. @@ -66,19 +66,6 @@ Tuple address format for ``socket`` module: Functions --------- -.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /) - - Create a new socket using the given address family, socket type and - protocol number. Note that specifying *proto* in most cases is not - required (and not recommended, as some MicroPython ports may omit - ``IPPROTO_*`` constants). Instead, *type* argument will select needed - protocol automatically:: - - # Create STREAM TCP socket - socket(AF_INET, SOCK_STREAM) - # Create DGRAM UDP socket - socket(AF_INET, SOCK_DGRAM) - .. function:: getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, /) Translate the host/port argument into a sequence of 5-tuples that contain all the @@ -176,6 +163,19 @@ Constants specific to WiPy: class socket ============ +.. class:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /) + + Create a new socket using the given address family, socket type and + protocol number. Note that specifying *proto* in most cases is not + required (and not recommended, as some MicroPython ports may omit + ``IPPROTO_*`` constants). Instead, *type* argument will select needed + protocol automatically:: + + # Create STREAM TCP socket + socket(AF_INET, SOCK_STREAM) + # Create DGRAM UDP socket + socket(AF_INET, SOCK_DGRAM) + Methods ------- diff --git a/docs/library/ssl.rst b/docs/library/ssl.rst index 4726daa59b4ae..dff90b8da58b9 100644 --- a/docs/library/ssl.rst +++ b/docs/library/ssl.rst @@ -13,26 +13,81 @@ facilities for network sockets, both client-side and server-side. Functions --------- -.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None, do_handshake=True) +.. function:: ssl.wrap_socket(sock, server_side=False, key=None, cert=None, cert_reqs=CERT_NONE, cadata=None, server_hostname=None, do_handshake=True) + + Wrap the given *sock* and return a new wrapped-socket object. The implementation + of this function is to first create an `SSLContext` and then call the `SSLContext.wrap_socket` + method on that context object. The arguments *sock*, *server_side* and *server_hostname* are + passed through unchanged to the method call. The argument *do_handshake* is passed through as + *do_handshake_on_connect*. The remaining arguments have the following behaviour: + + - *cert_reqs* determines whether the peer (server or client) must present a valid certificate. + Note that for mbedtls based ports, ``ssl.CERT_NONE`` and ``ssl.CERT_OPTIONAL`` will not + validate any certificate, only ``ssl.CERT_REQUIRED`` will. + + - *cadata* is a bytes object containing the CA certificate chain (in DER format) that will + validate the peer's certificate. Currently only a single DER-encoded certificate is supported. + + Depending on the underlying module implementation in a particular + :term:`MicroPython port`, some or all keyword arguments above may be not supported. + +class SSLContext +---------------- + +.. class:: SSLContext(protocol, /) + + 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 `_ . + +.. 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), - and returns an instance of ssl.SSLSocket, which wraps the underlying stream in - an SSL context. Returned object has the usual `stream` interface methods like + and returns an instance of ssl.SSLSocket, wrapping the underlying stream. + The returned object has the usual `stream` interface methods like ``read()``, ``write()``, etc. - A server-side SSL socket should be created from a normal socket returned from - :meth:`~socket.socket.accept()` on a non-SSL listening server socket. - - *do_handshake* determines whether the handshake is done as part of the ``wrap_socket`` + - *server_side* selects whether the wrapped socket is on the server or client side. + A server-side SSL socket should be created from a normal socket returned from + :meth:`~socket.socket.accept()` on a non-SSL listening server socket. + + - *do_handshake_on_connect* determines whether the handshake is done as part of the ``wrap_socket`` or whether it is deferred to be done as part of the initial reads or writes - (there is no ``do_handshake`` method as in CPython). For blocking sockets doing the handshake immediately is standard. For non-blocking sockets (i.e. when the *sock* passed into ``wrap_socket`` is in non-blocking mode) the handshake should generally be deferred because otherwise ``wrap_socket`` blocks until it completes. Note that in AXTLS the handshake can be deferred until the first read or write but it then blocks until completion. - Depending on the underlying module implementation in a particular - :term:`MicroPython port`, some or all keyword arguments above may be not supported. + - *server_hostname* is for use as a client, and sets the hostname to check against the received + server certificate. It also sets the name for Server Name Indication (SNI), allowing the server + to present the proper certificate. .. warning:: @@ -44,6 +99,17 @@ Functions returns an object more similar to CPython's ``SSLObject`` which does not have these socket methods. +.. attribute:: SSLContext.verify_mode + + 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 ` or ``ntptime``, and ``server_hostname`` + must be specified when on the client side. + Exceptions ---------- @@ -54,8 +120,14 @@ Exceptions Constants --------- +.. data:: ssl.PROTOCOL_TLS_CLIENT + ssl.PROTOCOL_TLS_SERVER + + Supported values for the *protocol* parameter. + .. data:: ssl.CERT_NONE ssl.CERT_OPTIONAL ssl.CERT_REQUIRED - Supported values for *cert_reqs* parameter. + Supported values for *cert_reqs* parameter, and the :attr:`SSLContext.verify_mode` + attribute. diff --git a/docs/library/stm.rst b/docs/library/stm.rst index a181d6044cc16..970ab188344a5 100644 --- a/docs/library/stm.rst +++ b/docs/library/stm.rst @@ -102,3 +102,39 @@ the second CPU, the RF core. Execute a HCI command on the SYS channel. The execution is synchronous. Returns a bytes object with the result of the SYS command. + +Functions specific to STM32WLxx MCUs +------------------------------------ + +These functions are available on STM32WLxx microcontrollers, and interact with +the integrated "SUBGHZ" radio modem peripheral. + +.. function:: subghz_cs(level) + + Sets the internal SPI CS pin attached to the radio peripheral. The ``level`` + argument is active-low: a truthy value means "CS pin high" and de-asserts the + signal, a falsey value means "CS pin low" and asserts the signal. + + The internal-only SPI bus corresponding to this CS signal can be instantiated + using :ref:`machine.SPI()` ``id`` value ``"SUBGHZ"``. + +.. function:: subghz_irq(handler) + + Sets the internal SUBGHZ radio interrupt handler to the provided + function. The handler function is called as a "hard" interrupt in response to + radio peripheral interrupts. See :ref:`isr_rules` for more information about + interrupt handlers in MicroPython. + + Calling this function with the handler argument set to None disables the IRQ. + + Due to a hardware limitation, each time this IRQ fires MicroPython disables + it before calling the handler. In order to receive another interrupt, Python + code should call ``subghz_irq()`` to set the handler again. This has the side + effect of re-enabling the IRQ. + +.. function:: subghz_is_busy() + + Return a ``bool`` corresponding to the internal "RFBUSYS" signal from the + radio peripheral. Before sending a new command to the radio over SPI then + this function should be polled until it returns ``False``, to confirm the + busy signal is de-asserted. diff --git a/docs/library/struct.rst b/docs/library/struct.rst index 92757aba8d50a..026cb5e8ac3b4 100644 --- a/docs/library/struct.rst +++ b/docs/library/struct.rst @@ -6,11 +6,58 @@ |see_cpython_module| :mod:`python:struct`. -Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. - -Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, -``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending -on the floating-point support). +The following byte orders are supported: + ++-----------+------------------------+----------+-----------+ +| Character | Byte order | Size | Alignment | ++===========+========================+==========+===========+ +| @ | native | native | native | ++-----------+------------------------+----------+-----------+ +| < | little-endian | standard | none | ++-----------+------------------------+----------+-----------+ +| > | big-endian | standard | none | ++-----------+------------------------+----------+-----------+ +| ! | network (= big-endian) | standard | none | ++-----------+------------------------+----------+-----------+ + +The following data types are supported: + ++--------+--------------------+-------------------+---------------+ +| Format | C Type | Python type | Standard size | ++========+====================+===================+===============+ +| b | signed char | integer | 1 | ++--------+--------------------+-------------------+---------------+ +| B | unsigned char | integer | 1 | ++--------+--------------------+-------------------+---------------+ +| h | short | integer | 2 | ++--------+--------------------+-------------------+---------------+ +| H | unsigned short | integer | 2 | ++--------+--------------------+-------------------+---------------+ +| i | int | integer (`1`) | 4 | ++--------+--------------------+-------------------+---------------+ +| I | unsigned int | integer (`1`) | 4 | ++--------+--------------------+-------------------+---------------+ +| l | long | integer (`1`) | 4 | ++--------+--------------------+-------------------+---------------+ +| L | unsigned long | integer (`1`) | 4 | ++--------+--------------------+-------------------+---------------+ +| q | long long | integer (`1`) | 8 | ++--------+--------------------+-------------------+---------------+ +| Q | unsigned long long | integer (`1`) | 8 | ++--------+--------------------+-------------------+---------------+ +| f | float | float (`2`) | 4 | ++--------+--------------------+-------------------+---------------+ +| d | double | float (`2`) | 8 | ++--------+--------------------+-------------------+---------------+ +| s | char[] | bytes | | ++--------+--------------------+-------------------+---------------+ +| P | void * | integer | | ++--------+--------------------+-------------------+---------------+ + +.. _fn: + +(1) Requires long support when used with values larger than 30 bits. +(2) Requires floating point support. .. admonition:: Difference to CPython :class: attention @@ -43,5 +90,5 @@ Functions .. function:: unpack_from(fmt, data, offset=0, /) Unpack from the *data* starting at *offset* according to the format string - *fmt*. *offset* may be negative to count from the end of *buffer*. The return + *fmt*. *offset* may be negative to count from the end of *data*. The return value is a tuple of the unpacked values. diff --git a/docs/library/sys.rst b/docs/library/sys.rst index 24f9e353bb006..7b34a0e31c6bf 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -43,6 +43,15 @@ Functions positional; further arguments are not supported. CPython-compatible ``traceback`` module can be found in `micropython-lib`. +.. function:: settrace(tracefunc) + + Enable tracing of bytecode execution. For details see the `CPython + documentation `_. + + This function requires a custom MicroPython build as it is typically not + present in pre-built firmware (due to it affecting performance). The relevant + configuration option is *MICROPY_PY_SYS_SETTRACE*. + Constants --------- @@ -60,12 +69,17 @@ Constants MicroPython, it has following attributes: * *name* - string "micropython" - * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) + * *version* - tuple (major, minor, micro, releaselevel), e.g. (1, 22, 0, '') + * *_machine* - string describing the underlying machine + * *_mpy* - supported mpy file-format version (optional attribute) This object is the recommended way to distinguish MicroPython from other Python implementations (note that it still may not exist in the very minimal ports). + Starting with version 1.22.0-preview, the fourth node *releaselevel* in + *implementation.version* is either an empty string or ``"preview"``. + .. admonition:: Difference to CPython :class: attention @@ -106,6 +120,14 @@ Constants A mutable list of directories to search for imported modules. + .. admonition:: Difference to CPython + :class: attention + + On MicroPython, an entry with the value ``".frozen"`` will indicate that import + should search :term:`frozen modules ` at that point in the search. + If no frozen module is found then search will *not* look for a directory called + ``.frozen``, instead it will continue with the next entry in ``sys.path``. + .. data:: platform The platform that MicroPython is running on. For OS/RTOS ports, this is @@ -115,6 +137,12 @@ Constants If you need to check whether your program runs on MicroPython (vs other Python implementation), use `sys.implementation` instead. +.. data:: ps1 + ps2 + + Mutable attributes holding strings, which are used for the REPL prompt. The defaults + give the standard Python prompt of ``>>>`` and ``...``. + .. data:: stderr Standard error `stream`. @@ -127,6 +155,14 @@ Constants Standard output `stream`. +.. data:: tracebacklimit + + A mutable attribute holding an integer value which is the maximum number of traceback + entries to store in an exception. Set to 0 to disable adding tracebacks. Defaults + to 1000. + + Note: this is not available on all ports. + .. data:: version Python language version that this implementation conforms to, as a string. diff --git a/docs/library/time.rst b/docs/library/time.rst index 6ca172f22128e..8c1c1d4d6fb23 100644 --- a/docs/library/time.rst +++ b/docs/library/time.rst @@ -10,8 +10,8 @@ The ``time`` module provides functions for getting the current time and date, measuring time intervals, and for delays. **Time Epoch**: Unix port uses standard for POSIX systems epoch of -1970-01-01 00:00:00 UTC. However, embedded ports use epoch of -2000-01-01 00:00:00 UTC. +1970-01-01 00:00:00 UTC. However, some embedded ports use epoch of +2000-01-01 00:00:00 UTC. Epoch year may be determined with ``gmtime(0)[0]``. **Maintaining actual calendar date/time**: This requires a Real Time Clock (RTC). On systems with underlying OS (including some @@ -163,8 +163,8 @@ Functions However, values returned by `ticks_ms()`, etc. functions may wrap around, so directly using subtraction on them will produce incorrect result. That is why `ticks_diff()` is needed, it implements modular (or more specifically, ring) - arithmetics to produce correct result even for wrap-around values (as long as they not - too distant inbetween, see below). The function returns **signed** value in the range + arithmetic to produce correct result even for wrap-around values (as long as they not + too distant in between, see below). The function returns **signed** value in the range [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for two's-complement signed binary integers). If the result is negative, it means that *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that @@ -183,7 +183,7 @@ Functions has passed. To avoid this mistake, just look at the clock regularly. Your application should do the same. "Too long sleep" metaphor also maps directly to application behaviour: don't let your application run any single task for too long. Run tasks - in steps, and do time-keeping inbetween. + in steps, and do time-keeping in between. `ticks_diff()` is designed to accommodate various usage patterns, among them: diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst deleted file mode 100644 index 11b9c6aee4136..0000000000000 --- a/docs/library/uasyncio.rst +++ /dev/null @@ -1,349 +0,0 @@ -:mod:`uasyncio` --- asynchronous I/O scheduler -============================================== - -.. module:: uasyncio - :synopsis: asynchronous I/O scheduler for writing concurrent code - -|see_cpython_module| -`asyncio `_ - -Example:: - - import uasyncio - - async def blink(led, period_ms): - while True: - led.on() - await uasyncio.sleep_ms(5) - led.off() - await uasyncio.sleep_ms(period_ms) - - async def main(led1, led2): - uasyncio.create_task(blink(led1, 700)) - uasyncio.create_task(blink(led2, 400)) - await uasyncio.sleep_ms(10_000) - - # Running on a pyboard - from pyb import LED - uasyncio.run(main(LED(1), LED(2))) - - # Running on a generic board - from machine import Pin - uasyncio.run(main(Pin(1), Pin(2))) - -Core functions --------------- - -.. function:: create_task(coro) - - Create a new task from the given coroutine and schedule it to run. - - Returns the corresponding `Task` object. - -.. function:: current_task() - - Return the `Task` object associated with the currently running task. - -.. function:: run(coro) - - Create a new task from the given coroutine and run it until it completes. - - Returns the value returned by *coro*. - -.. function:: sleep(t) - - Sleep for *t* seconds (can be a float). - - This is a coroutine. - -.. function:: sleep_ms(t) - - Sleep for *t* milliseconds. - - This is a coroutine, and a MicroPython extension. - -Additional functions --------------------- - -.. function:: wait_for(awaitable, timeout) - - Wait for the *awaitable* to complete, but cancel it if it takes longer - that *timeout* seconds. If *awaitable* is not a task then a task will be - created from it. - - If a timeout occurs, it cancels the task and raises ``asyncio.TimeoutError``: - this should be trapped by the caller. - - Returns the return value of *awaitable*. - - This is a coroutine. - -.. function:: wait_for_ms(awaitable, timeout) - - Similar to `wait_for` but *timeout* is an integer in milliseconds. - - This is a coroutine, and a MicroPython extension. - -.. function:: gather(*awaitables, return_exceptions=False) - - Run all *awaitables* concurrently. Any *awaitables* that are not tasks are - promoted to tasks. - - Returns a list of return values of all *awaitables*. - - This is a coroutine. - -class Task ----------- - -.. class:: Task() - - This object wraps a coroutine into a running task. Tasks can be waited on - using ``await task``, which will wait for the task to complete and return - the return value of the task. - - Tasks should not be created directly, rather use `create_task` to create them. - -.. method:: Task.cancel() - - Cancel the task by injecting a ``CancelledError`` into it. The task may - or may not ignore this exception. - -class Event ------------ - -.. class:: Event() - - Create a new event which can be used to synchronise tasks. Events start - in the cleared state. - -.. method:: Event.is_set() - - Returns ``True`` if the event is set, ``False`` otherwise. - -.. method:: Event.set() - - Set the event. Any tasks waiting on the event will be scheduled to run. - - Note: This must be called from within a task. It is not safe to call this - from an IRQ, scheduler callback, or other thread. See `ThreadSafeFlag`. - -.. method:: Event.clear() - - Clear the event. - -.. method:: Event.wait() - - Wait for the event to be set. If the event is already set then it returns - immediately. - - This is a coroutine. - -class ThreadSafeFlag --------------------- - -.. class:: ThreadSafeFlag() - - Create a new flag which can be used to synchronise a task with code running - outside the asyncio loop, such as other threads, IRQs, or scheduler - callbacks. Flags start in the cleared state. - -.. method:: ThreadSafeFlag.set() - - Set the flag. If there is a task waiting on the event, it will be scheduled - to run. - -.. method:: ThreadSafeFlag.wait() - - Wait for the flag to be set. If the flag is already set then it returns - immediately. - - A flag may only be waited on by a single task at a time. - - This is a coroutine. - -class Lock ----------- - -.. class:: Lock() - - Create a new lock which can be used to coordinate tasks. Locks start in - the unlocked state. - - In addition to the methods below, locks can be used in an ``async with`` statement. - -.. method:: Lock.locked() - - Returns ``True`` if the lock is locked, otherwise ``False``. - -.. method:: Lock.acquire() - - Wait for the lock to be in the unlocked state and then lock it in an atomic - way. Only one task can acquire the lock at any one time. - - This is a coroutine. - -.. method:: Lock.release() - - Release the lock. If any tasks are waiting on the lock then the next one in the - queue is scheduled to run and the lock remains locked. Otherwise, no tasks are - waiting an the lock becomes unlocked. - -TCP stream connections ----------------------- - -.. function:: open_connection(host, port) - - 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. - - 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 - the connection could not be made. - - This is a coroutine. - -.. function:: start_server(callback, host, port, backlog=5) - - 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. - - Returns a `Server` object. - - This is a coroutine. - -.. class:: Stream() - - This represents a TCP stream connection. To minimise code this class implements - both a reader and a writer, and both ``StreamReader`` and ``StreamWriter`` alias to - this class. - -.. method:: Stream.get_extra_info(v) - - Get extra information about the stream, given by *v*. The valid values for *v* are: - ``peername``. - -.. method:: Stream.close() - - Close the stream. - -.. method:: Stream.wait_closed() - - Wait for the stream to close. - - This is a coroutine. - -.. method:: Stream.read(n) - - Read up to *n* bytes and return them. - - This is a coroutine. - -.. method:: Stream.readinto(buf) - - Read up to n bytes into *buf* with n being equal to the length of *buf*. - - Return the number of bytes read into *buf*. - - This is a coroutine, and a MicroPython extension. - -.. method:: Stream.readexactly(n) - - Read exactly *n* bytes and return them as a bytes object. - - Raises an ``EOFError`` exception if the stream ends before reading *n* bytes. - - This is a coroutine. - -.. method:: Stream.readline() - - Read a line and return it. - - This is a coroutine. - -.. method:: Stream.write(buf) - - Accumulated *buf* to the output buffer. The data is only flushed when - `Stream.drain` is called. It is recommended to call `Stream.drain` immediately - after calling this function. - -.. method:: Stream.drain() - - Drain (write) all buffered output data out to the stream. - - This is a coroutine. - -.. class:: Server() - - This represents the server class returned from `start_server`. It can be used - in an ``async with`` statement to close the server upon exit. - -.. method:: Server.close() - - Close the server. - -.. method:: Server.wait_closed() - - Wait for the server to close. - - This is a coroutine. - -Event Loop ----------- - -.. function:: get_event_loop() - - Return the event loop used to schedule and run tasks. See `Loop`. - -.. function:: new_event_loop() - - Reset the event loop and return it. - - Note: since MicroPython only has a single event loop this function just - resets the loop's state, it does not create a new one. - -.. class:: Loop() - - This represents the object which schedules and runs tasks. It cannot be - created, use `get_event_loop` instead. - -.. method:: Loop.create_task(coro) - - Create a task from the given *coro* and return the new `Task` object. - -.. method:: Loop.run_forever() - - Run the event loop until `stop()` is called. - -.. method:: Loop.run_until_complete(awaitable) - - Run the given *awaitable* until it completes. If *awaitable* is not a task - then it will be promoted to one. - -.. method:: Loop.stop() - - Stop the event loop. - -.. method:: Loop.close() - - Close the event loop. - -.. method:: Loop.set_exception_handler(handler) - - Set the exception handler to call when a Task raises an exception that is not - caught. The *handler* should accept two arguments: ``(loop, context)``. - -.. method:: Loop.get_exception_handler() - - Get the current exception handler. Returns the handler, or ``None`` if no - custom handler is set. - -.. method:: Loop.default_exception_handler(context) - - The default exception handler that is called. - -.. method:: Loop.call_exception_handler(context) - - Call the current exception handler. The argument *context* is passed through and - is a dictionary containing keys: ``'message'``, ``'exception'``, ``'future'``. diff --git a/docs/library/vfs.rst b/docs/library/vfs.rst new file mode 100644 index 0000000000000..fcd06eb4353b1 --- /dev/null +++ b/docs/library/vfs.rst @@ -0,0 +1,208 @@ +:mod:`vfs` -- virtual filesystem control +======================================== + +.. module:: vfs + :synopsis: virtual filesystem control + +The ``vfs`` module contains functions for creating filesystem objects and +mounting/unmounting them in the Virtual Filesystem. + +Filesystem mounting +------------------- + +Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple +"real" filesystems within this VFS. Filesystem objects can be mounted at either +the root of the VFS, or at a subdirectory that lives in the root. This allows +dynamic and flexible configuration of the filesystem that is seen by Python +programs. Ports that have this functionality provide the :func:`mount` and +:func:`umount` functions, and possibly various filesystem implementations +represented by VFS classes. + +.. function:: mount(fsobj, mount_point, *, readonly) + + Mount the filesystem object *fsobj* at the location in the VFS given by the + *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` + method, or a block device. If it's a block device then the filesystem type + is automatically detected (an exception is raised if no filesystem was + recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, + or ``'/'`` to mount it at a subdirectory under the root. + + If *readonly* is ``True`` then the filesystem is mounted read-only. + + During the mount process the method ``mount()`` is called on the filesystem + object. + + Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. + +.. function:: umount(mount_point) + + Unmount a filesystem. *mount_point* can be a string naming the mount location, + or a previously-mounted filesystem object. During the unmount process the + method ``umount()`` is called on the filesystem object. + + Will raise ``OSError(EINVAL)`` if *mount_point* is not found. + +.. class:: VfsFat(block_dev) + + Create a filesystem object that uses the FAT filesystem format. Storage of + the FAT filesystem is provided by *block_dev*. + Objects created by this constructor can be mounted using :func:`mount`. + + .. staticmethod:: mkfs(block_dev) + + Build a FAT filesystem on *block_dev*. + +.. class:: VfsLfs1(block_dev, readsize=32, progsize=32, lookahead=32) + + Create a filesystem object that uses the `littlefs v1 filesystem format`_. + Storage of the littlefs filesystem is provided by *block_dev*, which must + support the :ref:`extended interface `. + Objects created by this constructor can be mounted using :func:`mount`. + + See :ref:`filesystem` for more information. + + .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) + + Build a Lfs1 filesystem on *block_dev*. + + .. note:: There are reports of littlefs v1 failing in certain situations, + for details see `littlefs issue 347`_. + +.. class:: VfsLfs2(block_dev, readsize=32, progsize=32, lookahead=32, mtime=True) + + Create a filesystem object that uses the `littlefs v2 filesystem format`_. + Storage of the littlefs filesystem is provided by *block_dev*, which must + support the :ref:`extended interface `. + Objects created by this constructor can be mounted using :func:`mount`. + + The *mtime* argument enables modification timestamps for files, stored using + littlefs attributes. This option can be disabled or enabled differently each + mount time and timestamps will only be added or updated if *mtime* is enabled, + otherwise the timestamps will remain untouched. Littlefs v2 filesystems without + timestamps will work without reformatting and timestamps will be added + transparently to existing files once they are opened for writing. When *mtime* + is enabled `os.stat` on files without timestamps will return 0 for the timestamp. + + See :ref:`filesystem` for more information. + + .. staticmethod:: mkfs(block_dev, readsize=32, progsize=32, lookahead=32) + + Build a Lfs2 filesystem on *block_dev*. + + .. note:: There are reports of littlefs v2 failing in certain situations, + for details see `littlefs issue 295`_. + +.. class:: VfsPosix(root=None) + + Create a filesystem object that accesses the host POSIX filesystem. + If *root* is specified then it should be a path in the host filesystem to use + as the root of the ``VfsPosix`` object. Otherwise the current directory of + the host filesystem is used. + +.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1 +.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs +.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 +.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 + +Block devices +------------- + +A block device is an object which implements the block protocol. This enables a +device to support MicroPython filesystems. The physical hardware is represented +by a user defined class. The :class:`AbstractBlockDev` class is a template for +the design of such a class: MicroPython does not actually provide that class, +but an actual block device class must implement the methods described below. + +A concrete implementation of this class will usually allow access to the +memory-like functionality of a piece of hardware (like flash memory). A block +device can be formatted to any supported filesystem and mounted using ``os`` +methods. + +See :ref:`filesystem` for example implementations of block devices using the +two variants of the block protocol described below. + +.. _block-device-interface: + +Simple and extended interface +............................. + +There are two compatible signatures for the ``readblocks`` and ``writeblocks`` +methods (see below), in order to support a variety of use cases. A given block +device may implement one form or the other, or both at the same time. The second +form (with the offset parameter) is referred to as the "extended interface". + +Some filesystems (such as littlefs) that require more control over write +operations, for example writing to sub-block regions without erasing, may require +that the block device supports the extended interface. + +.. class:: AbstractBlockDev(...) + + Construct a block device object. The parameters to the constructor are + dependent on the specific block device. + + .. method:: readblocks(block_num, buf) + readblocks(block_num, buf, offset) + + The first form reads aligned, multiples of blocks. + Starting at the block given by the index *block_num*, read blocks from + the device into *buf* (an array of bytes). + The number of blocks to read is given by the length of *buf*, + which will be a multiple of the block size. + + The second form allows reading at arbitrary locations within a block, + and arbitrary lengths. + Starting at block index *block_num*, and byte offset within that block + of *offset*, read bytes from the device into *buf* (an array of bytes). + The number of bytes to read is given by the length of *buf*. + + .. method:: writeblocks(block_num, buf) + writeblocks(block_num, buf, offset) + + The first form writes aligned, multiples of blocks, and requires that the + blocks that are written to be first erased (if necessary) by this method. + Starting at the block given by the index *block_num*, write blocks from + *buf* (an array of bytes) to the device. + The number of blocks to write is given by the length of *buf*, + which will be a multiple of the block size. + + The second form allows writing at arbitrary locations within a block, + and arbitrary lengths. Only the bytes being written should be changed, + and the caller of this method must ensure that the relevant blocks are + erased via a prior ``ioctl`` call. + Starting at block index *block_num*, and byte offset within that block + of *offset*, write bytes from *buf* (an array of bytes) to the device. + The number of bytes to write is given by the length of *buf*. + + Note that implementations must never implicitly erase blocks if the offset + argument is specified, even if it is zero. + + .. method:: ioctl(op, arg) + + Control the block device and query its parameters. The operation to + perform is given by *op* which is one of the following integers: + + - 1 -- initialise the device (*arg* is unused) + - 2 -- shutdown the device (*arg* is unused) + - 3 -- sync the device (*arg* is unused) + - 4 -- get a count of the number of blocks, should return an integer + (*arg* is unused) + - 5 -- get the number of bytes in a block, should return an integer, + or ``None`` in which case the default value of 512 is used + (*arg* is unused) + - 6 -- erase a block, *arg* is the block number to erase + + As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs + ``ioctl(6, ...)`` must also be intercepted. The need for others is + hardware dependent. + + Prior to any call to ``writeblocks(block, ...)`` littlefs issues + ``ioctl(6, block)``. This enables a device driver to erase the block + prior to a write if the hardware requires it. Alternatively a driver + might intercept ``ioctl(6, block)`` and return 0 (success). In this case + the driver assumes responsibility for detecting the need for erasure. + + Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. + Consequently an implementation can ignore unused values of ``op``. Where + ``op`` is intercepted, the return value for operations 4 and 5 are as + detailed above. Other operations should return 0 on success and non-zero + for failure, with the value returned being an ``OSError`` errno code. diff --git a/docs/library/wm8960.rst b/docs/library/wm8960.rst new file mode 100644 index 0000000000000..5abfb6a8a011c --- /dev/null +++ b/docs/library/wm8960.rst @@ -0,0 +1,397 @@ +.. _wm8960: + +:mod:`WM8960` -- Driver for the WM8960 codec +============================================ + +This driver is used to control a WM8960 codec chip. It is a Python +translation of the C-Code provided by NXP/Freescale for their i.MX RT series of +MCUs. Very little has been added, and just a few API related names were changed +or added to cope with the naming style of MicroPython. + +The primary purpose of the driver is initialization and setting operation modes +of the codec. It does not do the audio data processing for the codec. That is +the task of a separate driver. + +The WM8960 supports an I2C interface, in addition to the audio interface. The +connection depends on the interface used and the number of devices in the +system. For the I2C interface, SCL and SDA have to be connected, and of course +GND and Vcc. The I2C default address is ``0x1A``. + +Constructor +----------- + +.. class:: WM8960(i2c, sample_rate, *, bits=16, swap=SWAP_NONE, route=ROUTE_PLAYBACK_RECORD, left_input=INPUT_MIC3, right_input=INPUT_MIC2, sysclk_source=SYSCLK_MCLK, mclk_freq=None, primary=False, adc_sync=SYNC_DAC, protocol=BUS_I2S, i2c_address=WM8960_I2C_ADDR) + + Create a WM8960 driver object, initialize the device with default settings and return the + WM8960 object. + + Only the first two arguments are mandatory. All others are optional. The arguments are: + + - *i2c* is the I2C bus object. + - *sample_rate* is the audio sample rate. Acceptable values are 8000, + 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, 192000 + and 384000. Note that not every I2S hardware will support all values. + - *bits* is the number of bits per audio word. Acceptable value are 16, + 20, 24, and 32. + - *swap* swaps the left & right channel, if set; see below for options. + - *route* Setting the audio path in the codec; see below for options. + - *left_input* sets the audio source for the left input channel; + see below for options. + - *right_input* sets the audio source for the right input channel; + see below for options. + - *play_source* sets the audio target for the output audio; + see below for options. + - *sysclk_source* controls whether the internal master clock called + "sysclk" is directly taken from the MCLK input or derived from it + using an internal PLL. It is usually not required to change this. + - *mclk_freq* sets the mclk frequency applied to the MCLK pin of the + codec. If not set, default values are used. + - *primary* lets the WM8960 act as primary or secondary device. The + default setting is ``False``. When set to ``False``, + *sample_rate* and *bits* are controlled by the MCU. + - *adc_sync* sets which input is used for the ADC sync signal. + The default is using the DACLRC pin. + - *protocol* sets the communication protocol. The default is I2S. + See below for all options. + - *i2c_address* sets the I2C address of the WM8960, with default ``0x1A``. + + If *mclk_freq* is not set the following default values are used: + + - sysclk_source == SYSCLK_PLL: 11.2896 MHz for sample rates of 44100, + 22050 and 11015 Hz, and 12.288 Mhz for sample rates < 48000, otherwise + sample_rate * 256. + - sysclk_source == SYSCLK_MCLK: sample_rate * 256. + + If the MCLK signal is applied using, for example,. a separate oscillator, + it must be specified for proper operation. + +Tables of parameter constants +----------------------------- + +.. table:: **Swap Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SWAP_NONE + 1 SWAP_INPUT + 2 SWAP_OUTPUT + ===== ==== + +.. table:: **Protocol Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 2 BUS_I2S + 1 BUS_LEFT_JUSTIFIED + 0 BUS_RIGHT_JUSTIFIED + 3 BUS_PCMA + 19 BUS_PCMB + ===== ==== + +.. table:: **Input Source Parameter** + :widths: auto + :align: left + + ===== ============ ==== + Value Name Type + ===== ============ ==== + 0 INPUT_CLOSED + 1 INPUT_MIC1 Single ended + 2 INPUT_MIC2 Differential + 3 INPUT_MIC3 Differential + 4 INPUT_LINE2 + 5 INPUT_LINE3 + ===== ============ ==== + +.. table:: **Route Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 ROUTE_BYPASS + 1 ROUTE_PLAYBACK + 2 ROUTE_PLAYBACK_RECORD + 5 ROUTE_RECORD + ===== ==== + +.. table:: **Master Clock Source Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SYSCLK_MCLK + 1 SYSCLK_PLL + ===== ==== + +.. table:: **Module Names** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 MODULE_ADC + 1 MODULE_DAC + 2 MODULE_VREF + 3 MODULE_HEADPHONE + 4 MODULE_MIC_BIAS + 5 MODULE_MIC + 6 MODULE_LINE_IN + 7 MODULE_LINE_OUT + 8 MODULE_SPEAKER + 9 MODULE_OMIX + 10 MODULE_MONO_OUT + ===== ==== + +.. table:: **Play Channel Names** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 1 PLAY_HEADPHONE_LEFT + 2 PLAY_HEADPHONE_RIGHT + 4 PLAY_SPEAKER_LEFT + 8 PLAY_SPEAKER_RIGHT + ===== ==== + +.. table:: **adc_sync Parameters** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SYNC_ADC + 1 SYNC_DAC + ===== ==== + + +Methods +------- + +In addition to initialization, the driver provides some useful methods for +controlling its operation: + +.. method:: WM8960.set_left_input(input_source) + + Specify the source for the left input. The input source names are listed above. + +.. method:: WM8960.set_right_input(input_source) + + Specify the source for the right input. The input source names are listed above. + +.. method:: WM8960.volume(module, volume_l=None, volume_r=None) + + Sets or gets the volume of a certain module. + + If no volume values are supplied, the actual volume tuple is returned. + + If one or two values are supplied, it sets the volume of a certain module. + If two values are provided, the first one is used for the left channel, + the second for the right channel. If only one value is supplied, it is used + for both channels. The value range is normalized to 0.0-100.0 with a + logarithmic scale. + + For a list of suitable modules and db/step, see the table below. + +.. table:: **Module Names and dB steps** + :widths: auto + :align: center + + ======= ==== + dB/Step Name + ======= ==== + 1.28 MODULE_ADC + 1.28 MODULE_DAC + 0.8 MODULE_HEADPHONE + 0.475 MODULE_LINE_IN + 0.8 MODULE_SPEAKER + ======= ==== + +.. method:: WM8960.mute(module, mute, soft=True, ramp=wm8960.MUTE_FAST) + + Mute or unmute the output. If *mute* is True, the output is muted, if ``False`` + it is unmuted. + + If *soft* is set as True, muting will happen as a soft transition. The time for + the transition is defined by *ramp*, which is either ``MUTE_FAST`` or ``MUTE_SLOW``. + +.. method:: WM8960.set_data_route(route) + + Set the audio data route. For the parameter value/names, see the table above. + +.. method:: WM8960.set_module(module, active) + + Enable or disable a module, with *active* being ``False`` or ``True``. For + the list of module names, see the table above. + + Note that enabling ``MODULE_MONO_OUT`` is different from the `WM8960.mono` + method. The first enables output 3, while the `WM8960.mono` method sends a + mono mix to the left and right output. + +.. method:: WM8960.enable_module(module) + + Enable a module. For the list of module names, see the table above. + +.. method:: WM8960.disable_module(module) + + Disable a module. For the list of module names, see the table above. + +.. method:: WM8960.expand_3d(level) + + Enable Stereo 3D expansion. *level* is a number between 0 and 15. + A value of 0 disables the expansion. + +.. method:: WM8960.mono(active) + + If *active* is ``True``, a Mono mix is sent to the left and right output + channel. This is different from enabling the ``MODULE_MONO_MIX``, which + enables output 3. + +.. method:: WM8960.alc_mode(channel, mode=ALC_MODE) + + Enables or disables ALC mode. Parameters are: + + - *channel* enables and sets the channel for ALC. The parameter values are: + + - ALC_OFF: Switch ALC off + - ALS_RIGHT: Use the right input channel + - ALC_LEFT: Use the left input channel + - ALC_STEREO: Use both input channels. + + - *mode* sets the ALC mode. Input values are: + + - ALC_MODE: act as ALC + - ALC_LIMITER: act as limiter. + +.. method:: WM8960.alc_gain(target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78) + + Set the target level, highest and lowest gain levels and the noise gate as dB level. + Permitted ranges are: + + - *target*: -22.5 to -1.5 dB + - *max_gain*: -12 to 30 dB + - *min_gain*: -17 to 25 dB + - *noise_gate*: -78 to -30 dB + + Excess values are limited to the permitted ranges. A value of -78 or less + for *noise_gate* disables the noise gate function. + +.. method:: WM8960.alc_time(attack=24, decay=192, hold=0) + + Set the dynamic characteristic of ALC. The times are given as millisecond + values. Permitted ranges are: + + - *attack*: 6 to 6140 + - *decay*: 24 to 24580 + - *hold*: 0 to 43000 + + Excess values are limited within the permitted ranges. + +.. method:: WM8960.deemphasis(active) + + Enables or disables a deemphasis filter for playback, with *active* being + ``False`` or ``True``. This filter is applied only for sample rates of + 32000, 44100 and 48000. For other sample rates, the filter setting + is silently ignored. + +.. method:: WM8960.deinit() + + Disable all modules. + + +Examples +-------- + +Run WM8960 in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Slave mode using the default settings + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, 32000, left_input=wm8960.INPUT_MIC1) + wm.set_volume(wm8960.MODULE_HEADPHONE, 100) + + +Run WM8960 in primary mode:: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Master mode using specific audio format settings + # + from machine import Pin, I2C + import wm8960 + + i2c = I2C(0) + wm=wm8960.WM8960(i2c, 44100, primary=True, bits=16) + + +Run WM8960 on a MIMXRT10xx_DEV board in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Slave mode using the default settings + # swap the input channels such that a MIMXRT Dev board mic, which + # is connected to the right input, is assigned to the left audio channel. + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, sample_rate=16_000, + adc_sync=wm8960.SYNC_DAC, + swap=wm8960.SWAP_INPUT, + sysclk_source=wm8960.SYSCLK_MCLK) + + +Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # The breakout board uses a fixed 24MHz MCLK. Therefore the internal + # PLL must be used as sysclk, which is the master audio clock. + # The Sparkfun board has the WS pins for RX and TX connected on the + # board. Therefore adc_sync must be set to sync_adc, to configure + # it's ADCLRC pin as input. + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, sample_rate=16_000, + adc_sync=wm8960.SYNC_ADC, + sysclk_source=wm8960.SYSCLK_PLL, + mclk_freq=24_000_000, + left_input=wm8960.INPUT_MIC1, + right_input=wm8960.INPUT_CLOSED) + + +Play with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):: + + # The breakout board uses a fixed 24MHz MCLK. Therefore the internal + # PLL must be used as sysclk, which is the master audio clock. + # The Sparkfun board has the WS pins for RX and TX connected on the + # board. Therefore adc_sync must be set to sync_adc, to configure + # it's ADCLRC pin as input. + + from machine import I2C + i2c=I2C(0) + import wm8960 + wm=wm8960.WM8960(i2c, sample_rate=44_100, + adc_sync=wm8960.SYNC_ADC, + sysclk_source=wm8960.SYSCLK_PLL, + mclk_freq=24_000_000) + wm.set_volume(wm8960.MODULE_HEADPHONE, 100) diff --git a/docs/library/zephyr.DiskAccess.rst b/docs/library/zephyr.DiskAccess.rst index d19d81a962e23..e5eac8ca4988b 100644 --- a/docs/library/zephyr.DiskAccess.rst +++ b/docs/library/zephyr.DiskAccess.rst @@ -34,5 +34,5 @@ Methods These methods implement the simple and extended :ref:`block protocol ` defined by - :class:`uos.AbstractBlockDev`. + :class:`vfs.AbstractBlockDev`. diff --git a/docs/library/zephyr.FlashArea.rst b/docs/library/zephyr.FlashArea.rst index 306347d449eab..749b90a3b43c5 100644 --- a/docs/library/zephyr.FlashArea.rst +++ b/docs/library/zephyr.FlashArea.rst @@ -37,4 +37,4 @@ Methods These methods implement the simple and extended :ref:`block protocol ` defined by - :class:`uos.AbstractBlockDev`. + :class:`vfs.AbstractBlockDev`. diff --git a/docs/library/zephyr.rst b/docs/library/zephyr.rst index da3d14a093ecf..10676d9085289 100644 --- a/docs/library/zephyr.rst +++ b/docs/library/zephyr.rst @@ -32,7 +32,7 @@ Functions * *CPU utilization is only printed if runtime statistics are configured via the ``CONFIG_THREAD_RUNTIME_STATS`` kconfig* This function can only be accessed if ``CONFIG_THREAD_ANALYZER`` is configured for the port in ``zephyr/prj.conf``. - For more infomation, see documentation for Zephyr `thread analyzer + For more information, see documentation for Zephyr `thread analyzer `_. .. function:: shell_exec(cmd_in) diff --git a/docs/library/zlib.rst b/docs/library/zlib.rst index 96d6c245232ba..54310b72f2a3d 100644 --- a/docs/library/zlib.rst +++ b/docs/library/zlib.rst @@ -1,38 +1,82 @@ -:mod:`zlib` -- zlib decompression -================================= +:mod:`zlib` -- zlib compression & decompression +=============================================== .. module:: zlib - :synopsis: zlib decompression + :synopsis: zlib compression & decompression |see_cpython_module| :mod:`python:zlib`. -This module allows to decompress binary data compressed with +This module allows compression and decompression of binary data with the `DEFLATE algorithm `_ -(commonly used in zlib library and gzip archiver). Compression -is not yet implemented. +(commonly used in the zlib library and gzip archiver). + +.. note:: Prefer to use :class:`deflate.DeflateIO` instead of the functions in this + module as it provides a streaming interface to compression and decompression + which is convenient and more memory efficient when working with reading or + writing compressed data to a file, socket, or stream. + +**Availability:** + +* From MicroPython v1.21 onwards, this module may not be present by default on + all MicroPython firmware as it duplicates functionality available in + the :mod:`deflate ` module. + +* A copy of this module can be installed (or frozen) + from :term:`micropython-lib` (`source `_). + See :ref:`packages` for more information. This documentation describes that module. + +* Requires the built-in :mod:`deflate ` module (available since MicroPython v1.21) + +* Compression support will only be available if compression support is enabled + in the built-in :mod:`deflate ` module. Functions --------- -.. function:: decompress(data, wbits=0, bufsize=0, /) +.. function:: decompress(data, wbits=15, /) + + Decompresses *data* into a bytes object. + + The *wbits* parameter works the same way as for :meth:`zlib.compress` + with the following additional valid values: + + * ``0``: Automatically determine the window size from the zlib header + (*data* must be in zlib format). + * ``35`` to ``47``: Auto-detect either the zlib or gzip format. + + As for :meth:`zlib.compress`, see the :mod:`CPython documentation for zlib ` + for more information about the *wbits* parameter. As for :meth:`zlib.compress`, + MicroPython also supports smaller window sizes than CPython. See more + :ref:`MicroPython-specific details ` in the + :mod:`deflate ` module documentation. + + If the data to be decompressed requires a larger window size, it will + fail during decompression. + +.. function:: compress(data, wbits=15, /) - Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window - size used during compression (8-15, the dictionary size is power of 2 of - that value). Additionally, if value is positive, *data* is assumed to be - zlib stream (with zlib header). Otherwise, if it's negative, it's assumed - to be raw DEFLATE stream. *bufsize* parameter is for compatibility with - CPython and is ignored. + Compresses *data* into a bytes object. -.. class:: DecompIO(stream, wbits=0, /) + *wbits* allows you to configure the DEFLATE dictionary window size and the + output format. The window size allows you to trade-off memory usage for + compression level. A larger window size will allow the compressor to + reference fragments further back in the input. The output formats are "raw" + DEFLATE (no header/footer), zlib, and gzip, where the latter two + include a header and checksum. - Create a `stream` wrapper which allows transparent decompression of - compressed data in another *stream*. This allows to process compressed - streams with data larger than available heap size. In addition to - values described in :func:`decompress`, *wbits* may take values - 24..31 (16 + 8..15), meaning that input stream has gzip header. + The low four bits of the absolute value of *wbits* set the base-2 logarithm of + the DEFLATE dictionary window size. So for example, ``wbits=10``, + ``wbits=-10``, and ``wbits=26`` all set the window size to 1024 bytes. Valid + window sizes are ``5`` to ``15`` inclusive (corresponding to 32 to 32k bytes). - .. admonition:: Difference to CPython - :class: attention + Negative values of *wbits* between ``-5`` and ``-15`` correspond to "raw" + output mode, positive values between ``5`` and ``15`` correspond to zlib + output mode, and positive values between ``21`` and ``31`` correspond to + gzip output mode. - This class is MicroPython extension. It's included on provisional - basis and may be changed considerably or removed in later versions. + See the :mod:`CPython documentation for zlib ` for more + information about the *wbits* parameter. Note that MicroPython allows + for smaller window sizes, which is useful when memory is constrained while + still achieving a reasonable level of compression. It also speeds up + the compressor. See more :ref:`MicroPython-specific details ` + in the :mod:`deflate ` module documentation. diff --git a/docs/mimxrt/general.rst b/docs/mimxrt/general.rst new file mode 100644 index 0000000000000..35cf8e50eca2a --- /dev/null +++ b/docs/mimxrt/general.rst @@ -0,0 +1,94 @@ +.. _mimxrt_general: + +General information about the MIMXRT port +========================================= + +The i.MXRT MCU family is a high performance family of devices made by NXP. +Based on an ARM7 core, they provide many on-chip I/O units for building +small to medium sized devices. + +Multitude of boards +------------------- + +There is a multitude of modules and boards from different sources which carry +an i.MXRT chip. MicroPython aims to provide a generic port which runs on +as many boards/modules as possible, but there may be limitations. The +NXP IMXRT1020-EVK and the Teensy 4.0 and Teensy 4.1 development boards are taken +as reference for the port (for example, testing is performed on them). +For any board you are using please make sure you have a data sheet, schematics +and other reference materials so you can look up any board-specific functions. + +The following boards are supported by the port: + +- MIMXRT1010-EVK +- MIMXRT1020-EVK +- MIMXRT1050-EVK +- MIMXRT1060-EVK +- MIMXRT1064-EVK +- Teensy 4.0 +- Teensy 4.1 + +Supported MCUs +-------------- + ++-------------+--------------------+-------------------------+ +| Product | CPU | Memory | ++=============+====================+=========================+ +| i.MX RT1064 | Cortex-M7 @600 MHz | 1 MB SRAM, 4 MB Flash | ++-------------+--------------------+-------------------------+ +| i.MX RT1061 | Cortex-M7 @600 MHz | 1 MB SRAM | ++-------------+--------------------+-------------------------+ +| i.MX RT1062 | Cortex-M7 @600 MHz | 1 MB SRAM | ++-------------+--------------------+-------------------------+ +| i.MX RT1050 | Cortex-M7 @600 MHz | 512 kB SRAM | ++-------------+--------------------+-------------------------+ +| i.MX RT1020 | Cortex-M7 @500 MHz | 256 kB SRAM | ++-------------+--------------------+-------------------------+ +| i.MX RT1015 | Cortex-M7 @500 MHz | 128 kB SRAM | ++-------------+--------------------+-------------------------+ +| i.MX RT1010 | Cortex-M7 @500 MHz | 128 kB SRAM | ++-------------+--------------------+-------------------------+ + +Note: Most of the controllers do not have internal flash memory. Therefore +their flash capacity is dependent on an external flash chip. + +To make a generic MIMXRT port and support as many boards as possible the +following design and implementation decision were made: + +* GPIO pin numbering is based on the board numbering as well as on the + MCU numbering. Please have the manual/pin diagram of your board at hand + to find correspondence between your board pins and actual i.MXRT pins. +* All MCU pins are supported by MicroPython but not all are usable on any given board. + +Technical specifications and SoC datasheets +------------------------------------------- + +The data sheets and other reference material for i.MXRT chip are available +from the vendor site: https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus:IMX-RT-SERIES . +They are the primary reference for the chip technical specifications, capabilities, +operating modes, internal functioning, etc. + +For your convenience, a few technical specifications are provided below: + +* Architecture: ARM Cortex M7 +* CPU frequency: up to 600MHz +* Total RAM available: up to 1 MByte (see table) +* BootROM: 96KB +* External FlashROM: code and data, via SPI Flash; usual size 2 - 16 MB + Some boards provide additional external RAM and SPI flash. +* GPIO: up to 124 (GPIOs are multiplexed with other functions, including + external FlashROM, UART, etc.) +* UART: 4 or 8 RX/TX UART. Hardware handshaking is supported by the MCU, + but the boards used for testing do not expose the signals. +* SPI: 2 or 4 low power SPI interfaces (software implementation available on every pin) +* I2C: 2 or 4 low power I2C interfaces (software implementation available on every pin) +* I2S: 1 to 3 I2S interfaces +* ADC: one or two 12-bit SAR ADC converters +* Ethernet controller (except i.MX RT1010/-1015) +* Programming: using BootROM bootloader from USB - due to external FlashROM + and always-available BootROM bootloader, the MIMXRT is not brickable + +The lower numbers for UART, SPI and I2C apply to the i.MXRT 101x MCU. + +For more information see the i.MXRT data sheets or reference manuals. +NXP provides software support through it's SDK packages. diff --git a/docs/mimxrt/img/teensy_4.1.jpg b/docs/mimxrt/img/teensy_4.1.jpg new file mode 100644 index 0000000000000..0a09f68ea4f3e Binary files /dev/null and b/docs/mimxrt/img/teensy_4.1.jpg differ diff --git a/docs/mimxrt/pinout.rst b/docs/mimxrt/pinout.rst new file mode 100644 index 0000000000000..16bb4722734a2 --- /dev/null +++ b/docs/mimxrt/pinout.rst @@ -0,0 +1,385 @@ +.. _mimxrt_pinout: + +Pinout for the i.MXRT machine modules +===================================== + +.. _mimxrt_uart_pinout: + +| + +UART pin assignment +------------------- + +The pin assignment of UARTs to pins is fixed. +The UARTs are numbered 0..8. The rx/tx pins are assigned according to the +tables below: + +================= =========== =========== =========== =========== +Board / Pin UART0 UART1 UART2 UART3 +================= =========== =========== =========== =========== +Teensy 4.0 - 0/1 7/8 14/15 +Teensy 4.1 - 0/1 7/8 14/15 +MIMXRT1010-EVK Debug USB D0/D1 D7/D6 - +MIMXRT1015-EVK Debug USB D0/D1 D7/A1 - +MIMXRT1020-EVK Debug USB D0/D1 D9/D6 D10/D13 +MIMXRT1050-EVK Debug USB D0/D1 D7/D6 D8/D9 +MIMXRT1050-EVKB Debug USB D0/D1 D7/D6 D8/D9 +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 D7/D8 D5/D6 +Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07 +================= =========== =========== =========== =========== + +| + +================ =========== =========== ======= ======= ===== +Board / Pin UART4 UART5 UART6 UART7 UART8 +================ =========== =========== ======= ======= ===== +Teensy 4.0 16/17 21/20 25/24 28/29 - +Teensy 4.1 16/17 21/20 25/24 28/29 34/35 +MIMXRT1010-EVK - - - - - +MIMXRT1015-EVK - - - - - +MIMXRT1020-EVK D15/D14 A1/A0 - - - +MIMXRT1050-EVK A1/A0 - - - - +MIMXRT1050-EVKB A1/A0 - - - - +MIMXRT1060-EVK A1/A0 - - - - +MIMXRT1064-EVK A1/A0 - - - - +MIMXRT1170-EVK D15/D14 D25/D26 D33/D34 D35/D36 - +Olimex RT1010Py - - - - - +Seeed ARCH MIX J4_10/J4_11 J5_08/J5_12 - - - +================ =========== =========== ======= ======= ===== + +.. _mimxrt_pwm_pinout: + +| +| + +PWM pin assignment +------------------ + +Pins are specified in the same way as for the Pin class. The following tables show +the assignment of the board Pins to PWM modules: + +=========== ========== ========== ====== ========== ====== ======== +Pin/ MIMXRT 1010 1015 1020 1050/60/64 1170 Metro M7 +=========== ========== ========== ====== ========== ====== ======== +D0 - Q1/1 F1/1/B - - - +D1 - Q1/0 F1/1/A - - - +D2 F1/3/B F1/3/A - F1/3/B - - +D3 F1/3/A F1/0/A F2/3/B F4/0/A F1/2/A - +D4 F1/3/A (*) Q1/2 Q2/1 F2/3/A Q4/2 F1/0/B +D5 F1/0/B (*) F1/0/B F2/3/A F1/3/A F1/2/B F1/0/A +D6 - F1/2/B F2/0/A Q3/2 F1/0/A - +D7 - - F1/0/A Q3/3 - - +D8 F1/0/A F1/1/B F1/0/B F1/1/X Q4/3 F1/3/A +D9 F1/1/B (*) F1/2/A F2/0/B F1/0/X F1/0/B F1/3/B +D10 F1/3/B - F2/2/B F1/0/B (*) F2/2/B F1/2/A +D11 F1/2/A - F2/1/A F1/1/A (*) - F1/2/B +D12 F1/2/B - F2/1/B F1/1/B (*) - F1/1/A +D13 F1/3/A - F2/2/A F1/0/A (*) F2/2/A F1/1/B +D14 F1/0/B - - F2/3/B - F1/0/B +D15 F1/0/A - - F2/3/A - F1/0/A +A0 - - F1/2/A - - - +A1 F1/3/X F1/3/B F1/2/B - - - +A2 F1/2/X F1/3/A F1/3/A - - - +A3 - F1/2/A F1/3/B - - F1/3/B +A4 - - - Q3/1 - F1/2/X +A5 - - - Q3/0 - - +D31 - - - - F1/2/B - +D32 - - - - F1/2/A - +D33 - - - - F1/1/B - +D34 - - - - F1/1/A - +D35 - - - - F1/0/B - +D36 - - - - F1/0/A - +=========== ========== ========== ====== ========== ====== ======== + +Pins denoted with (*) are by default not wired at the board. + +==== ========== ==== ========== +Pin Teensy 4.0 Pin Teensy 4.1 +==== ========== ==== ========== +0 F1/1/X 0 F1/1/X +1 F1/0/X 1 F1/0/X +2 F4/2/A 2 F4/2/A +3 F4/2/B 3 F4/2/B +4 F2/0/A 4 F2/0/A +5 F2/1/A 5 F2/1/A +6 F2/2/A 6 F2/2/A +7 F1/3/B 7 F1/3/B +8 F1/3/A 8 F1/3/A +9 F2/2/B 9 F2/2/B +10 Q1/0 10 Q1/0 +11 Q1/2 11 Q1/2 +12 Q1/1 12 Q1/1 +13 Q2/0 13 Q2/0 +14 Q3/2 14 Q3/2 +15 Q3/3 15 Q3/3 +18 Q3/1 18 Q3/1 +19 Q3/0 19 Q3/0 +22 F4/0/A 22 F4/0/A +23 F4/1/A 23 F4/1/A +24 F1/2/X 24 F1/2/X +25 F1/3/X 25 F1/3/X +28 F3/1/B 28 F3/1/B +29 F3/1/A 29 F3/1/A +33 F2/0/B 33 F2/0/B +- - 36 F2/3/A +- - 37 F2/3/B +DAT1 F1/1/B 42 F1/1/B +DAT0 F1/1/A 43 F1/1/A +CLK F1/0/B 44 F1/0/B +CMD F1/0/A 45 F1/0/A +DAT2 F1/2/A 46 F1/2/A +DAT3 F1/2/B 47 F1/2/B +- - 48 F1/0/B +- - 49 F1/2/A +- - 50 F1/2/B +- - 51 F3/3/B +- - 52 F1/1/B +- - 53 F1/1/A +- - 54 F3/0/A +==== ========== ==== ========== + +| + +========= ============== +Pin Seeed ARCH MIX +========= ============== +J3_04 Q4/3 +J3_10 Q1/3 +J3_12 Q2/3 +J3_13 Q3/3 +J3_16 Q3/0 +J3_17 Q3/1 +J3_19 F1/3/X +J3_20 F1/2/X +J4_08 F4/0/A +J4_09 F4/1/A +J4_16 Q3/2 +J4_17 Q3/3 +J5_32 Q1/0 +J5_28 Q1/1 +J5_29 Q1/2 +J5_30 Q2/0 +J5_04 Q2/1 +J5_05 Q2/3 +J5_06 F2/0/A +J5_07 F2/0/B +J5_08 F2/1/A +J5_12 F2/1/B +J5_13 F2/2/A +J5_14 F2/2/B +J5_23 F1/3/A +J5_24 F1/3/B +J5_25 F2/3/A +J5_26 F2/3/B +J5_42 Q3/0 +J5_43 Q3/1 +J5_50 F1/0/X +LED_RED F2/3/A +LED_GREEN F1/3/A +LED_BLUE F1/3/B +========= ============== + +| + +========= =============== +Pin Olimex RT1010PY +========= =============== +D0 - +D1 F1/0/B +D2 F1/0/A +D3 F1/1/B +D4 F1/1/A +D5 F1/2/B +D6 F1/2/A +D7 F1/3/B +D8 F1/3/A +D9 - +D10 F1/0/B +D11 F1/0/A +D12 F1/1/B +D13 F1/1/A +D14 - +A0 - +A1 F1/2/B +A2 F1/2/A +A3 F1/3/B +A4 F1/3/A +SDI F1/3/X +SDO F1/2/X +CS0 F1/1/X +SCK F1/0/X +========= =============== + +Legend: + +* Qm/n: QTMR module m, channel n +* Fm/n/l: FLEXPWM module m, submodule n, channel l. The pulse at a X channel + is always aligned to the period start. + +Pins without a PWM signal are not listed. A signal may be available at more +than one Pin. FlexPWM pins may also be pure CPU pin, not assigned to a board +signal. In that case the PWM output is disabled. The PWM channel of a submodule +0 may still be used as synchronization source for other channels of the same +module, unless used by another peripheral. + +Submodule 0 pins for i.MX RT1011: + +================== ======= +Pin Channel +================== ======= +Pin.cpu.GPIO_01 B +Pin.cpu.GPIO_02 A +Pin.cpu.GPIO_AD_12 X +Pin.cpu.GPIO_SD_01 B +Pin.cpu.GPIO_SD_02 A +================== ======= + +Submodule 0 pins for i.MX RT1021: + +===================== ================== +Pin Module & Channel +===================== ================== +Pin.cpu.GPIO_AD_B1_06 FLEXPWM1 Channel A +Pin.cpu.GPIO_AD_B1_07 FLEXPWM1 Channel B +Pin.cpu.GPIO_EMC_26 FLEXPWM1 Channel A +Pin.cpu.GPIO_EMC_27 FLEXPWM1 Channel B +Pin.cpu.GPIO_AD_B0_14 FLEXPWM2 Channel A +Pin.cpu.GPIO_AD_B0_15 FLEXPWM2 Channel B +Pin.cpu.GPIO_EMC_10 FLEXPWM2 Channel X +Pin.cpu.GPIO_EMC_38 FLEXPWM2 Channel A +Pin.cpu.GPIO_EMC_39 FLEXPWM2 Channel B +===================== ================== + +Submodule 0 pins for i.MX RT1052, i.MX RT1062 and i.MX RT1064: + +===================== ================== +Pin Module & Channel +===================== ================== +Pin.cpu.GPIO_AD_B0_02 FLEXPWM1 Channel X +Pin.cpu.GPIO_EMC_23 FLEXPWM1 Channel A +Pin.cpu.GPIO_EMC_24 FLEXPWM1 Channel B +Pin.cpu.GPIO_SD_B0_00 FLEXPWM1 Channel A +Pin.cpu.GPIO_SD_B0_01 FLEXPWM1 Channel B +Pin.cpu.GPIO_B0_06 FLEXPWM2 Channel A +Pin.cpu.GPIO_B0_07 FLEXPWM2 Channel B +Pin.cpu.GPIO_EMC_06 FLEXPWM2 Channel A +Pin.cpu.GPIO_EMC_07 FLEXPWM2 Channel B +Pin.cpu.GPIO_EMC_29 FLEXPWM3 Channel A +Pin.cpu.GPIO_EMC_30 FLEXPWM3 Channel B +Pin.cpu.GPIO_AD_B1_08 FLEXPWM4 Channel A +Pin.cpu.GPIO_EMC_00 FLEXPWM4 Channel A +Pin.cpu.GPIO_EMC_01 FLEXPWM4 Channel B +===================== ================== + +Submodule 0 pins for i.MX RT1176 + +====================== ====================== +Pin Module & Channel +====================== ====================== +Pin.cpu.GPIO_EMC_B1_00 FLEXPWM4 Channel A (*) +Pin.cpu.GPIO_EMC_B1_01 FLEXPWM4 Channel B (*) +Pin.cpu.GPIO_EMC_B1_06 FLEXPWM2 Channel A (*) +Pin.cpu.GPIO_EMC_B1_07 FLEXPWM2 Channel B (*) +Pin.cpu.GPIO_EMC_B1_23 FLEXPWM1 Channel A (*) +Pin.cpu.GPIO_EMC_B1_24 FLEXPWM1 Channel B (*) +Pin.cpu.GPIO_EMC_B1_29 FLEXPWM3 Channel A (*) +Pin.cpu.GPIO_EMC_B1_30 FLEXPWM3 Channel B (*) +Pin.cpu.GPIO_AD_00 FLEXPWM1 Channel A +Pin.cpu.GPIO_AD_01 FLEXPWM1 Channel B +Pin.cpu.GPIO_AD_24 FLEXPWM2 Channel A +Pin.cpu.GPIO_AD_25 FLEXPWM2 Channel B +====================== ====================== + +.. _mimxrt_spi_pinout: + +| +| + +Hardware SPI pin assignment +--------------------------- + +The SPI signals have fixed assignments to GPIO pins. +It depends on the board design, which SPI's signals are exposed to the user, as +detailed in the table below. The signal order in the table is: CS0, CS1, MOSI, MISO, CLK. + +================= ========================= ======================= =============== +Board / Pin SPI0 SPI1 SPI2 +================= ========================= ======================= =============== +Teensy 4.0 10/-/11/12/13 0/-/26/1/27 - +Teensy 4.1 10/37/11/12/13 0/-/26/1/27 -/29/50/54/49 +MIXMXRT1010-EVK D10/D7/D11/D12/D13 - - +MIXMXRT1015-EVK D10/-/D11/D12/D13 - - +MIXMXRT1020-EVK D10/-/D11/D12/D13 A3/D0/A5/A4/A0 - +MIXMXRT1050-EVK D10/-/D11/D12/D13 (*) - - +MIXMXRT1050-EVKB D10/-/D11/D12/D13 (*) - - +MIXMXRT1060-EVK D10/-/D11/D12/D13 (*) - - +MIXMXRT1064-EVK D10/-/D11/D12/D13 (*) - - +MIXMXRT1170-EVK D10/-/D11/D12/D13 D28/-/D25/D24/D26 -/-/D14/D15/D24 +Adafruit Metro M7 -/-/MOSI/MISO/SCK - - +Olimex RT1010Py - CS0/-/SDO/SDI/SCK SDCARD with CS1 +Seeed ARCH MIX J4_12/-/J4_14/J4_13/J4_15 J3_09/J3_05/J3_08_J3_11 +================= ========================= ======================= =============== + +Pins denoted with (*) are by default not wired at the board. The CS0 and CS1 signals +are enabled with the keyword option cs=0 or cs=1 of the SPI object constructor. + +.. _mimxrt_i2c_pinout: + +| +| + +Hardware I2C pin assignment +--------------------------- + +The I2C signals have fixed assignments to GPIO pins. +It depends on the board design, which I2C's signals are exposed to the user, as +detailed in the table below. The signal order in the table is: SDA, SCL. + +================= =========== =========== =========== ======= ======= +Board / Pin I2C 0 I2C 1 I2C 2 I2C 3 I2C 4 +================= =========== =========== =========== ======= ======= +Teensy 4.0 18/19 17/16 25/24 - - +Teensy 4.1 18/19 17/16 25/24 - - +MIXMXRT1010-EVK D14/D15 D0/D1 - - - +MIXMXRT1015-EVK D14/D15 - - - - +MIXMXRT1020-EVK D14/D15 A4/A5 D0/D1 - - +MIXMXRT1050-EVK A4/A5 D1/D0 - - - +MIXMXRT1050-EVKB A4/A5 D1/D0 - - - +MIXMXRT1060-EVK A4/A5 D1/D0 - - - +MIXMXRT1064-EVK A4/A5 D1/D0 - - - +MIXMXRT1170-EVK D14/D15 D1/D0 A4/A5 D26/D25 D19/D18 +Adafruit Metro M7 D14/D15 D0/D1 +Olimex RT1010Py - SDA1/SCL1 SDA2/SCL2 - - +Seeed ARCH MIX J3_17/J3_16 J4_06/J4_07 J5_05/J5_04 - - +================= =========== =========== =========== ======= ======= + +.. _mimxrt_i2s_pinout: + +| +| + +Hardware I2S pin assignment +--------------------------- + +Pin assignments for a few MIMXRT boards: + +================= == ===== ======== ======= ======= ======== ======= ======= +Board ID MCK SCK_TX WS_TX SD_TX SCK_RX WS_RX SD_RX +================= == ===== ======== ======= ======= ======== ======= ======= +Teensy 4.0 1 23 26 27 7 21 20 8 +Teensy 4.0 2 33 4 3 2 - - 5 +Teensy 4.1 1 23 26 27 7 21 20 8 +Teensy 4.1 2 33 4 3 2 - - 5 +Seeed Arch MIX 1 J4_09 J4_14 J4_15 J14_13 J4_11 J4_10 J4_10 +Adafruit Metro M7 1 D8 D10 D9 D12 D14 D15 D13 +Olimex RT1010Py 1 D8 D6 D7 D4 D1 D2 D3 +Olimex RT1010Py 3 - D10 D9 D11 - - - +MIMXRT_DEV 1 "MCK" "SCK_TX" "WS_TX" "SD_TX" "SCK_RX" "WS_RX" "SD_RX" +================= == ===== ======== ======= ======= ======== ======= ======= + +Symbolic pin names are provided for the MIMXRT_10xx_DEV boards. +These are provided for the other boards as well. diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst new file mode 100644 index 0000000000000..519313438321c --- /dev/null +++ b/docs/mimxrt/quickref.rst @@ -0,0 +1,549 @@ +.. _mimxrt_quickref: + +Quick reference for the i.MXRT family +===================================== + +.. image:: img/teensy_4.1.jpg + :alt: Teensy 4.1 board + :width: 640px + +The Teensy 4.1 board. + +Below is a quick reference for i.MXRT-based boards. If it is your first time +working with this board it may be useful to get an overview of the microcontroller: + +.. toctree:: + :maxdepth: 1 + + general.rst + tutorial/intro.rst + pinout.rst + + +Installing MicroPython +---------------------- + +See the corresponding section of tutorial: :ref:`mimxrt_intro`. It also includes +a troubleshooting subsection. + +General board control +--------------------- + +The MicroPython REPL is on the USB port, configured in VCP mode. +Tab-completion is useful to find out what methods an object has. +Paste mode (ctrl-E) is useful to paste a large slab of Python code into +the REPL. + +The :mod:`machine` module:: + + import machine + + machine.freq() # get the current frequency of the CPU + +Delay and timing +---------------- + +Use the :mod:`time