diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 690e5f46a4fc0..195e1e06eea46 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,3 +1,12 @@
+# all: Prune trailing whitespace.
+dda9b9c6da5d3c31fa8769e581a753e95a270803
+
+# all: Remove the "STATIC" macro and just use "static" instead.
+decf8e6a8bb940d5829ca3296790631fcece7b21
+
+# renesas-ra: Fix spelling mistakes found by codespell.
+b3f2f18f927fa2fad10daf63d8c391331f5edf58
+
# all: Update Python formatting to ruff-format.
bbd8760bd9a2302e5abee29db279102bb11d7732
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 7bad9562964af..0000000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-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/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000000..1ec6c7067f9cd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,109 @@
+name: Bug report
+description: Report a bug or unexpected behaviour
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Please provide as much detail as you can, it really helps us find and fix bugs faster.
+
+ #### Not a bug report?
+
+ * If you have a question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
+ * For missing or incorrect documentation, or feature requests, then please [choose a different issue type](https://github.com/micropython/micropython/issues/new/choose).
+
+ #### Existing issue?
+
+ * Please search for [existing issues](https://github.com/micropython/micropython/issues) matching this bug before reporting.
+ - type: input
+ id: port-board-hw
+ attributes:
+ label: Port, board and/or hardware
+ description: |
+ Which MicroPython port(s) and board(s) are you using?
+ placeholder: |
+ esp32 port, ESP32-Fantastic board.
+ validations:
+ required: true
+ - type: textarea
+ id: version
+ attributes:
+ label: MicroPython version
+ description: |
+ To find the version:
+
+ 1. Open a serial REPL.
+ 2. Type Ctrl-B to see the startup message.
+ 3. Copy-paste that output here.
+
+ If the issue is about building MicroPython, please provide output of `git describe --dirty` and as much information as possible about the build environment.
+
+ If the version or configuration is modified from the official MicroPython releases or the master branch, please tell us the details of this as well.
+ placeholder: |
+ MicroPython v6.28.3 on 2029-01-23; PyBoard 9 with STM32F9
+ validations:
+ required: true
+ - type: textarea
+ id: steps-reproduce
+ attributes:
+ label: Reproduction
+ description: |
+ What steps will reproduce the problem? Please include all details that could be relevant about the environment, configuration, etc.
+
+ If there is Python code to reproduce this issue then please either:
+ a. Type it into a code block below ([code block guide](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks)), or
+ b. Post longer code to a [GitHub gist](https://gist.github.com/), or
+ c. Create a sample project on GitHub.
+
+ For build issues, please provide the exact build commands that you ran.
+ placeholder: |
+ 1. Copy paste the code provided below into a new file
+ 2. Use `mpremote run` to execute it on the board.
+ validations:
+ required: true
+ - type: textarea
+ id: expected
+ attributes:
+ label: Expected behaviour
+ description: |
+ What did you expect MicroPython to do? If comparing output with CPython or a different MicroPython port/version then please provide that output here.
+ placeholder: |
+ Expected to print "Hello World".
+
+ Here is the correct output, seen with previous MicroPython version v3.14.159:
+
+ > [...]
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: Observed behaviour
+ description: |
+ What actually happened? Where possible please paste exact output, or the complete build log, etc. Very long output can be linked in a [GitHub gist](https://gist.github.com/).
+ placeholder: |
+ This unexpected exception appears:
+
+ > [...]
+ validations:
+ required: true
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional Information
+ description: |
+ Is there anything else that might help to resolve this issue?
+ value: No, I've provided everything above.
+ - type: dropdown
+ id: code-of-conduct
+ attributes:
+ label: Code of Conduct
+ description: |
+ Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
+ options:
+ - "Yes, I agree"
+ multiple: true
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to help improve MicroPython.
diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md
deleted file mode 100644
index e36fa62ac29a4..0000000000000
--- a/.github/ISSUE_TEMPLATE/documentation.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-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/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml
new file mode 100644
index 0000000000000..93051e51c80c7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/documentation.yml
@@ -0,0 +1,46 @@
+name: Documentation issue
+description: Report areas of the documentation or examples that need improvement
+title: "docs: "
+labels: ["documentation"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ This form is for reporting issues with the documentation or examples provided with MicroPython.
+
+ If you have a general question \"How Do I ...?\", please post it on [GitHub Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead of here.
+
+ #### Existing issue?
+
+ * Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one.
+ - type: input
+ id: page
+ attributes:
+ label: Documentation URL
+ description: |
+ Does this issue relate to a particular page in the [online documentation](https://docs.micropython.org/en/latest/)? If yes, please paste the URL of the page:
+ placeholder: |
+ https://docs.micropython.org/en/latest/
+ - type: textarea
+ id: version
+ attributes:
+ label: Description
+ description: |
+ Please describe what was missing from the documentation and/or what was incorrect/incomplete.
+ validations:
+ required: true
+ - type: dropdown
+ id: code-of-conduct
+ attributes:
+ label: Code of Conduct
+ description: |
+ Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
+ options:
+ - "Yes, I agree"
+ multiple: true
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to help improve MicroPython.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 81b55d98e0da8..0000000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-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/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000000000..7d5162a32a4af
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,74 @@
+name: Feature request
+description: Request a feature or improvement
+labels: ['enhancement']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ This form is for requesting features or improvements in MicroPython.
+
+ #### Get feedback first
+
+ Before submitting a new feature idea here, suggest starting a discussion on [Discord](https://discord.gg/RB8HZSAExQ) or [GitHub Discussions](https://github.com/orgs/micropython/discussions/) to get early feedback from the community and maintainers.
+
+ #### Not a MicroPython core feature?
+
+ * If you have a question \"How Do I ...?\", please post it on GitHub Discussions or Discord instead of here.
+ * Could this feature be implemented as a pure Python library? If so, please open the request on the [micropython-lib repository](https://github.com/micropython/micropython-lib/issues) instead.
+
+ #### Existing issue?
+
+ * Please search for [existing issues](https://github.com/micropython/micropython/issues) before opening a new one.
+ - type: textarea
+ id: feature
+ attributes:
+ label: Description
+ description: |
+ Describe the feature you'd like to see added to MicroPython. What does this feature enable and why is it useful?
+
+ * For core Python features, where possible please include a link to the relevant PEP or CPython documentation.
+ * 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 to, 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.
+
+ If there is an existing discussion somewhere about this feature, please add a link to it as well.
+ validations:
+ required: true
+ - type: textarea
+ id: size
+ attributes:
+ label: Code Size
+ description: |
+ MicroPython aims to strike a balance between functionality and code size. Can this feature be optionally enabled?
+
+ If you believe the usefulness of this feature would outweigh the additional code size, please explain. (It's OK to say you're unsure here, we're happy to discuss this with you.)
+ - type: dropdown
+ id: implementation
+ attributes:
+ label: Implementation
+ description: |
+ What is your suggestion for implementing this feature?
+
+ (See also: [How to sponsor](https://github.com/sponsors/micropython#sponsors), [How to submit a Pull Request](https://github.com/micropython/micropython/wiki/ContributorGuidelines).)
+ options:
+ - I hope the MicroPython maintainers or community will implement this feature
+ - I intend to implement this feature and would submit a Pull Request if desirable
+ - I would like to sponsor development of this feature
+ multiple: true
+ validations:
+ required: true
+ - type: dropdown
+ id: code-of-conduct
+ attributes:
+ label: Code of Conduct
+ description: |
+ Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
+ options:
+ - "Yes, I agree"
+ multiple: true
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to suggest improvements for MicroPython.
diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md
deleted file mode 100644
index cfe4a4befdb14..0000000000000
--- a/.github/ISSUE_TEMPLATE/security.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-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/ISSUE_TEMPLATE/security.yml b/.github/ISSUE_TEMPLATE/security.yml
new file mode 100644
index 0000000000000..57c2a5885ed85
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/security.yml
@@ -0,0 +1,60 @@
+name: Security report
+description: Report a security issue or vulnerability in MicroPython
+labels: ["security"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ This form is for reporting security issues in MicroPython that are not readily exploitable.
+
+ 1. For issues that are readily exploitable or have high impact, please email contact@micropython.org instead.
+ 1. If this is a question about security, please ask it in [Discussions](https://github.com/orgs/micropython/discussions/) or [Discord](https://discord.gg/RB8HZSAExQ) instead.
+
+ #### Existing issue?
+
+ * Please search for [existing issues](https://github.com/micropython/micropython/issues) before reporting a new one.
+
+ - type: input
+ id: port-board-hw
+ attributes:
+ label: Port, board and/or hardware
+ description: |
+ Which MicroPython port(s) and board(s) are you using?
+ placeholder: |
+ esp32 port, ESP32-Duper board.
+ - type: textarea
+ id: version
+ attributes:
+ label: MicroPython version
+ description: |
+ To find the version:
+
+ 1. Open a serial REPL.
+ 2. Type Ctrl-B to see the startup message.
+ 3. Copy-paste that output here.
+
+ If the version or configuration is modified from the official MicroPython releases or the master branch, please tell us the details of this as well.
+ placeholder: |
+ MicroPython v6.28.3 on 2029-01-23; PyBoard 9 with STM32F9
+ - type: textarea
+ id: report
+ attributes:
+ label: Issue Report
+ description: |
+ Please provide a clear and concise description of the security issue.
+
+ * What does this issue allow an attacker to do?
+ * How does the attacker exploit this issue?
+ validations:
+ required: true
+ - type: dropdown
+ id: code-of-conduct
+ attributes:
+ label: Code of Conduct
+ description: |
+ Do you agree to follow the MicroPython [Code of Conduct](https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md) to ensure a safe and respectful space for everyone?
+ options:
+ - "Yes, I agree"
+ multiple: true
+ validations:
+ required: true
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000000..e11cebddb3710
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,33 @@
+
+
+### Summary
+
+
+
+
+### Testing
+
+
+
+
+### Trade-offs and Alternatives
+
+
+
diff --git a/.github/workflows/biome.yml b/.github/workflows/biome.yml
new file mode 100644
index 0000000000000..88744f16ca7d6
--- /dev/null
+++ b/.github/workflows/biome.yml
@@ -0,0 +1,16 @@
+name: JavaScript code lint and formatting with Biome
+
+on: [push, pull_request]
+
+jobs:
+ eslint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Biome
+ uses: biomejs/setup-biome@v2
+ with:
+ version: 1.5.3
+ - name: Run Biome
+ run: biome ci --indent-style=space --indent-width=4 tests/ ports/webassembly
diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml
index 5cd7984f7ac15..9f30f048cfdbe 100644
--- a/.github/workflows/code_formatting.yml
+++ b/.github/workflows/code_formatting.yml
@@ -18,13 +18,3 @@ jobs:
run: source tools/ci.sh && ci_c_code_formatting_run
- name: Check code formatting
run: git diff --exit-code
-
- code-spelling:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
- - name: Install packages
- run: source tools/ci.sh && ci_code_spell_setup
- - name: Run spell checker
- run: source tools/ci.sh && ci_code_spell_run
diff --git a/.github/workflows/code_size.yml b/.github/workflows/code_size.yml
index a65a00201a7d2..67261933798cb 100644
--- a/.github/workflows/code_size.yml
+++ b/.github/workflows/code_size.yml
@@ -1,16 +1,21 @@
name: Check code size
on:
- push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
+ - 'shared/**'
- 'lib/**'
- 'ports/bare-arm/**'
+ - 'ports/mimxrt/**'
- 'ports/minimal/**'
+ - 'ports/rp2/**'
+ - 'ports/samd/**'
+ - 'ports/stm32/**'
+ - 'ports/unix/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -18,7 +23,7 @@ concurrency:
jobs:
build:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
diff --git a/.github/workflows/code_size_comment.yml b/.github/workflows/code_size_comment.yml
index a394f7a14b054..521afad709d17 100644
--- a/.github/workflows/code_size_comment.yml
+++ b/.github/workflows/code_size_comment.yml
@@ -11,7 +11,7 @@ concurrency:
jobs:
comment:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: 'Download artifact'
id: download-artifact
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
new file mode 100644
index 0000000000000..1d6b1dc9d2b27
--- /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.4.1 tomli
+ - run: codespell
+
diff --git a/.github/workflows/commit_formatting.yml b/.github/workflows/commit_formatting.yml
index 3fdcabc4ca73f..fcbcaa7092ee2 100644
--- a/.github/workflows/commit_formatting.yml
+++ b/.github/workflows/commit_formatting.yml
@@ -1,6 +1,6 @@
name: Check commit message formatting
-on: [push, pull_request]
+on: [pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
- fetch-depth: '100'
+ fetch-depth: 100
- uses: actions/setup-python@v5
- name: Check commit message formatting
run: source tools/ci.sh && ci_commit_formatting_run
diff --git a/.github/workflows/mpy_format.yml b/.github/workflows/mpy_format.yml
index baa02ce08d507..b6768a46c3cdc 100644
--- a/.github/workflows/mpy_format.yml
+++ b/.github/workflows/mpy_format.yml
@@ -15,7 +15,7 @@ concurrency:
jobs:
test:
- runs-on: ubuntu-20.04 # use 20.04 to get python2
+ runs-on: ubuntu-22.04 # use 22.04 to get python2
steps:
- uses: actions/checkout@v4
- name: Install packages
diff --git a/.github/workflows/ports_qemu-arm.yml b/.github/workflows/ports_alif.yml
similarity index 51%
rename from .github/workflows/ports_qemu-arm.yml
rename to .github/workflows/ports_alif.yml
index db3cd7871d591..0e96e7d816e50 100644
--- a/.github/workflows/ports_qemu-arm.yml
+++ b/.github/workflows/ports_alif.yml
@@ -1,4 +1,4 @@
-name: qemu-arm port
+name: alif port
on:
push:
@@ -11,22 +11,23 @@ on:
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- - 'ports/qemu-arm/**'
- - 'tests/**'
+ - 'ports/alif/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
- build_and_test:
+ build_alif:
+ strategy:
+ fail-fast: false
+ matrix:
+ ci_func: # names are functions in ci.sh
+ - alif_ae3_build
runs-on: ubuntu-latest
steps:
- 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 --before-context=100 --text "FAIL" ports/qemu-arm/build/console.out
+ run: source tools/ci.sh && ci_alif_setup
+ - name: Build ci_${{matrix.ci_func }}
+ run: source tools/ci.sh && ci_${{ matrix.ci_func }}
diff --git a/.github/workflows/ports_esp32.yml b/.github/workflows/ports_esp32.yml
index 6872b9d12de78..4c07f89437757 100644
--- a/.github/workflows/ports_esp32.yml
+++ b/.github/workflows/ports_esp32.yml
@@ -25,17 +25,17 @@ jobs:
ci_func: # names are functions in ci.sh
- esp32_build_cmod_spiram_s2
- esp32_build_s3_c3
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- id: idf_ver
- name: Read the ESP-IDF version
- run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
+ name: Read the ESP-IDF version (including Python version)
+ run: source tools/ci.sh && echo "IDF_VER=${IDF_VER}-py${PYTHON_VER}" | tee "$GITHUB_OUTPUT"
- name: Cached ESP-IDF install
id: cache_esp_idf
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: |
./esp-idf/
diff --git a/.github/workflows/ports_mimxrt.yml b/.github/workflows/ports_mimxrt.yml
index 614d7458079e8..7743e036ab377 100644
--- a/.github/workflows/ports_mimxrt.yml
+++ b/.github/workflows/ports_mimxrt.yml
@@ -19,9 +19,14 @@ concurrency:
jobs:
build:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: 'micropython repo' # test build with space in path
steps:
- 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 d9cffb9778cba..76727c9d1f6bd 100644
--- a/.github/workflows/ports_nrf.yml
+++ b/.github/workflows/ports_nrf.yml
@@ -19,7 +19,7 @@ concurrency:
jobs:
build:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
diff --git a/.github/workflows/ports_qemu.yml b/.github/workflows/ports_qemu.yml
new file mode 100644
index 0000000000000..57192c43936e5
--- /dev/null
+++ b/.github/workflows/ports_qemu.yml
@@ -0,0 +1,44 @@
+name: qemu port
+
+on:
+ push:
+ pull_request:
+ paths:
+ - '.github/workflows/*.yml'
+ - 'tools/**'
+ - 'py/**'
+ - 'extmod/**'
+ - 'shared/**'
+ - 'lib/**'
+ - 'drivers/**'
+ - 'ports/qemu/**'
+ - 'tests/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build_and_test_arm:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install packages
+ run: source tools/ci.sh && ci_qemu_setup_arm
+ - name: Build and run test suite
+ run: source tools/ci.sh && ci_qemu_build_arm
+ - name: Print failures
+ if: failure()
+ run: tests/run-tests.py --print-failures
+
+ build_and_test_rv32:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install packages
+ run: source tools/ci.sh && ci_qemu_setup_rv32
+ - name: Build and run test suite
+ run: source tools/ci.sh && ci_qemu_build_rv32
+ - name: Print failures
+ if: failure()
+ run: tests/run-tests.py --print-failures
diff --git a/.github/workflows/ports_renesas-ra.yml b/.github/workflows/ports_renesas-ra.yml
index b1a30c2f11798..b9fa74331dc0b 100644
--- a/.github/workflows/ports_renesas-ra.yml
+++ b/.github/workflows/ports_renesas-ra.yml
@@ -19,7 +19,7 @@ concurrency:
jobs:
build_renesas_ra_board:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
diff --git a/.github/workflows/ports_rp2.yml b/.github/workflows/ports_rp2.yml
index 5741b75d2aa79..748f38e143893 100644
--- a/.github/workflows/ports_rp2.yml
+++ b/.github/workflows/ports_rp2.yml
@@ -20,8 +20,13 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: 'micropython repo' # test build with space in path
steps:
- 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_stm32.yml b/.github/workflows/ports_stm32.yml
index 84d30b27f6e66..8800f145189b8 100644
--- a/.github/workflows/ports_stm32.yml
+++ b/.github/workflows/ports_stm32.yml
@@ -25,7 +25,8 @@ jobs:
ci_func: # names are functions in ci.sh
- stm32_pyb_build
- stm32_nucleo_build
- runs-on: ubuntu-20.04
+ - stm32_misc_build
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install packages
diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml
index 2367eddbe6ea5..2547015038e4d 100644
--- a/.github/workflows/ports_unix.yml
+++ b/.github/workflows/ports_unix.yml
@@ -88,16 +88,17 @@ 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@v3
+ uses: codecov/codecov-action@v5
with:
fail_ci_if_error: true
verbose: true
+ token: ${{ secrets.CODECOV_TOKEN }}
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage_32bit:
- runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386
+ runs-on: ubuntu-22.04 # use 22.04 to get libffi-dev:i386
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -115,7 +116,7 @@ jobs:
run: tests/run-tests.py --print-failures
nanbox:
- runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386
+ runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -141,7 +142,7 @@ jobs:
run: tests/run-tests.py --print-failures
stackless_clang:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -155,7 +156,7 @@ jobs:
run: tests/run-tests.py --print-failures
float_clang:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -172,6 +173,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
+ # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
+ with:
+ python-version: '3.11'
- name: Build
run: source tools/ci.sh && ci_unix_settrace_build
- name: Run main test suite
@@ -184,6 +190,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests.
+ # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default.
+ with:
+ python-version: '3.11'
- name: Build
run: source tools/ci.sh && ci_unix_settrace_stackless_build
- name: Run main test suite
@@ -193,7 +204,7 @@ jobs:
run: tests/run-tests.py --print-failures
macos:
- runs-on: macos-11.0
+ runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -208,7 +219,8 @@ jobs:
run: tests/run-tests.py --print-failures
qemu_mips:
- runs-on: ubuntu-latest
+ # ubuntu-22.04 is needed for older libffi.
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -222,7 +234,8 @@ jobs:
run: tests/run-tests.py --print-failures
qemu_arm:
- runs-on: ubuntu-latest
+ # ubuntu-22.04 is needed for older libffi.
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install packages
@@ -234,3 +247,18 @@ jobs:
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
+
+ qemu_riscv64:
+ # ubuntu-22.04 is needed for older libffi.
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install packages
+ run: source tools/ci.sh && ci_unix_qemu_riscv64_setup
+ - name: Build
+ run: source tools/ci.sh && ci_unix_qemu_riscv64_build
+ - name: Run main test suite
+ run: source tools/ci.sh && ci_unix_qemu_riscv64_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 4b1f4ea791e20..84e018ba15d16 100644
--- a/.github/workflows/ports_windows.yml
+++ b/.github/workflows/ports_windows.yml
@@ -18,7 +18,130 @@ concurrency:
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
+ env:
+ CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
+ 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:
+ - uses: actions/setup-python@v5
+ # note: can go back to installing mingw-w64-${{ matrix.env }}-python after
+ # MSYS2 updates to Python >3.12 (due to settrace compatibility issue)
+ with:
+ python-version: '3.11'
+ - uses: msys2/setup-msys2@v2
+ with:
+ msystem: ${{ matrix.sys }}
+ update: true
+ install: >-
+ make
+ mingw-w64-${{ matrix.env }}-gcc
+ pkg-config
+ git
+ diffutils
+ path-type: inherit # Remove when setup-python is removed
+ - 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
+ run: 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@v4
diff --git a/.github/workflows/ports_zephyr.yml b/.github/workflows/ports_zephyr.yml
index f6f328c9277e4..eb85af6a36154 100644
--- a/.github/workflows/ports_zephyr.yml
+++ b/.github/workflows/ports_zephyr.yml
@@ -20,10 +20,41 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
+ - uses: jlumbroso/free-disk-space@main
+ with:
+ # Only free up a few things so this step runs quickly.
+ android: false
+ dotnet: true
+ haskell: true
+ large-packages: false
+ docker-images: false
+ swap-storage: false
- uses: actions/checkout@v4
+ - id: versions
+ name: Read Zephyr version
+ run: source tools/ci.sh && echo "ZEPHYR=$ZEPHYR_VERSION" | tee "$GITHUB_OUTPUT"
+ - name: Cached Zephyr Workspace
+ id: cache_workspace
+ uses: actions/cache@v4
+ with:
+ # note that the Zephyr CI docker image is 15GB. At time of writing
+ # GitHub caches are limited to 10GB total for a project. So we only
+ # cache the "workspace"
+ path: ./zephyrproject
+ key: zephyr-workspace-${{ steps.versions.outputs.ZEPHYR }}
+ - name: ccache
+ uses: hendrikmuhs/ccache-action@v1.2
+ with:
+ key: zephyr
- name: Install packages
run: source tools/ci.sh && ci_zephyr_setup
- name: Install Zephyr
+ if: steps.cache_workspace.outputs.cache-hit != 'true'
run: source tools/ci.sh && ci_zephyr_install
- name: Build
run: source tools/ci.sh && ci_zephyr_build
+ - name: Run main test suite
+ run: source tools/ci.sh && ci_zephyr_run_tests
+ - name: Print failures
+ if: failure()
+ run: tests/run-tests.py --print-failures
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
index 1159a1882d60e..4c4a2a3162ed6 100644
--- a/.github/workflows/ruff.yml
+++ b/.github/workflows/ruff.yml
@@ -1,11 +1,13 @@
-# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python code lint and formatting with ruff
+
on: [push, pull_request]
+
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - run: pip install --user ruff==0.1.3
+ # ruff version should be kept in sync with .pre-commit-config.yaml & also micropython-lib
+ - run: pipx install ruff==0.11.6
- run: ruff check --output-format=github .
- run: ruff format --diff .
diff --git a/.gitignore b/.gitignore
index 2d20cb18970e8..b5010dfd14db6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,8 +11,9 @@ build/
build-*/
docs/genrst/
-# Test failure outputs
+# Test failure outputs and intermediate artefacts
tests/results/*
+tests/ports/unix/ffi_lib.so
# Python cache files
__pycache__/
diff --git a/.gitmodules b/.gitmodules
index 75bffdadddeb8..02849ec9bdd11 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -3,13 +3,13 @@
url = https://github.com/micropython/axtls.git
[submodule "lib/libffi"]
path = lib/libffi
- url = https://github.com/atgreen/libffi
+ url = https://github.com/libffi/libffi
[submodule "lib/lwip"]
path = lib/lwip
url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/berkeley-db-1.xx"]
path = lib/berkeley-db-1.xx
- url = https://github.com/pfalcon/berkeley-db-1.xx
+ url = https://github.com/micropython/berkeley-db-1.xx
[submodule "lib/stm32lib"]
path = lib/stm32lib
url = https://github.com/micropython/stm32lib
@@ -59,3 +59,18 @@
[submodule "lib/protobuf-c"]
path = lib/protobuf-c
url = https://github.com/protobuf-c/protobuf-c.git
+[submodule "lib/open-amp"]
+ path = lib/open-amp
+ url = https://github.com/OpenAMP/open-amp.git
+[submodule "lib/libmetal"]
+ path = lib/libmetal
+ url = https://github.com/OpenAMP/libmetal.git
+[submodule "lib/arduino-lib"]
+ path = lib/arduino-lib
+ url = https://github.com/arduino/arduino-lib-mpy.git
+[submodule "lib/alif_ensemble-cmsis-dfp"]
+ path = lib/alif_ensemble-cmsis-dfp
+ url = https://github.com/alifsemi/alif_ensemble-cmsis-dfp.git
+[submodule "lib/alif-security-toolkit"]
+ path = lib/alif-security-toolkit
+ url = https://github.com/micropython/alif-security-toolkit.git
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3004bc5677214..ac9785bb59232 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -12,7 +12,16 @@ repos:
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: v0.1.3
+ # Version should be kept in sync with .github/workflows/ruff.yml & also micropython-lib
+ rev: v0.11.6
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.4.1
+ hooks:
+ - id: codespell
+ name: Spellcheck for changed files (codespell)
+ additional_dependencies:
+ - tomli
diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md
index d6b0a5926bf4b..d3f71cb083deb 100644
--- a/CODECONVENTIONS.md
+++ b/CODECONVENTIONS.md
@@ -104,6 +104,22 @@ 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
==========================
@@ -190,14 +206,21 @@ adhere to the existing style and use `tools/codeformat.py` to check any changes.
The main conventions, and things not enforceable via the auto-formatter, are
described below.
-White space:
+As the MicroPython code base is over ten years old, not every source file
+conforms fully to these conventions. If making small changes to existing code,
+then it's usually acceptable to follow the existing code's style. New code or
+major changes should follow the conventions described here.
+
+## White space
+
- Expand tabs to 4 spaces.
- Don't leave trailing whitespace at the end of a line.
- For control blocks (if, for, while), put 1 space between the
keyword and the opening parenthesis.
- Put 1 space after a comma, and 1 space around operators.
-Braces:
+## Braces
+
- Use braces for all blocks, even no-line and single-line pieces of
code.
- Put opening braces on the end of the line it belongs to, not on
@@ -205,18 +228,43 @@ Braces:
- For else-statements, put the else on the same line as the previous
closing brace.
-Header files:
+## Header files
+
- Header files should be protected from multiple inclusion with #if
directives. See an existing header for naming convention.
-Names:
+## Names
+
- Use underscore_case, not camelCase for all names.
- Use CAPS_WITH_UNDERSCORE for enums and macros.
- When defining a type use underscore_case and put '_t' after it.
-Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's
-important to use the correctly-sized (and signed) integer types. The
-general guidelines are:
+### Public names (declared in headers)
+
+- MicroPython-specific names (especially any declared in `py/` and `extmod/`
+ directories) should generally start with `mp_` or `MP_`.
+- Functions and variables declared in a header should generally share a longer
+ common prefix. Usually the prefix matches the file name (i.e. items defined in
+ `py/obj.c` are declared in `py/obj.h` and should be prefixed `mp_obj_`). There
+ are exceptions, for example where one header file contains declarations
+ implemented in multiple source files for expediency.
+
+### Private names (specific to a single .c file)
+
+- For static functions and variables exposed to Python (i.e. a static C function
+ that is wrapped in `MP_DEFINE_CONST_FUN_...` and attached to a module), use
+ the file-level shared common prefix, i.e. name them as if the function or
+ variable was not static.
+- Other static definitions in source files (i.e. functions or variables defined
+ in a .c file that are only used within that .c file) don't need any prefix
+ (specifically: no `s_` or `_` prefix, and generally avoid adding the
+ file-level common prefix).
+
+## Integer types
+
+MicroPython runs on 16, 32, and 64 bit machines, so it's important to use the
+correctly-sized (and signed) integer types. The general guidelines are:
+
- For most cases use mp_int_t for signed and mp_uint_t for unsigned
integer values. These are guaranteed to be machine-word sized and
therefore big enough to hold the value from a MicroPython small-int
@@ -225,11 +273,13 @@ general guidelines are:
- You can use int/uint, but remember that they may be 16-bits wide.
- If in doubt, use mp_int_t/mp_uint_t.
-Comments:
+## Comments
+
- Be concise and only write comments for things that are not obvious.
- Use `// ` prefix, NOT `/* ... */`. No extra fluff.
-Memory allocation:
+## Memory allocation
+
- Use m_new, m_renew, m_del (and friends) to allocate and free heap memory.
These macros are defined in py/misc.h.
diff --git a/LICENSE b/LICENSE
index 9bd457b42acea..929a2e97de7bf 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2013-2023 Damien P. George
+Copyright (c) 2013-2025 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
@@ -48,16 +48,17 @@ used during the build process and is not part of the compiled source code.
/cmsis (BSD-3-clause)
/crypto-algorithms (NONE)
/libhydrogen (ISC)
+ /libmetal (BSD-3-clause)
/littlefs (BSD-3-clause)
/lwip (BSD-3-clause)
/mynewt-nimble (Apache-2.0)
/nrfx (BSD-3-clause)
/nxp_driver (BSD-3-Clause)
/oofatfs (BSD-1-clause)
+ /open-amp (BSD-3-clause)
/pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause)
/stm32lib (BSD-3-clause)
- /tinytest (BSD-3-clause)
/tinyusb (MIT)
/uzlib (Zlib)
/wiznet5k (MIT)
@@ -69,6 +70,9 @@ used during the build process and is not part of the compiled source code.
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/esp32
/ppp_set_auth.* (Apache-2.0)
+ /rp2
+ /mutex_extra.c (BSD-3-clause)
+ /clocks_extra.c (BSD-3-clause)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
diff --git a/README.md b/README.md
index f5bc6d78f0a40..c78a2384604fe 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ 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
+`os`, `sys`, `time`, `re`, and `struct`, etc. Some 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.
@@ -35,8 +35,8 @@ 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
+See the [online documentation](https://docs.micropython.org/) for the API
+reference and information about using MicroPython and information about how
it is implemented.
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
@@ -108,13 +108,13 @@ 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).
+ - [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3, ESP32C6).
- [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)
+ - [qemu](ports/qemu) -- 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.
diff --git a/docs/conf.py b/docs/conf.py
index 728e3c4285d82..eb61487582024 100755
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -36,6 +36,9 @@
"is_release": micropy_version != "latest",
}
+# Authors used in various parts of the documentation.
+micropy_authors = "MicroPython authors and contributors"
+
# -- General configuration ------------------------------------------------
@@ -68,7 +71,7 @@
# General information about the project.
project = "MicroPython"
-copyright = "- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors"
+copyright = "- The MicroPython Documentation is Copyright © 2014-2025, " + micropy_authors
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -244,7 +247,7 @@
master_doc,
"MicroPython.tex",
"MicroPython Documentation",
- "Damien P. George, Paul Sokolovsky, and contributors",
+ micropy_authors,
"manual",
),
]
@@ -281,7 +284,7 @@
"index",
"micropython",
"MicroPython Documentation",
- ["Damien P. George, Paul Sokolovsky, and contributors"],
+ [micropy_authors],
1,
),
]
@@ -300,7 +303,7 @@
master_doc,
"MicroPython",
"MicroPython Documentation",
- "Damien P. George, Paul Sokolovsky, and contributors",
+ micropy_authors,
"MicroPython",
"One line description of project.",
"Miscellaneous",
diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst
index 75dbc953c06f8..c5aa919b7645a 100644
--- a/docs/develop/cmodules.rst
+++ b/docs/develop/cmodules.rst
@@ -59,7 +59,7 @@ A MicroPython user C module is a directory with the following files:
SRC_USERMOD_LIB_C += $(EXAMPLE_MOD_DIR)/utils/algorithm.c
Similarly, use ``SRC_USERMOD_CXX`` and ``SRC_USERMOD_LIB_CXX`` for C++
- source files.
+ source files. If you want to include assembly files use ``SRC_USERMOD_LIB_ASM``.
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
diff --git a/docs/develop/compiler.rst b/docs/develop/compiler.rst
index cac92585ff4ee..0c25ad3a01ef1 100644
--- a/docs/develop/compiler.rst
+++ b/docs/develop/compiler.rst
@@ -98,7 +98,7 @@ Then also edit ``py/lexer.c`` to add the new keyword literal text:
.. code-block:: c
:emphasize-lines: 12
- STATIC const char *const tok_kw[] = {
+ static const char *const tok_kw[] = {
...
"or",
"pass",
@@ -157,7 +157,7 @@ The most relevant method you should know about is this:
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(cm.rc, cm.context, NULL);
+ return mp_make_function_from_proto_fun(cm.rc, cm.context, NULL);
}
The compiler compiles the code in four passes: scope, stack size, code size and emit.
@@ -301,7 +301,7 @@ code statement:
.. code-block:: c
- STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
+ static void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
vtype_kind_t vtype;
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
if (vtype == VTYPE_PYOBJ) {
diff --git a/docs/develop/gettingstarted.rst b/docs/develop/gettingstarted.rst
index a17a320671f52..fed632ea1ac15 100644
--- a/docs/develop/gettingstarted.rst
+++ b/docs/develop/gettingstarted.rst
@@ -112,7 +112,7 @@ Check that you have Python available on your system:
.. code-block:: bash
$ python3
- Python 3.5.0 (default, Jul 17 2020, 14:04:10)
+ Python 3.5.0 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
@@ -278,7 +278,7 @@ To run a selection of tests on a board/device connected over USB use:
.. code-block:: bash
$ cd tests
- $ ./run-tests.py --target minimal --device /dev/ttyACM0
+ $ ./run-tests.py -t /dev/ttyACM0
See also :ref:`writingtests`.
diff --git a/docs/develop/library.rst b/docs/develop/library.rst
index c2a86ea1699bc..830211d81c862 100644
--- a/docs/develop/library.rst
+++ b/docs/develop/library.rst
@@ -48,16 +48,16 @@ hypothetical new module ``subsystem`` in the file ``modsubsystem.c``:
#if MICROPY_PY_SUBSYSTEM
// info()
- STATIC mp_obj_t py_subsystem_info(void) {
+ static mp_obj_t py_subsystem_info(void) {
return MP_OBJ_NEW_SMALL_INT(42);
}
MP_DEFINE_CONST_FUN_OBJ_0(subsystem_info_obj, py_subsystem_info);
- STATIC const mp_rom_map_elem_t mp_module_subsystem_globals_table[] = {
+ static const mp_rom_map_elem_t mp_module_subsystem_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_subsystem) },
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&subsystem_info_obj) },
};
- STATIC MP_DEFINE_CONST_DICT(mp_module_subsystem_globals, mp_module_subsystem_globals_table);
+ static MP_DEFINE_CONST_DICT(mp_module_subsystem_globals, mp_module_subsystem_globals_table);
const mp_obj_module_t mp_module_subsystem = {
.base = { &mp_type_module },
diff --git a/docs/develop/natmod.rst b/docs/develop/natmod.rst
index 6d15f867bcfe8..18678eaefbf11 100644
--- a/docs/develop/natmod.rst
+++ b/docs/develop/natmod.rst
@@ -39,7 +39,8 @@ options for the ``ARCH`` variable, see below):
* ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7)
* ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7)
* ``xtensa`` (non-windowed, eg ESP8266)
-* ``xtensawin`` (windowed with window size 8, eg ESP32)
+* ``xtensawin`` (windowed with window size 8, eg ESP32, ESP32S3)
+* ``rv32imc`` (RISC-V 32 bits with compressed instructions, eg ESP32C3, ESP32C6)
When compiling and linking the native .mpy file the architecture must be chosen
and the corresponding file can only be imported on that architecture. For more
@@ -69,6 +70,13 @@ The known limitations are:
So, if your C code has writable data, make sure the data is defined globally,
without an initialiser, and only written to within functions.
+The native module is not automatically linked against the standard static libraries
+like ``libm.a`` and ``libgcc.a``, which can lead to ``undefined symbol`` errors.
+You can link the runtime libraries by setting ``LINK_RUNTIME = 1``
+in your Makefile. Custom static libraries can also be linked by adding
+``MPY_LD_FLAGS += -l path/to/library.a``. Note that these are linked into
+the native module and will not be shared with other modules or the system.
+
Linker limitation: the native module is not linked against the symbol table of the
full MicroPython firmware. Rather, it is linked against an explicit table of exported
symbols found in ``mp_fun_table`` (in ``py/nativeglue.h``), that is fixed at firmware
@@ -128,7 +136,7 @@ The file ``factorial.c`` contains:
#include "py/dynruntime.h"
// Helper function to compute factorial
- STATIC mp_int_t factorial_helper(mp_int_t x) {
+ static mp_int_t factorial_helper(mp_int_t x) {
if (x == 0) {
return 1;
}
@@ -136,7 +144,7 @@ The file ``factorial.c`` contains:
}
// This is the function which will be called from Python, as factorial(x)
- STATIC mp_obj_t factorial(mp_obj_t x_obj) {
+ static mp_obj_t factorial(mp_obj_t x_obj) {
// Extract the integer from the MicroPython input object
mp_int_t x = mp_obj_get_int(x_obj);
// Calculate the factorial
@@ -145,7 +153,7 @@ The file ``factorial.c`` contains:
return mp_obj_new_int(result);
}
// Define a Python reference to the function above
- STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
+ static MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
@@ -172,7 +180,7 @@ The file ``Makefile`` contains:
# Source files (.c or .py)
SRC = factorial.c
- # Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin)
+ # Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin, rv32imc)
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 7f2c8cbe7282c..533dd64116f03 100644
--- a/docs/develop/optimizations.rst
+++ b/docs/develop/optimizations.rst
@@ -33,7 +33,7 @@ Variables
MicroPython processes local and global variables differently. Global variables
are stored and looked up from a global dictionary that is allocated on the heap
(note that each module has its own separate dict, so separate namespace).
-Local variables on the other hand are are stored on the Python value stack, which may
+Local variables on the other hand are stored on the Python value stack, which may
live on the C stack or on the heap. They are accessed directly by their offset
within the Python stack, which is more efficient than a global lookup in a dict.
diff --git a/docs/develop/porting.rst b/docs/develop/porting.rst
index 63919b97a6ccd..99725e1000bef 100644
--- a/docs/develop/porting.rst
+++ b/docs/develop/porting.rst
@@ -83,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);
}
@@ -262,17 +262,17 @@ To add a custom module like ``myport``, first add the module definition in a fil
#include "py/runtime.h"
- STATIC mp_obj_t myport_info(void) {
+ static mp_obj_t myport_info(void) {
mp_printf(&mp_plat_print, "info about my port\n");
return mp_const_none;
}
- STATIC MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
+ static MP_DEFINE_CONST_FUN_OBJ_0(myport_info_obj, myport_info);
- STATIC const mp_rom_map_elem_t myport_module_globals_table[] = {
+ static const mp_rom_map_elem_t myport_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_myport) },
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&myport_info_obj) },
};
- STATIC MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
+ static MP_DEFINE_CONST_DICT(myport_module_globals, myport_module_globals_table);
const mp_obj_module_t myport_module = {
.base = { &mp_type_module },
diff --git a/docs/develop/writingtests.rst b/docs/develop/writingtests.rst
index 9bb5178f55f22..a7d033f17e9b9 100644
--- a/docs/develop/writingtests.rst
+++ b/docs/develop/writingtests.rst
@@ -60,7 +60,7 @@ Then to run on a board:
.. code-block:: bash
- $ ./run-tests.py --target minimal --device /dev/ttyACM0
+ $ ./run-tests.py -t /dev/ttyACM0
And to run only a certain set of tests (eg a directory):
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_37.rst b/docs/differences/python_37.rst
index 86d1b6e81f96d..2b9a089217f6d 100644
--- a/docs/differences/python_37.rst
+++ b/docs/differences/python_37.rst
@@ -105,4 +105,4 @@ Changes to built-in modules:
.. rubric:: Notes
-.. [#ftimenanosec] Only :func:`time.time_ns` is implemented.
+.. [#ftimenanosec] Only :func:`time.time_ns` is implemented.
diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst
index 08df25b0554d0..ccc01099d17f9 100644
--- a/docs/esp32/quickref.rst
+++ b/docs/esp32/quickref.rst
@@ -18,6 +18,9 @@ working with this board it may be useful to get an overview of the microcontroll
general.rst
tutorial/index.rst
+Note that there are several varieties of ESP32 -- ESP32, ESP32C3, ESP32C6, ESP32S2, ESP32S3 --
+supported by MicroPython, with some differences in functionality between them.
+
Installing MicroPython
----------------------
@@ -58,47 +61,53 @@ The :mod:`esp32` module::
import esp32
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
- esp32.ULP() # access to the Ultra-Low-Power Co-processor
+ esp32.ULP() # access to the Ultra-Low-Power Co-processor, not on ESP32C3/C6
Note that the temperature sensor in the ESP32 will typically read higher than
ambient due to the IC getting warm while it runs. This effect can be minimised
by reading the temperature sensor immediately after waking up from sleep.
+ESP32C3, ESP32C6, ESP32S2, and ESP32S3 also have an internal temperature sensor available.
+It is implemented a bit differently to the ESP32 and returns the temperature in
+Celsius::
+
+ esp32.mcu_temperature() # read the internal temperature of the MCU, in Celsius
+
Networking
----------
WLAN
^^^^
-The :mod:`network` module::
+The :class:`network.WLAN` class in the :mod:`network` module::
import network
- wlan = network.WLAN(network.STA_IF) # create station interface
- wlan.active(True) # activate the interface
- wlan.scan() # scan for access points
- wlan.isconnected() # check if the station is connected to an AP
+ wlan = network.WLAN() # create station interface (the default, see below for an access point interface)
+ 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('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
+ wlan.config('mac') # get the interface's MAC address
+ wlan.ipconfig('addr4') # get the interface's IPv4 addresses
- ap = network.WLAN(network.AP_IF) # create access-point interface
- 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
+ ap = network.WLAN(network.WLAN.IF_AP) # create access-point interface
+ 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
A useful function for connecting to your local WiFi network is::
def do_connect():
- import network
- wlan = network.WLAN(network.STA_IF)
+ import machine, network
+ wlan = network.WLAN()
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('ssid', 'key')
while not wlan.isconnected():
- pass
- print('network config:', wlan.ifconfig())
+ machine.idle()
+ print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket ` module can be used
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
@@ -112,31 +121,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).
+.. _esp32_network_lan:
+
LAN
^^^
-To use the wired interfaces one has to specify the pins and mode ::
+Built-in MAC (original ESP32)
+"""""""""""""""""""""""""""""
+
+The original ESP32 SoC has a built-in Ethernet MAC. Using this MAC requires an
+external Ethernet PHY to be wired to the chip's EMAC pins. Most of the EMAC pin
+assignments are fixed, consult the ESP32 datasheet for details.
+
+If the PHY is connected, the internal Ethernet MAC can be configured via
+the :class:`network.LAN` constructor::
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
+ lan.ipconfig('addr4') # get the interface's IPv4 addresses
+
+Required keyword arguments for the constructor:
-The keyword arguments for the constructor defining the PHY type and interface are:
+- ``mdc`` and ``mdio`` - :class:`machine.Pin` objects (or integers) specifying
+ the MDC and MDIO pins.
+- ``phy_type`` - Select the PHY device type. Supported devices are
+ ``PHY_LAN8710``, ``PHY_LAN8720``, ``PHY_IP101``, ``PHY_RTL8201``,
+ ``PHY_DP83848``, ``PHY_KSZ8041`` and ``PHY_KSZ8081``. These values are all
+ constants defined in the ``network`` module.
+- ``phy_addr`` - The address number of the PHY device. Must be an integer in the
+ range 0x00 to 0x1f, inclusive. Common values are ``0`` and ``1``.
-- 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.
+All of the above keyword arguments must be present to configure the interface.
-These are working configurations for LAN interfaces of popular boards::
+Optional keyword arguments:
+
+- ``reset`` - :class:`machine.Pin` object (or integer) specifying the PHY reset pin.
+- ``power`` - :class:`machine.Pin` object (or integer) specifying a pin which
+ switches the power of the PHY device.
+- ``ref_clk`` - :class:`machine.Pin` object (or integer) specifying the pin used
+ for the EMAC ``ref_clk`` signal. If not specified, the board default is used
+ (typically GPIO 0, but may be different if a particular board has Ethernet.)
+- ``ref_clk_mode`` - Defines whether the EMAC ``ref_clk`` pin of the ESP32
+ should be an input or an output. Suitable values are ``machine.Pin.IN`` and
+ ``machine.Pin.OUT``. If not specified, the board default is used
+ (typically input, but may be different if a particular board has Ethernet.)
+
+These are working configurations for LAN interfaces of some popular ESP32 boards::
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
@@ -161,6 +194,66 @@ These are working configurations for LAN interfaces of popular boards::
lan = network.LAN(id=0, mdc=Pin(23), mdio=Pin(18), power=Pin(5),
phy_type=network.PHY_IP101, phy_addr=1)
+
+.. _esp32_spi_ethernet:
+
+SPI Ethernet Interface
+""""""""""""""""""""""
+
+All ESP32 SoCs support external SPI Ethernet interface chips. These are Ethernet
+interfaces that connect via a SPI bus, rather than an Ethernet RMII interface.
+
+.. note:: The only exception is the ESP32 ``d2wd`` variant, where this feature is disabled
+ to save code size.
+
+SPI Ethernet uses the same :class:`network.LAN` constructor, with a different
+set of keyword arguments::
+
+ import machine, network
+
+ spi = machine.SPI(1, sck=SCK_PIN, mosi=MOSI_PIN, miso=MISO_PIN)
+ lan = network.LAN(spi=spi, cs=CS_PIN, ...) # Set the pin and mode configuration
+ lan.active(True) # activate the interface
+ lan.ipconfig('addr4') # get the interface's IPv4 addresses
+
+Required keyword arguments for the constructor:
+
+- ``spi`` - Should be a :class:`machine.SPI` object configured for this
+ connection. Note that any clock speed configured on the SPI object is ignored,
+ the SPI Ethernet clock speed is configured at compile time.
+- ``cs`` - :class:`machine.Pin` object (or integer) specifying the CS pin
+ connected to the interface.
+- ``int`` - :class:`machine.Pin` object (or integer) specifying the INT pin
+ connected to the interface.
+- ``phy_type`` - Select the SPI Ethernet interface type. Supported devices are
+ ``PHY_KSZ8851SNL``, ``PHY_DM9051``, ``PHY_W5500``. These values are all
+ constants defined in the ``network`` module.
+- ``phy_addr`` - The address number of the PHY device. Must be an integer in the
+ range 0x00 to 0x1f, inclusive. This is usually ``0`` for SPI Ethernet devices.
+
+All of the above keyword arguments must be present to configure the interface.
+
+Optional keyword arguments for the constructor:
+
+- ``reset`` - :class:`machine.Pin` object (or integer) specifying the SPI Ethernet
+ interface reset pin.
+- ``power`` - :class:`machine.Pin` object (or integer) specifying a pin which
+ switches the power of the SPI Ethernet interface.
+
+Here is a sample configuration for a WIZNet W5500 chip connected to pins on
+an ESP32-S3 development board::
+
+ import machine, network
+ from machine import Pin, SPI
+
+ spi = SPI(1, sck=Pin(12), mosi=Pin(13), miso=Pin(14))
+ lan = network.LAN(spi=spi, phy_type=network.PHY_W5500, phy_addr=0,
+ cs=Pin(10), int=Pin(11))
+
+.. note:: WIZnet W5500 Ethernet is also supported on some other MicroPython
+ ports, but using a :ref:`different software interface
+ `.
+
Delay and timing
----------------
@@ -566,7 +659,9 @@ See :ref:`machine.RTC ` ::
from machine import RTC
rtc = RTC()
- rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
+ # time, eg. 2017/8/23 1:12:48
+ # the day-of-week value is ignored
rtc.datetime() # get date and time
WDT (Watchdog timer)
@@ -650,15 +745,15 @@ 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
+ # On original ESP32, 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
---
@@ -740,20 +835,33 @@ APA102 (DotStar) uses a different driver as it has an additional clock pin.
Capacitive touch
----------------
-Use the ``TouchPad`` class in the ``machine`` module::
+ESP32, ESP32-S2 and ESP32-S3 support capacitive touch via the ``TouchPad`` class
+in the ``machine`` module::
from machine import TouchPad, Pin
t = TouchPad(Pin(14))
t.read() # Returns a smaller number when touched
-``TouchPad.read`` returns a value relative to the capacitive variation. Small numbers (typically in
-the *tens*) are common when a pin is touched, larger numbers (above *one thousand*) when
-no touch is present. However the values are *relative* and can vary depending on the board
-and surrounding composition so some calibration may be required.
-
-There are ten capacitive touch-enabled pins that can be used on the ESP32: 0, 2, 4, 12, 13
-14, 15, 27, 32, 33. Trying to assign to any other pins will result in a ``ValueError``.
+``TouchPad.read`` returns a value proportional to the capacitance between the
+pin and the board's Ground connection. On ESP32 the number becomes smaller when
+the pin (or connected touch pad) is touched, on ESP32-S2 and ESP32-S3 the number
+becomes larger when the pin is touched.
+
+In all cases, a touch causes a significant change in the return value. Note the
+returned values are *relative* and can vary depending on the board and
+surrounding environment so some calibration (i.e. comparison to a baseline or
+rolling average) may be required.
+
+========= ==============================================
+Chip Touch-enabled pins
+--------- ----------------------------------------------
+ESP32 0, 2, 4, 12, 13, 14, 15, 27, 32, 33
+ESP32-S2 1 to 14 inclusive
+ESP32-S3 1 to 14 inclusive
+========= ==============================================
+
+Trying to assign to any other pins will result in a ``ValueError``.
Note that TouchPads can be used to wake an ESP32 from sleep::
diff --git a/docs/esp32/tutorial/index.rst b/docs/esp32/tutorial/index.rst
index c6242d731f180..2435f2ecd2f59 100644
--- a/docs/esp32/tutorial/index.rst
+++ b/docs/esp32/tutorial/index.rst
@@ -21,3 +21,4 @@ to ``__.
intro.rst
pwm.rst
peripheral_access.rst
+ reset.rst
diff --git a/docs/esp32/tutorial/intro.rst b/docs/esp32/tutorial/intro.rst
index be09599871ce6..599731ad755af 100644
--- a/docs/esp32/tutorial/intro.rst
+++ b/docs/esp32/tutorial/intro.rst
@@ -36,104 +36,95 @@ 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
-`MicroPython downloads page `_.
-From here, you have 3 main choices:
+`MicroPython download page`_. Search for your particular board on this page.
-* Stable firmware builds
-* Daily firmware builds
-* Daily firmware builds with SPIRAM support
+.. note:: If you don't see your specific board on the download page, then it's
+ very likely that one of the generic firmwares will work. These are
+ listed at the top of the download page and have names matching the
+ onboard Espressif chip (i.e. `ESP32 / WROOM`_, `ESP32-C3`_,
+ `ESP32-S3`_, etc).
-If you are just starting with MicroPython, the best bet is to go for the Stable
-firmware builds. If you are an advanced, experienced MicroPython ESP32 user
-who would like to follow development closely and help with testing new
-features, there are daily builds. If your board has SPIRAM support you can
-use either the standard firmware or the firmware with SPIRAM support, and in
-the latter case you will have access to more RAM for Python objects.
+ However, you may need to double check with the vendor you purchased
+ the board from.
-Deploying the firmware
-----------------------
-
-Once you have the MicroPython firmware you need to load it onto your ESP32 device.
-There are two main steps to do this: first you need to put your device in
-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.
+From here, you have a choice to make:
-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
-boards, along with the Espressif DevKitC, PICO-KIT, WROVER-KIT dev-kits.
+* Download a stable firmware release.
+* Download a daily firmware "Preview" build.
-For best results it is recommended to first erase the entire flash of your
-device before putting on new MicroPython firmware.
+If you are just starting with MicroPython, the best bet is to go for the stable
+Release firmware builds. If you are an advanced, experienced MicroPython ESP32
+user who would like to follow development closely and help with testing new
+features, then you may find the Preview builds useful.
-Currently we only support esptool.py to copy across the firmware. You can find
-this tool here: ``__, or install it
-using pip::
+.. _esp32_flashing:
- pip install esptool
-
-Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer).
-An older version (at least 1.2.1 is needed) works fine but will require Python
-2.7.
-
-Using esptool.py you can erase the flash with the command::
+Deploying the firmware
+----------------------
- esptool.py --port /dev/ttyUSB0 erase_flash
+Once you have the MicroPython firmware you need to load it onto your ESP32
+device. There are two main steps to do this: first you need to put your device
+in 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 then deploy the new firmware using::
+Detailed steps can be found on the same `MicroPython download page`_ for your
+board. It's recommended that you follow the steps on the download page, as they
+are customised for your particular board.
- esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-20180511-v1.9.4.bin
+If the above commands run without error then MicroPython should be installed on
+your board! Skip ahead to :ref:`esp32_serial_prompt`.
-Notes:
+.. _esp32_troubleshooting_install:
-* You might need to change the "port" setting to something else relevant for your
- PC
-* You may need to reduce the baudrate if you get errors when flashing
- (eg down to 115200 by adding ``--baud 115200`` into the command)
-* For some boards with a particular FlashROM configuration you may need to
- change the flash mode (eg by adding ``-fm dio`` into the command)
-* The filename of the firmware should match the file that you have
+Troubleshooting installation problems
+-------------------------------------
-If the above commands run without error then MicroPython should be installed on
-your board!
+If you experience problems during flashing or with running firmware immediately
+after flashing, here are some troubleshooting recommendations:
+
+* Esptool will try to detect the serial port where your ESP32 is connected. If
+ this doesn't work, or you have multiple serial ports, then you may need to
+ manually specify the port by adding the ``--port`` option to the start of the
+ ``esptool.py`` command line. For example, ``esptool.py --port /dev/ttyUSB0
+ `` for Linux or ``esptool --port COM4 `` for
+ Windows.
+* If the board isn't responding to esptool at all, it may need to be manually
+ reset into the bootloader download mode. Look for a button marked "BOOT" or
+ "IO0" on your board and a second button marked "RESET" or "RST". If you have
+ both buttons, try these steps:
+
+ 1. Press "BOOT" (or "IO0") and hold it down.
+ 2. Press "RESET" (or "RST") and immediately release it.
+ 3. Release "BOOT" (or "IO0").
+ 4. Re-run the flashing steps from the download page.
+
+ If your board doesn't have these buttons, consult the board manufacturer's
+ documentation about entering bootloader download mode.
+* If you get errors part-way through the flashing process then try reducing the
+ speed of data transfer by removing the ``--baud 460800`` argument.
+* Hardware problems can cause flashing to fail. There are two common problems:
+ bad power source quality, and defective hardware (especially very low cost
+ unbranded development boards). Speaking of power source, not just raw amperage
+ is important, but also low ripple and noise/EMI in general. The most reliable
+ and convenient power source is a USB port.
+* If you still experience problems with flashing the firmware then please also
+ refer to the `esptool Troubleshooting documentation`_.
+
+.. _esp32_serial_prompt:
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
-converter, depending on your board. The baudrate is 115200.
+over either UART0, which might be connected to a USB-serial converter depending
+on your board, or the chip's built-in USB device. 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
is found at :ref:`esp8266_tutorial` (but skip the Introduction section).
-Troubleshooting installation problems
--------------------------------------
-
-If you experience problems during flashing or with running firmware immediately
-after it, here are troubleshooting recommendations:
-
-* Be aware of and try to exclude hardware problems. There are 2 common
- problems: bad power source quality, and worn-out/defective FlashROM.
- Speaking of power source, not just raw amperage is important, but also low
- ripple and noise/EMI in general. The most reliable and convenient power
- source is a USB port.
-
-* 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 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.
-
-* To catch incorrect flash content (e.g. from a defective sector on a chip),
- add ``--verify`` switch to the commands above.
-
-* If you still experience problems with flashing the firmware please
- refer to esptool.py project page, https://github.com/espressif/esptool
- for additional documentation and a bug tracker where you can report problems.
-
-* If you are able to flash the firmware but the ``--verify`` option returns
- errors even after multiple retries the you may have a defective FlashROM chip.
+.. _esptool Troubleshooting documentation: https://docs.espressif.com/projects/esptool/en/latest/esp32/troubleshooting.html
+.. _MicroPython download page: https://micropython.org/download/?port=esp32
+.. _ESP32 / WROOM: https://micropython.org/download/ESP32_GENERIC
+.. _ESP32-C3: https://micropython.org/download/ESP32_GENERIC_C3
+.. _ESP32-S3: https://micropython.org/download/ESP32_GENERIC_S3
diff --git a/docs/esp32/tutorial/peripheral_access.rst b/docs/esp32/tutorial/peripheral_access.rst
index ecdec101f7ef7..f7c32c367ca09 100644
--- a/docs/esp32/tutorial/peripheral_access.rst
+++ b/docs/esp32/tutorial/peripheral_access.rst
@@ -32,6 +32,18 @@ the prescaler of the MCPWM0 peripheral.
mem32[MCPWM0] = 0x55 # change PWM_CLK_PRESCALE
print(hex(mem32[MCPWM0])) # read PWM_CLK_CFG_REG
+The specific addresses will be different on different ESP32
+models. For example, ESP32-S3 uses these values:
+
+.. code-block:: python3
+
+ DR_REG_DPORT_BASE = const(0x600C_0000)
+ DPORT_PERIP_CLK_EN0_REG = const(DR_REG_DPORT_BASE + 0x0018)
+ DPORT_PERIP_RST_EN0_REG = const(DR_REG_DPORT_BASE + 0x0020)
+ DPORT_PWM0_CLK_EN = const(1 << 17)
+ MCPWM0 = const(0x6001_E000 + 0x0004)
+ ...
+
Note that before a peripheral can be used its clock must be enabled and it must
be taken out of reset. In the above example the following registers are used
for this:
diff --git a/docs/esp32/tutorial/reset.rst b/docs/esp32/tutorial/reset.rst
new file mode 100644
index 0000000000000..b3fc6a85bd436
--- /dev/null
+++ b/docs/esp32/tutorial/reset.rst
@@ -0,0 +1,25 @@
+Factory reset
+=============
+
+If something unexpected happens and your ESP32-based board no longer boots
+MicroPython, then you may have to factory reset it. For more details, see
+:ref:`soft_bricking`.
+
+Factory resetting the MicroPython esp32 port involves fully erasing the flash
+and resetting the flash memory, so you will need to re-flash the MicroPython
+firmware afterwards and copy any Python files to the filesystem again.
+
+1. You will need the Espressif `esptool`_ installed on your system. This is the
+ same tool that you may have used to initially install MicroPython on your
+ board (see :ref:`installation instructions `).
+2. Find the serial port name of your board, and then use esptool to erase the
+ entire flash contents::
+
+ esptool.py -p PORTNAME erase_flash
+
+3. Use esptool to flash the MicroPython file to your board again. If needed,
+ this file and flashing instructions can be found on the `MicroPython
+ downloads page`_.
+
+.. _esptool: https://github.com/espressif/esptool
+.. _MicroPython downloads page: https://micropython.org/download/?port=esp32
diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst
index be0437e752eed..d7211aa5ab745 100644
--- a/docs/esp8266/general.rst
+++ b/docs/esp8266/general.rst
@@ -74,40 +74,7 @@ as possible after use.
Boot process
------------
-On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal
-frozen modules. It mounts filesystem in FlashROM, or if it's not available,
-performs first-time setup of the module and creates the filesystem. This
-part of the boot process is considered fixed, and not available for customization
-for end users (even if you build from source, please refrain from changes to
-it; customization of early boot process is available only to advanced users
-and developers, who can diagnose themselves any issues arising from
-modifying the standard process).
-
-Once the filesystem is mounted, ``boot.py`` is executed from it. The standard
-version of this file is created during first-time module set up and has
-commands to start a WebREPL daemon (disabled by default, configurable
-with ``webrepl_setup`` module), etc. This
-file is customizable by end users (for example, you may want to set some
-parameters or add other services which should be run on
-a module start-up). But keep in mind that incorrect modifications to boot.py
-may still lead to boot loops or lock ups, requiring to reflash a module
-from scratch. (In particular, it's recommended that you use either
-``webrepl_setup`` module or manual editing to configure WebREPL, but not
-both).
-
-As a final step of boot procedure, ``main.py`` is executed from filesystem,
-if exists. This file is a hook to start up a user application each time
-on boot (instead of going to REPL). For small test applications, you may
-name them directly as ``main.py``, and upload to module, but instead it's
-recommended to keep your application(s) in separate files, and have just
-the following in ``main.py``::
-
- import my_app
- my_app.main()
-
-This will allow to keep the structure of your application clear, as well as
-allow to install multiple applications on a board, and switch among them.
-
+See :doc:`/reference/reset_boot`.
Known Issues
------------
diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst
index ed2199737099a..e17b60f676105 100644
--- a/docs/esp8266/quickref.rst
+++ b/docs/esp8266/quickref.rst
@@ -49,19 +49,19 @@ The :mod:`esp` module::
Networking
----------
-The :mod:`network` module::
+The :class:`network.WLAN` class in the :mod:`network` module::
import network
- wlan = network.WLAN(network.STA_IF) # create station interface
+ wlan = network.WLAN(network.WLAN.IF_STA) # create station interface
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('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
+ wlan.ipconfig('addr4') # get the interface's IPv4 addresses
- ap = network.WLAN(network.AP_IF) # create access-point interface
+ ap = network.WLAN(network.WLAN.IF_AP) # create access-point interface
ap.active(True) # activate the interface
ap.config(ssid='ESP-AP') # set the SSID of the access point
@@ -69,14 +69,14 @@ A useful function for connecting to your local WiFi network is::
def do_connect():
import network
- wlan = network.WLAN(network.STA_IF)
+ wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
- print('network config:', wlan.ifconfig())
+ print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket ` module can be used
to create and use TCP/UDP sockets as usual.
@@ -163,10 +163,10 @@ sys.stdin.read() if it's needed to read characters from the UART(0)
while it's also used for the REPL (or detach, read, then reattach).
When detached the UART(0) can be used for other purposes.
-If there are no objects in any of the dupterm slots when the REPL is
-started (on hard or soft reset) then UART(0) is automatically attached.
-Without this, the only way to recover a board without a REPL would be to
-completely erase and reflash (which would install the default boot.py which
+If there are no objects in any of the dupterm slots when the REPL is started (on
+:doc:`hard or soft reset `) then UART(0) is automatically
+attached. Without this, the only way to recover a board without a REPL would be
+to completely erase and reflash (which would install the default boot.py which
attaches the REPL).
To detach the REPL from UART0, use::
@@ -284,7 +284,9 @@ See :ref:`machine.RTC ` ::
from machine import RTC
rtc = RTC()
- rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
+ # time, eg. 2017/8/23 1:12:48
+ # the day-of-week value is ignored
rtc.datetime() # get date and time
# synchronize with ntp
diff --git a/docs/esp8266/tutorial/network_basics.rst b/docs/esp8266/tutorial/network_basics.rst
index dc3cd3dd5e070..e383c00c6ceed 100644
--- a/docs/esp8266/tutorial/network_basics.rst
+++ b/docs/esp8266/tutorial/network_basics.rst
@@ -1,14 +1,15 @@
Network basics
==============
-The network module is used to configure the WiFi connection. There are two WiFi
-interfaces, one for the station (when the ESP8266 connects to a router) and one
-for the access point (for other devices to connect to the ESP8266). Create
+The :class:`network.WLAN` class in the :mod:`network` module is used to
+configure the WiFi connection. There are two WiFi interfaces, one for
+the station (when the ESP8266 connects to a router) and one for the
+access point (for other devices to connect to the ESP8266). Create
instances of these objects using::
>>> import network
- >>> sta_if = network.WLAN(network.STA_IF)
- >>> ap_if = network.WLAN(network.AP_IF)
+ >>> sta_if = network.WLAN(network.WLAN.IF_STA)
+ >>> ap_if = network.WLAN(network.WLAN.IF_AP)
You can check if the interfaces are active by::
@@ -19,10 +20,10 @@ You can check if the interfaces are active by::
You can also check the network settings of the interface by::
- >>> ap_if.ifconfig()
- ('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
+ >>> ap_if.ipconfig('addr4')
+ ('192.168.4.1', '255.255.255.0')
-The returned values are: IP address, netmask, gateway, DNS.
+The returned values are: IP address and netmask.
Configuration of the WiFi
-------------------------
@@ -45,8 +46,8 @@ To check if the connection is established use::
Once established you can check the IP address::
- >>> sta_if.ifconfig()
- ('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
+ >>> sta_if.ipconfig('addr4')
+ ('192.168.0.2', '255.255.255.0')
You can then disable the access-point interface if you no longer need it::
@@ -57,14 +58,14 @@ connect to your WiFi network::
def do_connect():
import network
- sta_if = network.WLAN(network.STA_IF)
+ sta_if = network.WLAN(network.WLAN.IF_STA)
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect('', '')
while not sta_if.isconnected():
pass
- print('network config:', sta_if.ifconfig())
+ print('network config:', sta_if.ipconfig('addr4'))
Sockets
-------
diff --git a/docs/esp8266/tutorial/repl.rst b/docs/esp8266/tutorial/repl.rst
index bc0142aaef5f9..db55d45facde8 100644
--- a/docs/esp8266/tutorial/repl.rst
+++ b/docs/esp8266/tutorial/repl.rst
@@ -38,7 +38,7 @@ browser. The latest versions of Firefox and Chrome are supported.
For your convenience, WebREPL client is hosted at
``__. Alternatively, you can install it
-locally from the the GitHub repository
+locally from the GitHub repository
``__.
Before connecting to WebREPL, you should set a password and enable it via
diff --git a/docs/library/array.rst b/docs/library/array.rst
index f417a7046e2ff..957260c2c7f92 100644
--- a/docs/library/array.rst
+++ b/docs/library/array.rst
@@ -19,6 +19,10 @@ Classes
array are given by *iterable*. If it is not provided, an empty
array is created.
+ In addition to the methods below, array objects also implement the buffer
+ protocol. This means the contents of the entire array can be accessed as raw
+ bytes via a `memoryview` or other interfaces which use this protocol.
+
.. method:: append(val)
Append new element *val* to the end of array, growing it.
diff --git a/docs/library/asyncio.rst b/docs/library/asyncio.rst
index b57f1ee04eaec..51ad8a2876a34 100644
--- a/docs/library/asyncio.rst
+++ b/docs/library/asyncio.rst
@@ -149,8 +149,7 @@ 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.
+ callbacks. Flags start in the cleared state.
.. method:: ThreadSafeFlag.set()
diff --git a/docs/library/binascii.rst b/docs/library/binascii.rst
index 6c02f019aaa58..c728c5a8a574c 100644
--- a/docs/library/binascii.rst
+++ b/docs/library/binascii.rst
@@ -36,3 +36,9 @@ Functions
Encode binary data in base64 format, as in `RFC 3548
`_. Returns the encoded data
followed by a newline character if newline is true, as a bytes object.
+
+.. function:: crc32(data, [value])
+
+ Compute CRC-32, the 32-bit checksum of *data*, starting with an initial CRC
+ of *value*. The default initial CRC is zero. The algorithm is consistent
+ with the ZIP file checksum.
diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst
index 78cb4cc281486..b09c370abd46d 100644
--- a/docs/library/bluetooth.rst
+++ b/docs/library/bluetooth.rst
@@ -312,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''``.
@@ -665,7 +665,7 @@ L2CAP connection-oriented-channels
Connect to a listening peer on the specified *psm* with local MTU set to *mtu*.
- On successful connection, the the ``_IRQ_L2CAP_CONNECT`` event will be
+ On successful connection, the ``_IRQ_L2CAP_CONNECT`` event will be
raised, allowing the client to obtain the CID and the local and remote (peer) MTU.
An unsuccessful connection will raise the ``_IRQ_L2CAP_DISCONNECT`` event
@@ -722,7 +722,7 @@ Pairing and bonding
and ``_IRQ_SET_SECRET`` events.
**Note:** This is currently only supported when using the NimBLE stack on
- STM32 and Unix (not ESP32).
+ ESP32, STM32 and Unix.
.. method:: BLE.gap_pair(conn_handle, /)
diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst
index 7a0229c2aaaf6..b5d08ba7fed50 100644
--- a/docs/library/builtins.rst
+++ b/docs/library/builtins.rst
@@ -19,6 +19,8 @@ Functions and types
.. class:: bytearray()
+ |see_cpython| `python:bytearray`.
+
.. class:: bytes()
|see_cpython| `python:bytes`.
@@ -82,6 +84,10 @@ Functions and types
In MicroPython, `byteorder` parameter must be positional (this is
compatible with CPython).
+ .. note:: The optional ``signed`` kwarg from CPython is not supported.
+ MicroPython currently converts negative integers as signed,
+ and positive as unsigned. (:ref:`Details `.)
+
.. function:: isinstance()
.. function:: issubclass()
@@ -100,6 +106,8 @@ Functions and types
.. class:: memoryview()
+ |see_cpython| `python:memoryview`.
+
.. function:: min()
.. function:: next()
@@ -166,6 +174,10 @@ Exceptions
.. exception:: KeyboardInterrupt
+ |see_cpython| `python:KeyboardInterrupt`.
+
+ See also in the context of :ref:`soft_bricking`.
+
.. exception:: KeyError
.. exception:: MemoryError
@@ -186,6 +198,12 @@ Exceptions
|see_cpython| `python:SystemExit`.
+ On non-embedded ports (i.e. Windows and Unix), an unhandled ``SystemExit``
+ exits the MicroPython process in a similar way to CPython.
+
+ On embedded ports, an unhandled ``SystemExit`` currently causes a
+ :ref:`soft_reset` of MicroPython.
+
.. exception:: TypeError
|see_cpython| `python:TypeError`.
diff --git a/docs/library/collections.rst b/docs/library/collections.rst
index 6cf2c096ffc62..6a23e456c66a7 100644
--- a/docs/library/collections.rst
+++ b/docs/library/collections.rst
@@ -18,7 +18,9 @@ Classes
appends and pops from either side of the deque. New deques are created
using the following arguments:
- - *iterable* must be the empty tuple, and the new deque is created empty.
+ - *iterable* is an iterable used to populate the deque when it is
+ created. It can be an empty tuple or list to create a deque that
+ is initially empty.
- *maxlen* must be specified and the deque will be bounded to this
maximum length. Once the deque is full, any new items added will
@@ -26,18 +28,37 @@ Classes
- The optional *flags* can be 1 to check for overflow when adding items.
- As well as supporting `bool` and `len`, deque objects have the following
- methods:
+ Deque objects support `bool`, `len`, iteration and subscript load and store.
+ They also have the following methods:
.. method:: deque.append(x)
Add *x* to the right side of the deque.
- Raises IndexError if overflow checking is enabled and there is no more room left.
+ Raises ``IndexError`` if overflow checking is enabled and there is
+ no more room in the queue.
+
+ .. method:: deque.appendleft(x)
+
+ Add *x* to the left side of the deque.
+ Raises ``IndexError`` if overflow checking is enabled and there is
+ no more room in the queue.
+
+ .. method:: deque.pop()
+
+ Remove and return an item from the right side of the deque.
+ Raises ``IndexError`` if no items are present.
.. method:: deque.popleft()
Remove and return an item from the left side of the deque.
- Raises IndexError if no items are present.
+ Raises ``IndexError`` if no items are present.
+
+ .. method:: deque.extend(iterable)
+
+ Extend the deque by appending all the items from *iterable* to
+ the right of the deque.
+ Raises ``IndexError`` if overflow checking is enabled and there is
+ no more room in the deque.
.. function:: namedtuple(name, fields)
diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst
index 422329bf1e801..dc35e7905e162 100644
--- a/docs/library/esp32.rst
+++ b/docs/library/esp32.rst
@@ -114,7 +114,7 @@ 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()
diff --git a/docs/library/espnow.rst b/docs/library/espnow.rst
index f0b592dffc8ab..84e9e9465de96 100644
--- a/docs/library/espnow.rst
+++ b/docs/library/espnow.rst
@@ -56,7 +56,7 @@ A simple example would be:
import espnow
# A WLAN interface must be active to send()/recv()
- sta = network.WLAN(network.STA_IF) # Or network.AP_IF
+ sta = network.WLAN(network.WLAN.IF_STA) # Or network.WLAN.IF_AP
sta.active(True)
sta.disconnect() # For ESP8266
@@ -76,7 +76,7 @@ A simple example would be:
import espnow
# A WLAN interface must be active to send()/recv()
- sta = network.WLAN(network.STA_IF)
+ sta = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.disconnect() # Because ESP8266 auto-connects to last Access Point
@@ -164,11 +164,13 @@ Configuration
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
+ *rate*: (ESP32 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
- `_.
+ `_. This
+ parameter is actually *write-only* due to ESP-IDF not providing any
+ means for querying the radio interface's rate parameter.
.. data:: Returns:
@@ -182,14 +184,14 @@ Configuration
Sending and Receiving Data
--------------------------
-A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be
+A wifi interface (``network.WLAN.IF_STA`` or ``network.WLAN.IF_AP``) 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 = network.WLAN(network.WLAN.IF_STA)
sta.active(True)
sta.disconnect() # For ESP8266
@@ -441,12 +443,14 @@ must first register the sender and use the same encryption keys as the sender
- *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)
+ channel of the wifi device will be used, if channel is set to another
+ value then this must match the channel currently configured on the
+ interface (see :func:`WLAN.config`). (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`_
+ ``network.WLAN.IF_STA`` (=0) or ``network.WLAN.IF_AP`` (=1).
+ (default=0/``network.WLAN.IF_STA``). See `ESPNow and Wifi Operation`_
below for more information.
- *encrypt*: (ESP32 only) If set to ``True`` data exchanged with
@@ -470,6 +474,9 @@ must first register the sender and use the same encryption keys as the sender
registered.
- ``OSError(num, "ESP_ERR_ESPNOW_FULL")`` if too many peers are
already registered.
+ - ``OSError(num, "ESP_ERR_ESPNOW_CHAN")`` if a channel value was
+ set that doesn't match the channel currently configured for this
+ interface.
- ``ValueError()`` on invalid keyword args or values.
.. method:: ESPNow.del_peer(mac)
@@ -588,7 +595,7 @@ api-reference/network/esp_now.html#api-reference>`_. For example::
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)
+ network.WLAN(network.WLAN.IF_STA).active(True)
else:
raise err
@@ -645,7 +652,7 @@ A small async server example::
import asyncio
# A WLAN interface must be active to send()/recv()
- network.WLAN(network.STA_IF).active(True)
+ network.WLAN(network.WLAN.IF_STA).active(True)
e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support
e.active(True)
@@ -747,8 +754,8 @@ 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
+`WLAN` interface (``network.WLAN.IF_STA`` or ``network.WLAN.IF_AP``),
+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:
@@ -832,8 +839,8 @@ Other issues to take care with when using ESPNow with wifi are:
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 = network.WLAN(network.WLAN.IF_STA); sta.active(False)
+ ap = network.WLAN(network.WLAN.IF_AP); ap.active(False)
sta.active(True)
while not sta.active():
time.sleep(0.1)
diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst
index 149f4d6609be9..f22a3613bdbcb 100644
--- a/docs/library/framebuf.rst
+++ b/docs/library/framebuf.rst
@@ -114,7 +114,7 @@ Drawing text
.. method:: FrameBuffer.text(s, x, y[, c])
- Write text to the FrameBuffer using the the coordinates as the upper-left
+ Write text to the FrameBuffer using the coordinates as the upper-left
corner of the text. The color of the text can be defined by the optional
argument but is otherwise a default value of 1. All characters have
dimensions of 8x8 pixels and there is currently no way to change the font.
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 4a7f78ecf3184..2919378ce13b2 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -69,6 +69,7 @@ library.
heapq.rst
io.rst
json.rst
+ marshal.rst
math.rst
os.rst
platform.rst
@@ -103,7 +104,9 @@ the following libraries.
micropython.rst
neopixel.rst
network.rst
+ openamp.rst
uctypes.rst
+ vfs.rst
The following libraries provide drivers for hardware components.
diff --git a/docs/library/machine.ADCBlock.rst b/docs/library/machine.ADCBlock.rst
index eb94362d5597c..e947f70815071 100644
--- a/docs/library/machine.ADCBlock.rst
+++ b/docs/library/machine.ADCBlock.rst
@@ -26,7 +26,7 @@ Constructors
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.
diff --git a/docs/library/machine.PWM.rst b/docs/library/machine.PWM.rst
index b9cf00240314c..5f592b8dff593 100644
--- a/docs/library/machine.PWM.rst
+++ b/docs/library/machine.PWM.rst
@@ -86,7 +86,7 @@ Specific PWM class implementations
The following concrete class(es) implement enhancements to the PWM class.
- | :ref:`pyb.Timer for PyBoard `
+ | :ref:`pyb.Timer for PyBoard `
Limitations of PWM
------------------
@@ -103,7 +103,7 @@ Limitations of PWM
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.
+ 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
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index 49fb66beb38ea..4aac0f4b94be2 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -209,13 +209,13 @@ The following methods are not part of the core Pin API and only implemented on c
Set pin to "0" output level.
- Availability: nrf, rp2, stm32 ports.
+ Availability: mimxrt, nrf, renesas-ra, rp2, samd, stm32 ports.
.. method:: Pin.high()
Set pin to "1" output level.
- Availability: nrf, rp2, stm32 ports.
+ Availability: mimxrt, nrf, renesas-ra, rp2, samd, stm32 ports.
.. method:: Pin.mode([mode])
@@ -238,6 +238,12 @@ The following methods are not part of the core Pin API and only implemented on c
Availability: cc3200 port.
+.. method:: Pin.toggle()
+
+ Toggle output pin from "0" to "1" or vice-versa.
+
+ Availability: cc3200, esp32, esp8266, mimxrt, rp2, samd ports.
+
Constants
---------
diff --git a/docs/library/machine.RTC.rst b/docs/library/machine.RTC.rst
index be2be2eee5eea..e2ddd728bde4c 100644
--- a/docs/library/machine.RTC.rst
+++ b/docs/library/machine.RTC.rst
@@ -42,12 +42,21 @@ Methods
Initialise the RTC. Datetime is a tuple of the form:
- ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])``
+ ``(year, month, day, hour, minute, second, microsecond, tzinfo)``
+
+ All eight arguments must be present. The ``microsecond`` and ``tzinfo``
+ values are currently ignored but might be used in the future.
+
+ Availability: CC3200, ESP32, MIMXRT, SAMD. The rtc.init() method on
+ the stm32 and renesas-ra ports just (re-)starts the RTC and does not
+ accept arguments.
.. method:: RTC.now()
Get get the current datetime tuple.
+ Availability: WiPy.
+
.. method:: RTC.deinit()
Resets the RTC to the time of January 1, 2015 and starts running it again.
@@ -62,10 +71,13 @@ Methods
Get the number of milliseconds left before the alarm expires.
-.. method:: RTC.cancel(alarm_id=0)
+.. method:: RTC.alarm_cancel(alarm_id=0)
Cancel a running alarm.
+ The mimxrt port also exposes this function as ``RTC.cancel(alarm_id=0)``, but this is
+ scheduled to be removed in MicroPython 2.0.
+
.. method:: RTC.irq(*, trigger, handler=None, wake=machine.IDLE)
Create an irq object triggered by a real time clock alarm.
@@ -75,6 +87,21 @@ Methods
- ``wake`` specifies the sleep mode from where this interrupt can wake
up the system.
+.. method:: RTC.memory([data])
+
+ ``RTC.memory(data)`` will write *data* to the RTC memory, where *data* is any
+ object which supports the buffer protocol (including `bytes`, `bytearray`,
+ `memoryview` and `array.array`). ``RTC.memory()`` reads RTC memory and returns
+ a `bytes` object.
+
+ Data written to RTC user memory is persistent across restarts, including
+ :ref:`soft_reset` and `machine.deepsleep()`.
+
+ The maximum length of RTC user memory is 2048 bytes by default on esp32,
+ and 492 bytes on esp8266.
+
+ Availability: esp32, esp8266 ports.
+
Constants
---------
diff --git a/docs/library/machine.SD.rst b/docs/library/machine.SD.rst
index c736dc4d2836e..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
diff --git a/docs/library/machine.SDCard.rst b/docs/library/machine.SDCard.rst
index cde0bd1d145d9..c4a0d5d172b30 100644
--- a/docs/library/machine.SDCard.rst
+++ b/docs/library/machine.SDCard.rst
@@ -23,21 +23,23 @@ arguments that might need to be set in order to use either a non-standard slot
or a non-standard pin assignment. The exact subset of arguments supported will
vary from platform to platform.
-.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None, freq=20000000)
+.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None,
+ cs=None, cmd=None, data=None, freq=20000000)
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:
- *slot* selects which of the available interfaces to use. Leaving this
unset will select the default interface.
- - *width* selects the bus width for the SD/MMC interface.
+ - *width* selects the bus width for the SD/MMC interface. This many data
+ pins must be connected to the SD card.
- *cd* can be used to specify a card-detect pin.
@@ -51,7 +53,14 @@ vary from platform to platform.
- *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).
+ The following additional parameters are only present on ESP32 port:
+
+ - *cmd* can be used to specify the SD CMD pin (ESP32-S3 only).
+
+ - *data* can be used to specify a list or tuple of SD data bus pins
+ (ESP32-S3 only).
+
+ - *freq* selects the SD/MMC interface frequency in Hz.
Implementation-specific details
-------------------------------
@@ -67,52 +76,130 @@ The standard PyBoard has just one slot. No arguments are necessary or supported.
ESP32
`````
-The ESP32 provides two channels of SD/MMC hardware and also supports
-access to SD Cards through either of the two SPI ports that are
-generally available to the user. As a result the *slot* argument can
-take a value between 0 and 3, inclusive. Slots 0 and 1 use the
-built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0
-supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit
-access; the SPI slots only support 1-bit access.
-
- .. note:: Slot 0 is used to communicate with on-board flash memory
- on most ESP32 modules and so will be unavailable to the
- user.
-
- .. note:: Most ESP32 modules that provide an SD card slot using the
- dedicated hardware only wire up 1 data pin, so the default
- value for *width* is 1.
-
-The pins used by the dedicated SD/MMC hardware are fixed. The pins
-used by the SPI hardware can be reassigned.
-
- .. note:: If any of the SPI signals are remapped then all of the SPI
- signals will pass through a GPIO multiplexer unit which
- can limit the performance of high frequency signals. Since
- the normal operating speed for SD cards is 40MHz this can
- cause problems on some cards.
-
-The default (and preferred) pin assignment are as follows:
-
- ====== ====== ====== ====== ======
- Slot 0 1 2 3
- ------ ------ ------ ------ ------
- Signal Pin Pin Pin Pin
- ====== ====== ====== ====== ======
- sck 6 14 18 14
- cmd 11 15
- cs 5 15
- miso 19 12
- mosi 23 13
- D0 7 2
- D1 8 4
- D2 9 12
- D3 10 13
- D4 16
- D5 17
- D6 5
- D7 18
- ====== ====== ====== ====== ======
+SD cards support access in both SD/MMC mode and the simpler (but slower) SPI
+mode.
+
+SPI mode makes use of a `SPI` host peripheral, which cannot concurrently be used
+for other SPI interactions.
+
+The ``slot`` argument determines which mode is used. Different values are
+supported on different chips:
+
+========== ======== ======== ============ ============
+Chip Slot 0 Slot 1 Slot 2 Slot 3
+========== ======== ======== ============ ============
+ESP32 SD/MMC SPI (id=1) SPI (id=0)
+ESP32-C3 SPI (id=0)
+ESP32-C6 SPI (id=0)
+ESP32-S2 SPI (id=1) SPI (id=0)
+ESP32-S3 SD/MMC SD/MMC SPI (id=1) SPI (id=0)
+========== ======== ======== ============ ============
+
+Different slots support different data bus widths (number of data pins):
+
+========== ========== =====================
+Slot Type Supported data widths
+========== ========== =====================
+0 SD/MMC 1, 4, 8
+1 SD/MMC 1, 4
+2 SPI 1
+3 SPI 1
+========== ========== =====================
+
+.. note:: Most ESP32 modules that provide an SD card slot using the
+ dedicated hardware only wire up 1 data pin, so the default
+ value for ``width`` is 1.
+
+Additional details depend on which ESP32 family chip is in use:
+
+Original ESP32
+~~~~~~~~~~~~~~
+
+In SD/MMC mode (slot 1), pin assignments in SD/MMC mode are fixed on the
+original ESP32. The SPI mode slots (2 & 3) allow pins to be set to different
+values in the constructor.
+
+The default pin assignments are as follows:
+
+ ====== ====== ====== ====== ============
+ Slot 1 2 3 Can be set
+ ------ ------ ------ ------ ------------
+ Signal Pin Pin Pin
+ ====== ====== ====== ====== ============
+ CLK 14 No
+ CMD 15 No
+ D0 2 No
+ D1 4 No
+ D2 12 No
+ D3 13 No
+ sck 18 14 Yes
+ cs 5 15 Yes
+ miso 19 12 Yes
+ mosi 23 13 Yes
+ ====== ====== ====== ====== ============
+
+The ``cd`` and ``wp`` pins are not fixed in either mode and default to disabled, unless set.
+
+ESP32-S3
+~~~~~~~~
+
+The ESP32-S3 chip allows pins to be set to different values for both SD/MMC and
+SPI mode access.
+
+If not set, default pin assignments are as follows:
+
+ ======== ====== ====== ====== ======
+ Slot 0 1 2 3
+ -------- ------ ------ ------ ------
+ Signal Pin Pin Pin Pin
+ ======== ====== ====== ====== ======
+ CLK 14 14
+ CMD 15 15
+ D0 2 2
+ D1 4 4
+ D2 12 12
+ D3 13 13
+ D4 33*
+ D5 34*
+ D6 35*
+ D7 36*
+ sck 37* 14
+ cs 34* 13
+ miso 37* 2
+ mosi 35* 15
+ ======== ====== ====== ====== ======
+
+.. note:: Slots 0 and 1 cannot both be in use at the same time.
+
+.. note:: Pins marked with an asterisk * in the table must be changed from the
+ default if the ESP32-S3 board is configured for Octal SPI Flash or
+ PSRAM.
+
+To access a card in SD/MMC mode, set ``slot`` parameter value 0 or 1 and
+parameters ``sck`` (for CLK), ``cmd`` and ``data`` as needed to assign pins. If
+the ``data`` argument is passed then it should be a list or tuple of data pins
+or pin numbers with length equal to the ``width`` argument. For example::
+
+ sd = SDCard(slot=0, width=4, sck=8, cmd=9, data=(10, 11, 12, 13))
+
+To access a card in SPI mode, set ``slot`` parameter value 2 or 3 and pass
+parameters ``sck``, ``cs``, ``miso``, ``mosi`` as needed to assign pins.
+
+In either mode the ``cd`` and ``wp`` pins default to disabled, unless set in the
+constructor.
+
+Other ESP32 chips
+~~~~~~~~~~~~~~~~~
+
+Other ESP32 family chips do not have hardware SD/MMC host controllers and can
+only access SD cards in SPI mode.
+
+To access a card in SPI mode, set ``slot`` parameter value 2 or 3 and pass
+parameters ``sck``, ``cs``, ``miso``, ``mosi`` to assign pins.
+
+.. note:: ESP32-C3 and ESP32-C6 only have one available `SPI` bus, so the only
+ valid ``slot`` parameter value is 2. Using this bus for the SD card
+ will prevent also using it for :class:`machine.SPI`.
cc3200
``````
diff --git a/docs/library/machine.TimerWiPy.rst b/docs/library/machine.TimerWiPy.rst
index f8c8bb29da7fb..54280a5994ad5 100644
--- a/docs/library/machine.TimerWiPy.rst
+++ b/docs/library/machine.TimerWiPy.rst
@@ -71,7 +71,7 @@ Methods
Otherwise, a TimerChannel object is initialized and returned.
- The operating mode is is the one configured to the Timer object that was used to
+ The operating mode 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``.
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index 072bdb7188a3d..5be79cccce884 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -83,7 +83,7 @@ Methods
- *pins* is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order).
Any of the pins can be None if one wants the UART to operate with limited functionality.
- If the RTS pin is given the the RX pin must be given as well. The same applies to CTS.
+ If the RTS pin is given the RX pin must be given as well. The same applies to CTS.
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.
@@ -152,31 +152,6 @@ Methods
Send a break condition on the bus. This drives the bus low for a duration
longer than required for a normal transmission of a character.
-.. method:: UART.irq(trigger, priority=1, handler=None, wake=machine.IDLE)
-
- Create a callback to be triggered when data is received on the UART.
-
- - *trigger* can only be ``UART.RX_ANY``
- - *priority* level of the interrupt. Can take values in the range 1-7.
- Higher values represent higher priorities.
- - *handler* an optional function to be called when new characters arrive.
- - *wake* can only be ``machine.IDLE``.
-
- .. note::
-
- The handler will be called whenever any of the following two conditions are met:
-
- - 8 new characters have been received.
- - At least 1 new character is waiting in the Rx buffer and the Rx line has been
- silent for the duration of 1 complete frame.
-
- This means that when the handler function is called there will be between 1 to 8
- characters waiting.
-
- Returns an irq object.
-
- Availability: WiPy.
-
.. method:: UART.flush()
Waits until all data has been sent. In case of a timeout, an exception is raised. The timeout
@@ -185,7 +160,7 @@ Methods
.. note::
- For the rp2, esp8266 and nrf ports the call returns while the last byte is sent.
+ For the 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
@@ -197,17 +172,91 @@ Methods
.. note::
- For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte
+ For the 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
+.. method:: UART.irq(handler=None, trigger=0, hard=False)
+
+ Configure an interrupt handler to be called when a UART event occurs.
+
+ The arguments are:
+
+ - *handler* is an optional function to be called when the interrupt event
+ triggers. The handler must take exactly one argument which is the
+ ``UART`` instance.
+
+ - *trigger* configures the event(s) which can generate an interrupt.
+ Possible values are a mask of one or more of the following:
+
+ - ``UART.IRQ_RXIDLE`` interrupt after receiving at least one character
+ and then the RX line goes idle.
+ - ``UART.IRQ_RX`` interrupt after each received character.
+ - ``UART.IRQ_TXIDLE`` interrupt after or while the last character(s) of
+ a message are or have been sent.
+ - ``UART.IRQ_BREAK`` interrupt when a break state is detected at RX
+
+ - *hard* if true a hardware interrupt is used. This reduces the delay
+ between the pin change and the handler being called. Hard interrupt
+ handlers may not allocate memory; see :ref:`isr_rules`.
+
+ Returns an irq object.
+
+ Due to limitations of the hardware not all trigger events are available on all ports.
+
+ .. table:: Availability of triggers
+ :align: center
+
+ ============== ========== ====== ========== =========
+ Port / Trigger IRQ_RXIDLE IRQ_RX IRQ_TXIDLE IRQ_BREAK
+ ============== ========== ====== ========== =========
+ CC3200 yes
+ ESP32 yes yes yes
+ MIMXRT yes yes
+ NRF yes yes
+ RENESAS-RA yes yes
+ RP2 yes yes yes
+ SAMD yes yes yes
+ STM32 yes yes
+ ============== ========== ====== ========== =========
+
+
+ .. note::
+ - The ESP32 port does not support the option hard=True.
+
+ - The rp2 port's UART.IRQ_TXIDLE is only triggered when the message
+ is longer than 5 characters and the trigger happens when still 5 characters
+ are to be sent.
+
+ - The rp2 port's UART.IRQ_BREAK needs receiving valid characters for triggering
+ again.
+
+ - The SAMD port's UART.IRQ_TXIDLE is triggered while the last character is sent.
+
+ - On STM32F4xx MCU's, using the trigger UART.IRQ_RXIDLE the handler will be called once
+ after the first character and then after the end of the message, when the line is
+ idle.
+
+
+ Availability: cc3200, esp32, mimxrt, nrf, renesas-ra, rp2, samd, stm32.
+
Constants
---------
-.. data:: UART.RX_ANY
+.. data:: UART.RTS
+ UART.CTS
+
+ Flow control options.
+
+ Availability: esp32, mimxrt, renesas-ra, rp2, stm32.
+
+.. data:: UART.IRQ_RXIDLE
+ UART.IRQ_RX
+ UART.IRQ_TXIDLE
+ UART.IRQ_BREAK
- IRQ trigger sources
+ IRQ trigger sources.
- Availability: WiPy.
+ Availability: renesas-ra, stm32, esp32, rp2040, mimxrt, samd, cc3200.
diff --git a/docs/library/machine.USBDevice.rst b/docs/library/machine.USBDevice.rst
new file mode 100644
index 0000000000000..5291679ac1258
--- /dev/null
+++ b/docs/library/machine.USBDevice.rst
@@ -0,0 +1,304 @@
+.. currentmodule:: machine
+.. _machine.USBDevice:
+
+class USBDevice -- USB Device driver
+====================================
+
+.. note:: ``machine.USBDevice`` is currently only supported for esp32, rp2 and
+ samd ports. Native USB support is also required, and not every board
+ supports native USB.
+
+USBDevice provides a low-level Python API for implementing USB device functions using
+Python code.
+
+.. warning:: This low-level API assumes familiarity with the USB standard. There
+ are high-level `usb driver modules in micropython-lib`_ which provide a
+ simpler interface and more built-in functionality.
+
+Terminology
+-----------
+
+- A "Runtime" USB device interface or driver is one which is defined using this
+ Python API after MicroPython initially starts up.
+
+- A "Built-in" USB device interface or driver is one that is compiled into the
+ MicroPython firmware, and is always available. Examples are USB-CDC (serial
+ port) which is usually enabled by default. Built-in USB-MSC (Mass Storage) is an
+ option on some ports.
+
+Lifecycle
+---------
+
+Managing a runtime USB interface can be tricky, especially if you are communicating
+with MicroPython over a built-in USB-CDC serial port that's part of the same USB
+device.
+
+- A MicroPython :ref:`soft reset ` will always clear all runtime USB
+ interfaces, which results in the entire USB device disconnecting from the
+ host. If MicroPython is also providing a built-in USB-CDC serial port then
+ this will re-appear after the soft reset.
+
+ This means some functions (like ``mpremote run``) that target the USB-CDC
+ serial port will immediately fail if a runtime USB interface is active,
+ because the port goes away when ``mpremote`` triggers a soft reset. The
+ operation should succeed on the second try, as after the soft reset there is
+ no more runtime USB interface.
+
+- To configure a runtime USB device on every boot, it's recommended to place the
+ configuration code in the :ref:`boot.py` file on the :ref:`device VFS
+ `. On each reset this file is executed before the USB subsystem is
+ initialised (and before :ref:`main.py`), so it allows the board to come up with the runtime
+ USB device immediately.
+
+- For development or debugging, it may be convenient to connect a hardware
+ serial REPL and disable the built-in USB-CDC serial port entirely. Not all ports
+ support this (currently only ``rp2``). The custom build should be configured
+ with ``#define MICROPY_HW_USB_CDC (0)`` and ``#define
+ MICROPY_HW_ENABLE_UART_REPL (1)``.
+
+Constructors
+------------
+
+.. class:: USBDevice()
+
+ Construct a USBDevice object.
+
+ .. note:: This object is a singleton, each call to this constructor
+ returns the same object reference.
+
+Methods
+-------
+
+.. method:: USBDevice.config(desc_dev, desc_cfg, desc_strs=None, open_itf_cb=None, reset_cb=None, control_xfer_cb=None, xfer_cb=None)
+
+ Configures the ``USBDevice`` singleton object with the USB runtime device
+ state and callback functions:
+
+ - ``desc_dev`` - A bytes-like object containing
+ the new USB device descriptor.
+
+ - ``desc_cfg`` - A bytes-like object containing the
+ new USB configuration descriptor.
+
+ - ``desc_strs`` - Optional object holding strings or bytes objects
+ containing USB string descriptor values. Can be a list, a dict, or any
+ object which supports subscript indexing with integer keys (USB string
+ descriptor index).
+
+ Strings are an optional USB feature, and this parameter can be unset
+ (default) if no strings are referenced in the device and configuration
+ descriptors, or if only built-in strings should be used.
+
+ Apart from index 0, all the string values should be plain ASCII. Index 0
+ is the special "languages" USB descriptor, represented as a bytes object
+ with a custom format defined in the USB standard. ``None`` can be
+ returned at index 0 in order to use a default "English" language
+ descriptor.
+
+ To fall back to providing a built-in string value for a given index, a
+ subscript lookup can return ``None``, raise ``KeyError``, or raise
+ ``IndexError``.
+
+ - ``open_itf_cb`` - This callback is called once for each interface
+ or Interface Association Descriptor in response to a Set
+ Configuration request from the USB Host (the final stage before
+ the USB device is available to the host).
+
+ The callback takes a single argument, which is a memoryview of the
+ interface or IAD descriptor that the host is accepting (including
+ all associated descriptors). It is a view into the same
+ ``desc_cfg`` object that was provided as a separate
+ argument to this function. The memoryview is only valid until the
+ callback function returns.
+
+ - ``reset_cb`` - This callback is called when the USB host performs
+ a bus reset. The callback takes no arguments. Any in-progress
+ transfers will never complete. The USB host will most likely
+ proceed to re-enumerate the USB device by calling the descriptor
+ callbacks and then ``open_itf_cb()``.
+
+ - ``control_xfer_cb`` - This callback is called one or more times
+ for each USB control transfer (device Endpoint 0). It takes two
+ arguments.
+
+ The first argument is the control transfer stage. It is one of:
+
+ - ``1`` for SETUP stage.
+ - ``2`` for DATA stage.
+ - ``3`` for ACK stage.
+
+ Second argument is a memoryview to read the USB control request
+ data for this stage. The memoryview is only valid until the
+ callback function returns. Data in this memoryview will be the same
+ across each of the three stages of a single transfer.
+
+ A successful transfer consists of this callback being called in sequence
+ for the three stages. Generally speaking, if a device wants to do
+ something in response to a control request then it's best to wait until
+ the ACK stage to confirm the host controller completed the transfer as
+ expected.
+
+ The callback should return one of the following values:
+
+ - ``False`` to stall the endpoint and reject the transfer. It won't
+ proceed to any remaining stages.
+ - ``True`` to continue the transfer to the next stage.
+ - A buffer object can be returned at the SETUP stage when the transfer
+ will send or receive additional data. Typically this is the case when
+ the ``wLength`` field in the request has a non-zero value. This should
+ be a writable buffer for an ``OUT`` direction transfer, or a readable
+ buffer with data for an ``IN`` direction transfer.
+
+ - ``xfer_cb`` - This callback is called whenever a non-control
+ transfer submitted by calling :func:`USBDevice.submit_xfer` completes.
+
+ The callback has three arguments:
+
+ 1. The Endpoint number for the completed transfer.
+ 2. Result value: ``True`` if the transfer succeeded, ``False``
+ otherwise.
+ 3. Number of bytes successfully transferred. In the case of a
+ "short" transfer, The result is ``True`` and ``xferred_bytes``
+ will be smaller than the length of the buffer submitted for the
+ transfer.
+
+ .. note:: If a bus reset occurs (see :func:`USBDevice.reset`),
+ ``xfer_cb`` is not called for any transfers that have not
+ already completed.
+
+.. method:: USBDevice.active(self, [value] /)
+
+ Returns the current active state of this runtime USB device as a
+ boolean. The runtime USB device is "active" when it is available to
+ interact with the host, it doesn't mean that a USB Host is actually
+ present.
+
+ If the optional ``value`` argument is set to a truthy value, then
+ the USB device will be activated.
+
+ If the optional ``value`` argument is set to a falsey value, then
+ the USB device is deactivated. While the USB device is deactivated,
+ it will not be detected by the USB Host.
+
+ To simulate a disconnect and a reconnect of the USB device, call
+ ``active(False)`` followed by ``active(True)``. This may be
+ necessary if the runtime device configuration has changed, so that
+ the host sees the new device.
+
+.. attribute:: USBDevice.builtin_driver
+
+ This attribute holds the current built-in driver configuration, and must be
+ set to one of the ``USBDevice.BUILTIN_`` named constants defined on this object.
+
+ By default it holds the value :data:`USBDevice.BUILTIN_NONE`.
+
+ Runtime USB device must be inactive when setting this field. Call the
+ :func:`USBDevice.active` function to deactivate before setting if necessary
+ (and again to activate after setting).
+
+ If this value is set to any value other than :data:`USBDevice.BUILTIN_NONE` then
+ the following restrictions apply to the :func:`USBDevice.config` arguments:
+
+ - ``desc_cfg`` should begin with the built-in USB interface descriptor data
+ accessible via :data:`USBDevice.builtin_driver` attribute ``desc_cfg``.
+ Descriptors appended after the built-in configuration descriptors should use
+ interface, string and endpoint numbers starting from the max built-in values
+ defined in :data:`USBDevice.builtin_driver` attributes ``itf_max``, ``str_max`` and
+ ``ep_max``.
+
+ - The ``bNumInterfaces`` field in the built-in configuration
+ descriptor will also need to be updated if any new interfaces
+ are appended to the end of ``desc_cfg``.
+
+ - ``desc_strs`` should either be ``None`` or a list/dictionary where index
+ values less than ``USBDevice.builtin_driver.str_max`` are missing or have
+ value ``None``. This reserves those string indexes for the built-in
+ drivers. Placing a different string at any of these indexes overrides that
+ string in the built-in driver.
+
+.. method:: USBDevice.remote_wakeup(self)
+
+ Wake up host if we are in suspend mode and the REMOTE_WAKEUP feature
+ is enabled by the host. This has to be enabled in the USB attributes,
+ and on the host. Returns ``True`` if remote wakeup was enabled and
+ active and the host was woken up.
+
+.. method:: USBDevice.submit_xfer(self, ep, buffer /)
+
+ Submit a USB transfer on endpoint number ``ep``. ``buffer`` must be
+ an object implementing the buffer interface, with read access for
+ ``IN`` endpoints and write access for ``OUT`` endpoints.
+
+ .. note:: ``ep`` cannot be the control Endpoint number 0. Control
+ transfers are built up through successive executions of
+ ``control_xfer_cb``, see above.
+
+ Returns ``True`` if successful, ``False`` if the transfer could not
+ be queued (as USB device is not configured by host, or because
+ another transfer is queued on this endpoint.)
+
+ When the USB host completes the transfer, the ``xfer_cb`` callback
+ is called (see above).
+
+ Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
+ active.
+
+.. method:: USBDevice.stall(self, ep, [stall] /)
+
+ Calling this function gets or sets the STALL state of a device endpoint.
+
+ ``ep`` is the number of the endpoint.
+
+ If the optional ``stall`` parameter is set, this is a boolean flag
+ for the STALL state.
+
+ The return value is the current stall state of the endpoint (before
+ any change made by this function).
+
+ An endpoint that is set to STALL may remain stalled until this
+ function is called again, or STALL may be cleared automatically by
+ the USB host.
+
+ Raises ``OSError`` with reason ``MP_EINVAL`` If the USB device is not
+ active.
+
+Constants
+---------
+
+.. data:: USBDevice.BUILTIN_NONE
+.. data:: USBDevice.BUILTIN_DEFAULT
+.. data:: USBDevice.BUILTIN_CDC
+.. data:: USBDevice.BUILTIN_MSC
+.. data:: USBDevice.BUILTIN_CDC_MSC
+
+ These constant objects hold the built-in descriptor data which is
+ compiled into the MicroPython firmware. ``USBDevice.BUILTIN_NONE`` and
+ ``USBDevice.BUILTIN_DEFAULT`` are always present. Additional objects may be present
+ depending on the firmware build configuration and the actual built-in drivers.
+
+ .. note:: Currently at most one of ``USBDevice.BUILTIN_CDC``,
+ ``USBDevice.BUILTIN_MSC`` and ``USBDevice.BUILTIN_CDC_MSC`` is defined
+ and will be the same object as ``USBDevice.BUILTIN_DEFAULT``.
+ These constants are defined to allow run-time detection of
+ the built-in driver (if any). Support for selecting one of
+ multiple built-in driver configurations may be added in the
+ future.
+
+ These values are assigned to :data:`USBDevice.builtin_driver` to get/set the
+ built-in configuration.
+
+ Each object contains the following read-only fields:
+
+ - ``itf_max`` - One more than the highest bInterfaceNumber value used
+ in the built-in configuration descriptor.
+ - ``ep_max`` - One more than the highest bEndpointAddress value used
+ in the built-in configuration descriptor. Does not include any
+ ``IN`` flag bit (0x80).
+ - ``str_max`` - One more than the highest string descriptor index
+ value used by any built-in descriptor.
+ - ``desc_dev`` - ``bytes`` object containing the built-in USB device
+ descriptor.
+ - ``desc_cfg`` - ``bytes`` object containing the complete built-in USB
+ configuration descriptor.
+
+.. _usb driver modules in micropython-lib: https://github.com/micropython/micropython-lib/tree/master/micropython/usb#readme
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index 3f5cd6f13c72b..76d111f11ef3d 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -62,14 +62,13 @@ Reset related functions
.. function:: reset()
- Resets the device in a manner similar to pushing the external RESET
- button.
+ :ref:`Hard resets ` the device in a manner similar to pushing the
+ external RESET button.
.. function:: soft_reset()
- Performs a soft reset of the interpreter, deleting all Python objects and
- resetting the Python heap. It tries to retain the method by which the user
- is connected to the MicroPython REPL (eg serial, USB, Wifi).
+ Performs a :ref:`soft reset ` of the interpreter, deleting all
+ Python objects and resetting the Python heap.
.. function:: reset_cause()
@@ -127,14 +126,20 @@ Power related functions
.. function:: idle()
- Gates the clock to the CPU, useful to reduce power consumption at any time during
- short or long periods. Peripherals continue working and execution resumes as soon
- as any interrupt is triggered (on many ports this includes system timer
- interrupt occurring at regular intervals on the order of millisecond).
+ Gates the clock to the CPU, useful to reduce power consumption at any time
+ during short or long periods. Peripherals continue working and execution
+ resumes as soon as any interrupt is triggered, or at most one millisecond
+ after the CPU was paused.
+
+ It is recommended to call this function inside any tight loop that is
+ continuously checking for an external change (i.e. polling). This will reduce
+ power consumption without significantly impacting performance. To reduce
+ power consumption further then see the :func:`lightsleep`,
+ :func:`time.sleep()` and :func:`time.sleep_ms()` functions.
.. function:: sleep()
- .. note:: This function is deprecated, use `lightsleep()` instead with no arguments.
+ .. note:: This function is deprecated, use :func:`lightsleep()` instead with no arguments.
.. function:: lightsleep([time_ms])
deepsleep([time_ms])
@@ -265,3 +270,4 @@ Classes
machine.WDT.rst
machine.SD.rst
machine.SDCard.rst
+ machine.USBDevice.rst
diff --git a/docs/library/marshal.rst b/docs/library/marshal.rst
new file mode 100644
index 0000000000000..6d3213e0a6ec8
--- /dev/null
+++ b/docs/library/marshal.rst
@@ -0,0 +1,28 @@
+:mod:`marshal` -- Python object serialization
+=============================================
+
+.. module:: marshal
+ :synopsis: Convert Python objects to and from a binary format
+
+|see_cpython_module| :mod:`python:marshal`.
+
+This module implements conversion between Python objects and a binary format.
+The format is specific to MicroPython but does not depend on the machine
+architecture, so the data can be transferred and used on a different MicroPython
+instance, as long as the version of the binary data matches (it's currently
+versioned as the mpy file version, see :ref:`mpy_files`).
+
+Functions
+---------
+
+.. function:: dumps(value, /)
+
+ Convert the given *value* to binary format and return a corresponding ``bytes``
+ object.
+
+ Currently, code objects are the only supported values that can be converted.
+
+.. function:: loads(data, /)
+
+ Convert the given bytes-like *data* to its corresponding Python object, and
+ return it.
diff --git a/docs/library/math.rst b/docs/library/math.rst
index a6f13d48c1892..335bd80781cfc 100644
--- a/docs/library/math.rst
+++ b/docs/library/math.rst
@@ -125,8 +125,11 @@ Functions
Return the natural logarithm of the gamma function of ``x``.
.. function:: log(x)
+ log(x, base)
- Return the natural logarithm of ``x``.
+ With one argument, return the natural logarithm of *x*.
+
+ With two arguments, return the logarithm of *x* to the given *base*.
.. function:: log10(x)
diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst
index b17dfa9a75a48..4d5a064a7a70e 100644
--- a/docs/library/micropython.rst
+++ b/docs/library/micropython.rst
@@ -136,6 +136,14 @@ Functions
the heap may be locked) and scheduling a function to call later will lift
those restrictions.
+ On multi-threaded ports, the scheduled function's behaviour depends on
+ whether the Global Interpreter Lock (GIL) is enabled for the specific port:
+
+ - If GIL is enabled, the function can preempt any thread and run in its
+ context.
+ - If GIL is disabled, the function will only preempt the main thread and run
+ in its context.
+
Note: If `schedule()` is called from a preempting IRQ, when memory
allocation is not allowed and the callback to be passed to `schedule()` is
a bound method, passing this directly will fail. This is because creating a
@@ -147,3 +155,71 @@ Functions
There is a finite queue to hold the scheduled functions and `schedule()`
will raise a `RuntimeError` if the queue is full.
+
+Classes
+-------
+
+.. class:: RingIO(size)
+.. class:: RingIO(buffer)
+ :noindex:
+
+ Provides a fixed-size ringbuffer for bytes with a stream interface. Can be
+ considered like a fifo queue variant of `io.BytesIO`.
+
+ When created with integer size a suitable buffer will be allocated.
+ Alternatively a `bytearray` or similar buffer protocol object can be provided
+ to the constructor for in-place use.
+
+ The classic ringbuffer algorithm is used which allows for any size buffer
+ to be used however one byte will be consumed for tracking. If initialised
+ with an integer size this will be accounted for, for example ``RingIO(16)``
+ will allocate a 17 byte buffer internally so it can hold 16 bytes of data.
+ When passing in a pre-allocated buffer however one byte less than its
+ original length will be available for storage, eg. ``RingIO(bytearray(16))``
+ will only hold 15 bytes of data.
+
+ A RingIO instance can be IRQ / thread safe when used to pass data in a single
+ direction eg. when written to in an IRQ and read from in a non-IRQ function
+ (or vice versa). This does not hold if you try to eg. write to a single instance
+ from both IRQ and non-IRQ code, this would often cause data corruption.
+
+ .. method:: RingIO.any()
+
+ Returns an integer counting the number of characters that can be read.
+
+ .. method:: RingIO.read([nbytes])
+
+ Read available characters. This is a non-blocking function. If ``nbytes``
+ is specified then read at most that many bytes, otherwise read as much
+ data as possible.
+
+ Return value: a bytes object containing the bytes read. Will be
+ zero-length bytes object if no data is available.
+
+ .. method:: RingIO.readline([nbytes])
+
+ Read a line, ending in a newline character or return if one exists in
+ the buffer, else return available bytes in buffer. If ``nbytes`` is
+ specified then read at most that many bytes.
+
+ Return value: a bytes object containing the line read.
+
+ .. method:: RingIO.readinto(buf[, nbytes])
+
+ Read available bytes into the provided ``buf``. If ``nbytes`` is
+ specified then read at most that many bytes. Otherwise, read at
+ most ``len(buf)`` bytes.
+
+ Return value: Integer count of the number of bytes read into ``buf``.
+
+ .. method:: RingIO.write(buf)
+
+ Non-blocking write of bytes from ``buf`` into the ringbuffer, limited
+ by the available space in the ringbuffer.
+
+ Return value: Integer count of bytes written.
+
+ .. method:: RingIO.close()
+
+ No-op provided as part of standard `stream` interface. Has no effect
+ on data in the ringbuffer.
diff --git a/docs/library/neopixel.rst b/docs/library/neopixel.rst
index edcbc9345c304..b618e6012c382 100644
--- a/docs/library/neopixel.rst
+++ b/docs/library/neopixel.rst
@@ -43,7 +43,8 @@ Constructors
- *pin* is a machine.Pin instance.
- *n* is the number of LEDs in the strip.
- *bpp* is 3 for RGB LEDs, and 4 for RGBW LEDs.
- - *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz).
+ - *timing* is 0 for 400KHz, and 1 for 800kHz LEDs (most are 800kHz). You
+ may also supply a timing tuple as accepted by `machine.bitstream()`.
Pixel access methods
--------------------
diff --git a/docs/library/network.LAN.rst b/docs/library/network.LAN.rst
index 375e02cefecd0..1b3c19c560b36 100644
--- a/docs/library/network.LAN.rst
+++ b/docs/library/network.LAN.rst
@@ -6,11 +6,11 @@ class LAN -- control an Ethernet module
This class allows you to control the Ethernet interface. The PHY hardware type is board-specific.
-Example usage::
+Example usage, for a board with built-in LAN support::
import network
nic = network.LAN(0)
- print(nic.ifconfig())
+ print(nic.ipconfig("addr4"))
# now use socket as usual
...
@@ -32,7 +32,7 @@ Constructors
- *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 PHY 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.
@@ -41,6 +41,9 @@ Constructors
nic = LAN(0, phy_type=LAN.PHY_LAN8720, phy_addr=1, ref_clk_mode=Pin.IN)
+ .. note:: On esp32 port the constructor requires different arguments. See
+ :ref:`esp32 port reference `.
+
Methods
-------
diff --git a/docs/library/network.PPP.rst b/docs/library/network.PPP.rst
new file mode 100644
index 0000000000000..15ab1da193448
--- /dev/null
+++ b/docs/library/network.PPP.rst
@@ -0,0 +1,106 @@
+.. currentmodule:: network
+.. _network.PPP:
+
+class PPP -- create network connections over serial PPP
+=======================================================
+
+This class allows you to create a network connection over a serial port using
+the PPP protocol.
+
+.. note:: Currently only the esp32 port has PPP support enabled in the default
+ firmware build. PPP support can be enabled in custom builds of the
+ stm32 and rp2 ports by enabling networking support and setting
+ ``MICROPY_PY_NETWORK_PPP_LWIP`` to 1.
+
+Example usage::
+
+ import network
+
+ ppp = network.PPP(uart)
+ ppp.connect()
+
+ while not ppp.isconnected():
+ pass
+
+ print(ppp.ipconfig("addr4"))
+
+ # use the socket module as usual, etc
+
+ ppp.disconnect()
+
+Constructors
+------------
+
+.. class:: PPP(stream)
+
+ Create a PPP driver object.
+
+ Arguments are:
+
+ - *stream* is any object that supports the stream protocol, but is most commonly a
+ :class:`machine.UART` instance. This stream object must have an ``irq()`` method
+ and an ``IRQ_RXIDLE`` constant, for use by `PPP.connect`.
+
+Methods
+-------
+
+.. method:: PPP.connect(security=SEC_NONE, user=None, key=None)
+
+ Initiate a PPP connection with the given parameters:
+
+ - *security* is the type of security, either ``PPP.SEC_NONE``, ``PPP.SEC_PAP``,
+ or ``PPP.SEC_CHAP``.
+ - *user* is an optional user name to use with the security mode.
+ - *key* is an optional password to use with the security mode.
+
+ When this method is called the underlying stream has its interrupt configured to call
+ `PPP.poll` via ``stream.irq(ppp.poll, stream.IRQ_RXIDLE)``. This makes sure the
+ stream is polled, and data passed up the PPP stack, wheverver data becomes available
+ on the stream.
+
+ The connection proceeds asynchronously, in the background.
+
+.. method:: PPP.disconnect()
+
+ Terminate the connection. This must be called to cleanly close the PPP connection.
+
+.. method:: PPP.isconnected()
+
+ Returns ``True`` if the PPP link is connected and up.
+ Returns ``False`` otherwise.
+
+.. method:: PPP.status()
+
+ Returns the PPP status.
+
+.. method:: PPP.config(config_parameters)
+
+ Sets or gets parameters of the PPP interface. The only parameter that can be
+ retrieved and set is the underlying stream, using::
+
+ stream = PPP.config("stream")
+ PPP.config(stream=stream)
+
+.. method:: PPP.ipconfig('param')
+ PPP.ipconfig(param=value, ...)
+
+ See `AbstractNIC.ipconfig`.
+
+.. method:: PPP.ifconfig([(ip, subnet, gateway, dns)])
+
+ See `AbstractNIC.ifconfig`.
+
+.. method:: PPP.poll()
+
+ Poll the underlying stream for data, and pass it up the PPP stack.
+ This is called automatically if the stream is a UART with a RXIDLE interrupt,
+ so it's not usually necessary to call it manually.
+
+Constants
+---------
+
+.. data:: PPP.SEC_NONE
+ PPP.SEC_PAP
+ PPP.SEC_CHAP
+
+ The type of connection security.
diff --git a/docs/library/network.WIZNET5K.rst b/docs/library/network.WIZNET5K.rst
index c13d43a376ece..d0778a7a37ce8 100644
--- a/docs/library/network.WIZNET5K.rst
+++ b/docs/library/network.WIZNET5K.rst
@@ -9,11 +9,14 @@ the W5200 and W5500 chipsets. The particular chipset that is supported
by the firmware is selected at compile-time via the MICROPY_PY_NETWORK_WIZNET5K
option.
+.. note:: The esp32 port also supports WIZnet W5500 chipsets, but this port
+ uses the :ref:`network.LAN interface `.
+
Example usage::
import network
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
- print(nic.ifconfig())
+ print(nic.ipconfig("addr4"))
# now use socket as usual
...
@@ -51,20 +54,7 @@ Constructors
Methods
-------
-.. method:: WIZNET5K.isconnected()
-
- Returns ``True`` if the physical Ethernet link is connected and up.
- Returns ``False`` otherwise.
-
-.. method:: WIZNET5K.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'))
+This class implements most methods from `AbstractNIC `, which are documented there. Additional methods are:
.. method:: WIZNET5K.regs()
diff --git a/docs/library/network.WLAN.rst b/docs/library/network.WLAN.rst
index 68cd49769afff..ee0ef490fda84 100644
--- a/docs/library/network.WLAN.rst
+++ b/docs/library/network.WLAN.rst
@@ -8,7 +8,7 @@ This class provides a driver for WiFi network processors. Example usage::
import network
# enable station interface and connect to WiFi access point
- nic = network.WLAN(network.STA_IF)
+ nic = network.WLAN(network.WLAN.IF_STA)
nic.active(True)
nic.connect('your-ssid', 'your-key')
# now use sockets as usual
@@ -18,8 +18,8 @@ Constructors
.. class:: WLAN(interface_id)
Create a WLAN network interface object. Supported interfaces are
-``network.STA_IF`` (station aka client, connects to upstream WiFi access
-points) and ``network.AP_IF`` (access point, allows other WiFi clients to
+``network.WLAN.IF_STA`` (station aka client, connects to upstream WiFi access
+points) and ``network.WLAN.IF_AP`` (access point, allows other WiFi clients to
connect). Availability of the methods below depends on interface type.
For example, only STA interface may `WLAN.connect()` to an access point.
@@ -75,7 +75,7 @@ Methods
Return the current status of the wireless connection.
When called with no argument the return value describes the network link status.
- The possible statuses are defined as constants:
+ The possible statuses are defined as constants in the :mod:`network` module:
* ``STAT_IDLE`` -- no connection and no activity,
* ``STAT_CONNECTING`` -- connecting in progress,
@@ -85,7 +85,18 @@ Methods
* ``STAT_GOT_IP`` -- connection successful.
When called with one argument *param* should be a string naming the status
- parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``.
+ parameter to retrieve, and different parameters are supported depending on the
+ mode the WiFi is in.
+
+ In STA mode, passing ``'rssi'`` returns a signal strength indicator value, whose
+ format varies depending on the port (this is available on all ports that support
+ WiFi network interfaces, except for CC3200).
+
+ In AP mode, passing ``'stations'`` returns a list of connected WiFi stations
+ (this is available on all ports that support WiFi network interfaces, except for
+ CC3200). The format of the station information entries varies across ports,
+ providing either the raw BSSID of the connected station, the IP address of the
+ connected station, or both.
.. method:: WLAN.isconnected()
@@ -107,7 +118,7 @@ Methods
Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by
- `WLAN.ifconfig()`). These include network-specific and hardware-specific
+ `AbstractNIC.ipconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, keyword argument syntax should be used,
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::
@@ -126,7 +137,7 @@ Methods
============= ===========
mac MAC address (bytes)
ssid WiFi access point name (string)
- channel WiFi channel (integer)
+ channel WiFi channel (integer). Depending on the port this may only be supported on the AP interface.
hidden Whether SSID is hidden (boolean)
security Security protocol supported (enumeration, see module constants)
key Access key (string)
diff --git a/docs/library/network.WLANWiPy.rst b/docs/library/network.WLANWiPy.rst
index 2a5ba118454bc..4ac82e92c6a58 100644
--- a/docs/library/network.WLANWiPy.rst
+++ b/docs/library/network.WLANWiPy.rst
@@ -20,7 +20,7 @@ This class provides a driver for the WiFi network processor in the WiPy. Example
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
while not wlan.isconnected():
time.sleep_ms(50)
- print(wlan.ifconfig())
+ print(wlan.ipconfig("addr4"))
# now use socket as usual
...
@@ -96,16 +96,10 @@ Methods
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
-.. method:: WLANWiPy.ifconfig(if_id=0, config=['dhcp' or configtuple])
+.. method:: WLANWiPy.ipconfig('param')
+ WLANWiPy.ipconfig(param=value, ...)
- With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*.
-
- if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
- are negotiated with the AP.
-
- If the 4-tuple config is given then a static IP is configured. For instance::
-
- wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
+ See :meth:`AbstractNIC.ipconfig `. Supported parameters are: ``dhcp4``, ``addr4``, ``gw4``.
.. method:: WLANWiPy.mode([mode])
diff --git a/docs/library/network.rst b/docs/library/network.rst
index cc508842942a5..d05d17132dc67 100644
--- a/docs/library/network.rst
+++ b/docs/library/network.rst
@@ -24,7 +24,7 @@ For example::
print("Waiting for connection...")
while not nic.isconnected():
time.sleep(1)
- print(nic.ifconfig())
+ print(nic.ipconfig("addr4"))
# now use socket as usual
import socket
@@ -113,8 +113,48 @@ parameter should be `id`.
connected to the AP. The list contains tuples of the form
(MAC, RSSI).
+.. method:: AbstractNIC.ipconfig('param')
+ AbstractNIC.ipconfig(param=value, ...)
+
+ Get or set interface-specific IP-configuration interface parameters.
+ Supported parameters are the following (availability of a particular
+ parameter depends on the port and the specific network interface):
+
+ * ``dhcp4`` (``True/False``) obtain an IPv4 address, gateway and dns
+ server via DHCP. This method does not block and wait for an address
+ to be obtained. To check if an address was obtained, use the read-only
+ property ``has_dhcp4``.
+ * ``gw4`` Get/set the IPv4 default-gateway.
+ * ``dhcp6`` (``True/False``) obtain a DNS server via stateless DHCPv6.
+ Obtaining IP Addresses via DHCPv6 is currently not implemented.
+ * ``autoconf6`` (``True/False``) obtain a stateless IPv6 address via
+ the network prefix shared in router advertisements. To check if a
+ stateless address was obtained, use the read-only
+ property ``has_autoconf6``.
+ * ``addr4`` (e.g. ``192.168.0.4/24``) obtain the current IPv4 address
+ and network mask as ``(ip, subnet)``-tuple, regardless of how this
+ address was obtained. This method can be used to set a static IPv4
+ address either as ``(ip, subnet)``-tuple or in CIDR-notation.
+ * ``addr6`` (e.g. ``fe80::1234:5678``) obtain a list of current IPv6
+ addresses as ``(ip, state, preferred_lifetime, valid_lifetime)``-tuple.
+ This include link-local, slaac and static addresses.
+ ``preferred_lifetime`` and ``valid_lifetime`` represent the remaining
+ valid and preferred lifetime of each IPv6 address, in seconds.
+ ``state`` indicates the current state of the address:
+
+ * ``0x08`` - ``0x0f`` indicates the address is tentative, counting the
+ number of probes sent.
+ * ``0x10`` The address is deprecated (but still valid)
+ * ``0x30`` The address is preferred (and valid)
+ * ``0x40`` The address is duplicated and can not be used.
+
+ This method can be used to set a static IPv6
+ address, by setting this parameter to the address, like ``fe80::1234:5678``.
+
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)])
+ .. note:: This function is deprecated, use `ipconfig()` instead.
+
Get/set IP-level network interface parameters: IP address, subnet mask,
gateway and DNS server. When called with no arguments, this method returns
a 4-tuple with the above information. To set the above values, pass a
@@ -127,7 +167,7 @@ parameter should be `id`.
Get or set general network interface parameters. These methods allow to work
with additional parameters beyond standard IP configuration (as dealt with by
- `ifconfig()`). These include network-specific and hardware-specific
+ `ipconfig()`). These include network-specific and hardware-specific
parameters. For setting parameters, the keyword argument
syntax should be used, and multiple parameters can be set at once. For
querying, a parameter name should be quoted as a string, and only one
@@ -152,6 +192,7 @@ provide a way to control networking interfaces of various kinds.
network.WLANWiPy.rst
network.WIZNET5K.rst
network.LAN.rst
+ network.PPP.rst
Network functions
=================
@@ -195,6 +236,20 @@ The following are functions available in the network module.
The default hostname is typically the name of the board.
+.. function:: ipconfig('param')
+ ipconfig(param=value, ...)
+
+ Get or set global IP-configuration parameters.
+ Supported parameters are the following (availability of a particular
+ parameter depends on the port and the specific network interface):
+
+ * ``dns`` Get/set DNS server. This method can support both, IPv4 and
+ IPv6 addresses.
+ * ``prefer`` (``4/6``) Specify which address type to return, if a domain
+ name has both A and AAAA records. Note, that this does not clear the
+ local DNS cache, so that any previously obtained addresses might not
+ change.
+
.. function:: phy_mode([mode])
Get or set the PHY mode.
diff --git a/docs/library/openamp.rst b/docs/library/openamp.rst
new file mode 100644
index 0000000000000..de4d51ad06b5e
--- /dev/null
+++ b/docs/library/openamp.rst
@@ -0,0 +1,115 @@
+:mod:`openamp` -- provides standard Asymmetric Multiprocessing (AMP) support
+============================================================================
+
+.. module:: openamp
+ :synopsis: provides standard Asymmetric Multiprocessing (AMP) support
+
+The ``openamp`` module provides a standard inter-processor communications infrastructure
+for MicroPython. The module handles all of the details of OpenAMP, such as setting up
+the shared resource table, initializing vrings, etc. It provides an API for using the
+RPMsg bus infrastructure with the `Endpoint` class, and provides processor Life Cycle
+Management (LCM) support, such as loading firmware and starting and stopping a remote
+core, via the `RemoteProc` class.
+
+Example usage::
+
+ import openamp
+
+ def ept_recv_callback(src, data):
+ print("Received message on endpoint", data)
+
+ # Create a new RPMsg endpoint to communicate with the remote core.
+ ept = openamp.Endpoint("vuart-channel", callback=ept_recv_callback)
+
+ # Create a RemoteProc object, load its firmware and start it.
+ rproc = openamp.RemoteProc("virtual_uart.elf") # Or entry point address (ex 0x081E0000)
+ rproc.start()
+
+ while True:
+ if ept.is_ready():
+ ept.send("data")
+
+Functions
+---------
+
+.. function:: new_service_callback(ns_callback)
+
+ Set the new service callback.
+
+ The *ns_callback* argument is a function that will be called when the remote processor
+ announces new services. At that point the host processor can choose to create the
+ announced endpoint, if this particular service is supported, or ignore it if it's
+ not. If this function is not set, the host processor should first register the
+ endpoint locally, and it will be automatically bound when the remote announces
+ the service.
+
+Endpoint class
+--------------
+
+.. class:: Endpoint(name, callback, src=ENDPOINT_ADDR_ANY, dest=ENDPOINT_ADDR_ANY)
+
+ Construct a new RPMsg Endpoint. An endpoint is a bidirectional communication
+ channel between two cores.
+
+ Arguments are:
+
+ - *name* is the name of the endpoint.
+ - *callback* is a function that is called when the endpoint receives data with the
+ source address of the remote point, and the data as bytes passed by reference.
+ - *src* is the endpoint source address. If none is provided one will be assigned
+ to the endpoint by the library.
+ - *dest* is the endpoint destination address. If the endpoint is created from the
+ new_service_callback, this must be provided and it must match the remote endpoint's
+ source address. If the endpoint is registered locally, before the announcement, the
+ destination address will be assigned by the library when the endpoint is bound.
+
+.. method:: Endpoint.deinit()
+
+ Destroy the endpoint and release all of its resources.
+
+.. method:: Endpoint.is_ready()
+
+ Returns True if the endpoint is ready to send (i.e., has both a source and destination addresses)
+
+.. method:: Endpoint.send(src=-1, dest=-1, timeout=-1)
+
+ Send a message to the remote processor over this endpoint.
+
+ Arguments are:
+
+ - *src* is the source endpoint address of the message. If none is provided, the
+ source address the endpoint is bound to is used.
+ - *dest* is the destination endpoint address of the message. If none is provided,
+ the destination address the endpoint is bound to is used.
+ - *timeout* specifies the time in milliseconds to wait for a free buffer. By default
+ the function is blocking.
+
+RemoteProc class
+----------------
+
+.. class:: RemoteProc(entry)
+
+ The RemoteProc object provides processor Life Cycle Management (LCM) support, such as
+ loading firmware, starting and stopping a remote core.
+
+ The *entry* argument can be a path to firmware image, in which case the firmware is
+ loaded from file to its target memory, or an entry point address, in which case the
+ firmware must be loaded already at the given address.
+
+.. method:: RemoteProc.start()
+
+ Starts the remote processor.
+
+.. method:: RemoteProc.stop()
+
+ Stops the remote processor. The exact behavior is platform-dependent. On the STM32H7 for
+ example it's not possible to stop and then restart the Cortex-M4 core, so a complete
+ system reset is performed on a call to this function.
+
+.. method:: RemoteProc.shutdown()
+
+ Shutdown stops the remote processor and releases all of its resources. The exact behavior
+ is platform-dependent, however typically it disables power and clocks to the remote core.
+ This function is also used as the finaliser (i.e., called when ``RemoteProc`` object is
+ collected). Note that on the STM32H7, it's not possible to stop and then restart the
+ Cortex-M4 core, so a complete system reset is performed on a call to this function.
diff --git a/docs/library/os.rst b/docs/library/os.rst
index 27a7d2d44a05b..710875e34c39b 100644
--- a/docs/library/os.rst
+++ b/docs/library/os.rst
@@ -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/pyb.CAN.rst b/docs/library/pyb.CAN.rst
index 57a85d54b7714..eb21d8223f26e 100644
--- a/docs/library/pyb.CAN.rst
+++ b/docs/library/pyb.CAN.rst
@@ -67,11 +67,17 @@ Methods
: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 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%.
+ both the *baudrate* (within .1%) and the desired *sample_point* (to the nearest 1%). For more precise
+ control over the CAN timing, set the *prescaler*, *bs1* and *bs2* parameters directly.
+ - *sample_point* specifies the position of the bit sample with respect to the whole nominal bit time,
+ expressed as an integer percentage of the nominal bit time. The default *sample_point* is 75%.
+ This parameter is ignored unless *baudrate* is set.
- *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).
+
+ The remaining parameters are only present on boards with CAN FD support, and configure the optional CAN FD
+ Bit Rate Switch (BRS) feature:
+
- *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;
@@ -82,10 +88,11 @@ Methods
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%.
-
+ both the *brs_baudrate* (within .1%) and the desired *brs_sample_point* (to the nearest 1%). For more
+ precise control over the BRS timing, set the *brs_prescaler*, *brs_bs1* and *brs_bs2* parameters directly.
+ - *brs_sample_point* specifies the position of the bit sample with respect to the whole nominal bit time,
+ expressed as an integer percentage of the nominal bit time. The default *brs_sample_point* is 75%.
+ This parameter is ignored unless *brs_baudrate* is set.
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);
diff --git a/docs/library/pyb.Flash.rst b/docs/library/pyb.Flash.rst
index 984e13f4583a4..562bcf1e2466e 100644
--- a/docs/library/pyb.Flash.rst
+++ b/docs/library/pyb.Flash.rst
@@ -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.Timer.rst b/docs/library/pyb.Timer.rst
index 1749efce2d508..c644e38d78624 100644
--- a/docs/library/pyb.Timer.rst
+++ b/docs/library/pyb.Timer.rst
@@ -163,7 +163,7 @@ Methods
- ``callback`` - as per TimerChannel.callback()
- ``pin`` None (the default) or a Pin object. If specified (and not None)
- this will cause the alternate function of the the indicated pin
+ this will cause the alternate function of the indicated pin
to be configured for this timer channel. An error will be raised if
the pin doesn't support any alternate functions for this timer channel.
diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst
index c8ef2c531542f..5eb75c22b608d 100644
--- a/docs/library/pyb.rst
+++ b/docs/library/pyb.rst
@@ -147,10 +147,10 @@ Power related functions
(internal oscillator) directly. The higher frequencies use the HSE to
drive the PLL (phase locked loop), and then use the output of the PLL.
- Note that if you change the frequency while the USB is enabled then
- the USB may become unreliable. It is best to change the frequency
- in boot.py, before the USB peripheral is started. Also note that sysclk
- frequencies below 36MHz do not allow the USB to function correctly.
+ Note that if you change the frequency while the USB is enabled then the USB
+ may become unreliable. It is best to change the frequency in :ref:`boot.py`,
+ before the USB peripheral is started. Also note that sysclk frequencies below
+ 36MHz do not allow the USB to function correctly.
.. function:: wfi()
@@ -205,19 +205,20 @@ Miscellaneous functions
.. function:: main(filename)
- Set the filename of the main script to run after boot.py is finished. If
- this function is not called then the default file main.py will be executed.
+ Set the filename of the main script to run after :ref:`boot.py` is finished.
+ If this function is not called then the default file :ref:`main.py` will be
+ executed.
It only makes sense to call this function from within boot.py.
.. 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)``
diff --git a/docs/library/rp2.DMA.rst b/docs/library/rp2.DMA.rst
new file mode 100644
index 0000000000000..c5e3f31aa2ed6
--- /dev/null
+++ b/docs/library/rp2.DMA.rst
@@ -0,0 +1,293 @@
+.. currentmodule:: rp2
+.. _rp2.DMA:
+
+class DMA -- access to the RP2040's DMA controller
+==================================================
+
+The :class:`DMA` class offers access to the RP2040's Direct Memory Access (DMA)
+controller, providing the ability move data between memory blocks and/or IO registers. The DMA
+controller has its own, separate read and write bus master connections onto the bus fabric and
+each DMA channel can independently read data from one address and write it back to another
+address, optionally incrementing one or both pointers, allowing it to perform transfers on behalf
+of the processor while the processor carries out other tasks or enters a low power state. The
+RP2040's DMA controller has 12 independent DMA channels that can run concurrently. For full
+details of the RP2040's DMA system see section 2.5 of the `RP2040 Datasheet
+`_.
+
+Examples
+--------
+
+The simplest use of the DMA controller is to move data from one block of memory to another.
+This can be accomplished with the following code::
+
+ a = bytearray(32*1024)
+ b = bytearray(32*1024)
+ d = rp2.DMA()
+ c = d.pack_ctrl() # Just use the default control value.
+ # The count is in 'transfers', which defaults to four-byte words, so divide length by 4
+ d.config(read=a, write=b, count=len(a)//4, ctrl=c, trigger=True)
+ # Wait for completion
+ while d.active():
+ pass
+
+Note that while this example sits in an idle loop while it waits for the transfer to complete,
+the program could just as well do some useful work in this time instead.
+
+Another, perhaps more common use of the DMA controller is to transfer between memory and an IO
+peripheral. In this situation the address of the IO register does not change for each transfer but
+the memory address needs to be incremented. It is also necessary to control the pace of the
+transfer so as to not write data before it can be accepted by a peripheral or read it before the
+data is ready, and this can be controlled with the ``treq_sel`` field of the DMA channel's control
+register. The various fields of the control register for each DMA channel can be packed
+using the :meth:`DMA.pack_ctrl()` method and unpacked using the :meth:`DMA.unpack_ctrl()`
+static method. Code to transfer data from a byte array to the TX FIFO of a PIO state machine,
+one byte at a time, looks like this::
+
+ # pio_num is index of the PIO block being used, sm_num is the state machine in that block.
+ # my_state_machine is an rp2.PIO() instance.
+ DATA_REQUEST_INDEX = (pio_num << 3) + sm_num
+
+ src_data = bytearray(1024)
+ d = rp2.DMA()
+
+ # Transfer bytes, rather than words, don't increment the write address and pace the transfer.
+ c = d.pack_ctrl(size=0, inc_write=False, treq_sel=DATA_REQUEST_INDEX)
+
+ d.config(
+ read=src_data,
+ write=my_state_machine,
+ count=len(src_data),
+ ctrl=c,
+ trigger=True
+ )
+
+Note that in this example the value given for the write address is just the PIO state machine to
+which we are sending the data. This works because PIO state machines present the buffer protocol,
+allowing direct access to their data FIFO registers.
+
+Constructor
+-----------
+
+.. class:: DMA()
+
+ Claim one of the DMA controller channels for exclusive use.
+
+Methods
+-------
+
+.. method:: DMA.config(read=None, write=None, count=None, ctrl=None, trigger=False)
+
+ Configure the DMA registers for the channel and optionally start the transfer.
+ Parameters are:
+
+ - *read*: The address from which the DMA controller will start reading data or
+ an object that will provide data to be read. It can be an integer or any
+ object that supports the buffer protocol.
+ - *write*: The address to which the DMA controller will start writing or an
+ object into which data will be written. It can be an integer or any object
+ that supports the buffer protocol.
+ - *count*: The number of bus transfers that will execute before this channel
+ stops. Note that this is the number of transfers, not the number of bytes.
+ If the transfers are 2 or 4 bytes wide then the total amount of data moved
+ (and thus the size of required buffer) needs to be multiplied accordingly.
+ - *ctrl*: The value for the DMA control register. This is an integer value
+ that is typically packed using the :meth:`DMA.pack_ctrl()`.
+ - *trigger*: Optionally commence the transfer immediately.
+
+.. method:: DMA.irq(handler=None, hard=False)
+
+ Returns the IRQ object for this DMA channel and optionally configures it.
+
+.. method:: DMA.close()
+
+ Release the claim on the underlying DMA channel and free the interrupt
+ handler. The :class:`DMA` object can not be used after this operation.
+
+.. method:: DMA.pack_ctrl(default=None, **kwargs)
+
+ Pack the values provided in the keyword arguments into the named fields of a new control
+ register value. Any field that is not provided will be set to a default value. The
+ default will either be taken from the provided ``default`` value, or if that is not
+ given, a default suitable for the current channel; setting this to the current value
+ of the `DMA.ctrl` attribute provides an easy way to override a subset of the fields.
+
+ The keys for the keyword arguments can be any key returned by the :meth:`DMA.unpack_ctrl()`
+ method. The writable values are:
+
+ - *enable*: ``bool`` Set to enable the channel (default: ``True``).
+
+ - *high_pri*: ``bool`` Make this channel's bus traffic high priority (default: ``False``).
+
+ - *size*: ``int`` Transfer size: 0=byte, 1=half word, 2=word (default: 2).
+
+ - *inc_read*: ``bool`` Increment the read address after each transfer (default: ``True``).
+
+ - *inc_write*: ``bool`` Increment the write address after each transfer (default: ``True``).
+
+ - *ring_size*: ``int`` If non-zero, only the bottom ``ring_size`` bits of one
+ address register will change when an address is incremented, causing the
+ address to wrap at the next ``1 << ring_size`` byte boundary. Which
+ address is wrapped is controlled by the ``ring_sel`` flag. A zero value
+ disables address wrapping.
+
+ - *ring_sel*: ``bool`` Set to ``False`` to have the ``ring_size`` apply to the read address
+ or ``True`` to apply to the write address.
+
+ - *chain_to*: ``int`` The channel number for a channel to trigger after this transfer
+ completes. Setting this value to this DMA object's own channel number
+ disables chaining (this is the default).
+
+ - *treq_sel*: ``int`` Select a Transfer Request signal. See section 2.5.3 in the RP2040
+ datasheet for details.
+
+ - *irq_quiet*: ``bool`` Do not generate interrupt at the end of each transfer. Interrupts
+ will instead be generated when a zero value is written to the trigger
+ register, which will halt a sequence of chained transfers (default:
+ ``True``).
+
+ - *bswap*: ``bool`` If set to true, bytes in words or half-words will be reversed before
+ writing (default: ``True``).
+
+ - *sniff_en*: ``bool`` Set to ``True`` to allow data to be accessed by the chips sniff
+ hardware (default: ``False``).
+
+ - *write_err*: ``bool`` Setting this to ``True`` will clear a previously reported write
+ error.
+
+ - *read_err*: ``bool`` Setting this to ``True`` will clear a previously reported read
+ error.
+
+ See the description of the ``CH0_CTRL_TRIG`` register in section 2.5.7 of the RP2040
+ datasheet for details of all of these fields.
+
+.. method:: DMA.unpack_ctrl(value)
+
+ Unpack a value for a DMA channel control register into a dictionary with key/value pairs
+ for each of the fields in the control register. *value* is the ``ctrl`` register value
+ to unpack.
+
+ This method will return values for all the keys that can be passed to ``DMA.pack_ctrl``.
+ In addition, it will also return the read-only flags in the control register: ``busy``,
+ which goes high when a transfer starts and low when it ends, and ``ahb_err``, which is
+ the logical OR of the ``read_err`` and ``write_err`` flags. These values will be ignored
+ when packing, so that the dictionary created by unpacking a control register can be used
+ directly as the keyword arguments for packing.
+
+.. method:: DMA.active([value])
+
+ Gets or sets whether the DMA channel is currently running.
+
+ >>> sm.active()
+ 0
+ >>> sm.active(1)
+ >>> while sm.active():
+ ... pass
+
+Attributes
+----------
+
+.. attribute:: DMA.read
+
+ This attribute reflects the address from which the next bus transfer
+ will read. It may be written with either an integer or an object
+ that supports the buffer protocol and doing so has immediate effect.
+
+.. attribute:: DMA.write
+
+ This attribute reflects the address to which the next bus transfer
+ will write. It may be written with either an integer or an object
+ that supports the buffer protocol and doing so has immediate effect.
+
+.. attribute:: DMA.count
+
+ Reading this attribute will return the number of remaining bus
+ transfers in the *current* transfer sequence. Writing this attribute
+ sets the total number of transfers to be the *next* transfer sequence.
+
+.. attribute:: DMA.ctrl
+
+ This attribute reflects DMA channel control register. It is typically written
+ with an integer packed using the :meth:`DMA.pack_ctrl()` method. The returned
+ register value can be unpacked using the :meth:`DMA.unpack_ctrl()` method.
+
+.. attribute:: DMA.channel
+
+ The channel number of the DMA channel. This can be passed in the ``chain_to``
+ argument of `DMA.pack_ctrl()` on another channel to allow DMA chaining.
+
+.. attribute:: DMA.registers
+
+ This attribute is an array-like object that allows direct access to
+ the DMA channel's registers. The index is by word, rather than by byte,
+ so the register indices are the register address offsets divided by 4.
+ See the RP2040 data sheet for register details.
+
+Chaining and trigger register access
+------------------------------------
+
+The DMA controller in the RP2040 offers a couple advanced features to allow one DMA channel
+to initiate a transfer on another channel. One is the use of the ``chain_to`` value in the
+control register and the other is writing to one of the DMA channel's registers that has a
+trigger effect. When coupled with the ability to have one DMA channel write directly to the
+`DMA.registers` of another channel, this allows for complex transactions to be performed
+without any CPU intervention.
+
+Below is an example of using both chaining and register
+triggering to implement gathering of multiple blocks of data into a single destination. Full
+details of these features can be found in section 2.5 of the RP2040 data sheet and the code
+below is a Pythonic version of the example in sub-section 2.5.6.2.
+
+.. code-block:: python
+
+ from rp2 import DMA
+ from uctypes import addressof
+ from array import array
+
+ def gather_strings(string_list, buf):
+ # We use two DMA channels. The first sends lengths and source addresses from the gather
+ # list to the registers of the second. The second copies the data itself.
+ gather_dma = DMA()
+ buffer_dma = DMA()
+
+ # Pack up length/address pairs to be sent to the registers.
+ gather_list = array("I")
+
+ for s in string_list:
+ gather_list.append(len(s))
+ gather_list.append(addressof(s))
+
+ gather_list.append(0)
+ gather_list.append(0)
+
+ # When writing to the registers of the second DMA channel, we need to wrap the
+ # write address on an 8-byte (1<<3 bytes) boundary. We write to the ``TRANS_COUNT``
+ # and ``READ_ADD_TRIG`` registers in the last register alias (registers 14 and 15).
+ gather_ctrl = gather_dma.pack_ctrl(ring_size=3, ring_sel=True)
+ gather_dma.config(
+ read=gather_list, write=buffer_dma.registers[14:16],
+ count=2, ctrl=gather_ctrl
+ )
+
+ # When copying the data, the transfer size is single bytes, and when completed we need
+ # to chain back to the start another gather DMA transaction.
+ buffer_ctrl = buffer_dma.pack_ctrl(size=0, chain_to=gather_dma.channel)
+ # The read and count values will be set by the other DMA channel.
+ buffer_dma.config(write=buf, ctrl=buffer_ctrl)
+
+ # Set the transfer in motion.
+ gather_dma.active(1)
+
+ # Wait until all the register values have been sent
+ end_address = addressof(gather_list) + 4 * len(gather_list)
+ while gather_dma.read != end_address:
+ pass
+
+ input = ["This is ", "a ", "test", " of the scatter", " gather", " process"]
+ output = bytearray(64)
+
+ print(output)
+ gather_strings(input, output)
+ print(output)
+
+This example idles while waiting for the transfer to complete; alternatively it could
+set an interrupt handler and return immediately.
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.PIO.rst b/docs/library/rp2.PIO.rst
index e0675af1e9a2c..f922456c8c483 100644
--- a/docs/library/rp2.PIO.rst
+++ b/docs/library/rp2.PIO.rst
@@ -27,6 +27,17 @@ Constructors
Methods
-------
+.. method:: PIO.gpio_base([base])
+
+ Query and optionally set the current GPIO base for this PIO instance.
+
+ If an argument is given then it must be a pin (or integer corresponding to a pin
+ number), restricted to either GPIO0 or GPIO16. The GPIO base will then be set to
+ that pin. Setting the GPIO base must be done before any programs are added or state
+ machines created.
+
+ Returns the current GPIO base pin.
+
.. method:: PIO.add_program(program)
Add the *program* to the instruction memory of this PIO instance.
diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst
index ee16ce3c513da..1cb87e90b6e2d 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.
@@ -140,3 +140,10 @@ Methods
Optionally configure it.
+Buffer protocol
+---------------
+
+The StateMachine class supports the `buffer protocol`, allowing direct access to the transmit
+and receive FIFOs for each state machine. This is primarily in order to allow StateMachine
+objects to be passed directly as the read or write parameters when configuring a `rp2.DMA()`
+channel.
diff --git a/docs/library/rp2.rst b/docs/library/rp2.rst
index 7a473387b4a81..a215e98b51e55 100644
--- a/docs/library/rp2.rst
+++ b/docs/library/rp2.rst
@@ -23,7 +23,7 @@ The ``rp2`` module includes functions for assembling PIO programs.
For running PIO programs, see :class:`rp2.StateMachine`.
-.. function:: asm_pio(*, out_init=None, set_init=None, sideset_init=None, in_shiftdir=0, out_shiftdir=0, autopush=False, autopull=False, push_thresh=32, pull_thresh=32, fifo_join=PIO.JOIN_NONE)
+.. function:: asm_pio(*, out_init=None, set_init=None, sideset_init=None, side_pindir=False, in_shiftdir=PIO.SHIFT_LEFT, out_shiftdir=PIO.SHIFT_LEFT, autopush=False, autopull=False, push_thresh=32, pull_thresh=32, fifo_join=PIO.JOIN_NONE)
Assemble a PIO program.
@@ -35,8 +35,10 @@ For running PIO programs, see :class:`rp2.StateMachine`.
- *out_init* configures the pins used for ``out()`` instructions.
- *set_init* configures the pins used for ``set()`` instructions. There can
be at most 5.
- - *sideset_init* configures the pins used side-setting. There can be at
- most 5.
+ - *sideset_init* configures the pins used for ``.side()`` modifiers. There
+ can be at most 5.
+ - *side_pindir* when set to ``True`` configures ``.side()`` modifiers to be
+ used for pin directions, instead of pin values (the default, when ``False``).
The following parameters are used by default, but can be overridden in
`StateMachine.init()`:
@@ -241,6 +243,7 @@ Classes
.. toctree::
:maxdepth: 1
+ rp2.DMA.rst
rp2.Flash.rst
rp2.PIO.rst
rp2.StateMachine.rst
diff --git a/docs/library/ssl.rst b/docs/library/ssl.rst
index f9be27745379b..4327c74bad6c8 100644
--- a/docs/library/ssl.rst
+++ b/docs/library/ssl.rst
@@ -13,7 +13,7 @@ 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, cadata=None, server_hostname=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`
@@ -117,11 +117,32 @@ Exceptions
This exception does NOT exist. Instead its base class, OSError, is used.
+DTLS support
+------------
+
+.. admonition:: Difference to CPython
+ :class: attention
+
+ This is a MicroPython extension.
+
+This module supports DTLS in client and server mode via the `PROTOCOL_DTLS_CLIENT`
+and `PROTOCOL_DTLS_SERVER` constants that can be used as the ``protocol`` argument
+of `SSLContext`.
+
+In this case the underlying socket is expected to behave as a datagram socket (i.e.
+like the socket opened with ``socket.socket`` with ``socket.AF_INET`` as ``af`` and
+``socket.SOCK_DGRAM`` as ``type``).
+
+DTLS is only supported on ports that use mbed TLS, and it is not enabled by default:
+it requires enabling ``MBEDTLS_SSL_PROTO_DTLS`` in the specific port configuration.
+
Constants
---------
.. data:: ssl.PROTOCOL_TLS_CLIENT
ssl.PROTOCOL_TLS_SERVER
+ ssl.PROTOCOL_DTLS_CLIENT (when DTLS support is enabled)
+ ssl.PROTOCOL_DTLS_SERVER (when DTLS support is enabled)
Supported values for the *protocol* parameter.
diff --git a/docs/library/struct.rst b/docs/library/struct.rst
index 026cb5e8ac3b4..c2357505960d7 100644
--- a/docs/library/struct.rst
+++ b/docs/library/struct.rst
@@ -45,6 +45,8 @@ The following data types are supported:
+--------+--------------------+-------------------+---------------+
| Q | unsigned long long | integer (`1`) | 8 |
+--------+--------------------+-------------------+---------------+
+| e | n/a (half-float) | float (`2`) | 2 |
++--------+--------------------+-------------------+---------------+
| f | float | float (`2`) | 4 |
+--------+--------------------+-------------------+---------------+
| d | double | float (`2`) | 8 |
diff --git a/docs/library/sys.rst b/docs/library/sys.rst
index c8eb4b5c502b9..baefd927051d2 100644
--- a/docs/library/sys.rst
+++ b/docs/library/sys.rst
@@ -12,9 +12,12 @@ Functions
.. function:: exit(retval=0, /)
Terminate current program with a given exit code. Underlyingly, this
- function raise as `SystemExit` exception. If an argument is given, its
+ function raises a `SystemExit` exception. If an argument is given, its
value given as an argument to `SystemExit`.
+ On embedded ports (i.e. all ports but Windows and Unix), an unhandled
+ `SystemExit` currently causes a :ref:`soft_reset` of MicroPython.
+
.. function:: atexit(func)
Register *func* to be called upon termination. *func* must be a callable
@@ -69,14 +72,29 @@ 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)
+ * *_build* - string that can help identify the configuration that
+ MicroPython was built with
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"``.
+
+ The *_build* entry was added in version 1.25.0 and is a hyphen-separated
+ set of elements. New elements may be appended in the future so it's best to
+ access this field using ``sys.implementation._build.split("-")``. The
+ elements that are currently used are:
+
+ * On the unix, webassembly and windows ports the first element is the variant
+ name, for example ``'standard'``.
+ * On microcontroller targets, the first element is the board name and the second
+ element (if present) is the board variant, for example ``'RPI_PICO2-RISCV'``
+
.. admonition:: Difference to CPython
:class: attention
diff --git a/docs/library/vfs.rst b/docs/library/vfs.rst
new file mode 100644
index 0000000000000..1fa1e3060cb5b
--- /dev/null
+++ b/docs/library/vfs.rst
@@ -0,0 +1,216 @@
+: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:: mount()
+ :noindex:
+
+ With no arguments to :func:`mount`, return a list of tuples representing
+ all active mountpoints.
+
+ The returned list has the form *[(fsobj, mount_point), ...]*.
+
+.. 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/zephyr.DiskAccess.rst b/docs/library/zephyr.DiskAccess.rst
index 3e5fa9a3575a0..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:`os.AbstractBlockDev`.
+ :class:`vfs.AbstractBlockDev`.
diff --git a/docs/library/zephyr.FlashArea.rst b/docs/library/zephyr.FlashArea.rst
index 9cd4dd59d6852..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:`os.AbstractBlockDev`.
+ :class:`vfs.AbstractBlockDev`.
diff --git a/docs/library/zephyr.rst b/docs/library/zephyr.rst
index 10676d9085289..1a106d50ea717 100644
--- a/docs/library/zephyr.rst
+++ b/docs/library/zephyr.rst
@@ -22,9 +22,10 @@ Functions
Returns the thread id of the current thread, which is used to reference the thread.
-.. function:: thread_analyze()
+.. function:: thread_analyze(cpu)
- Runs the Zephyr debug thread analyzer on the current thread and prints stack size statistics in the format:
+ Runs the Zephyr debug thread analyzer on the current thread on the given cpu
+ and prints stack size statistics in the format:
"``thread_name``-20s: STACK: unused ``available_stack_space`` usage ``stack_space_used``
/ ``stack_size`` (``percent_stack_space_used`` %); CPU: ``cpu_utilization`` %"
@@ -35,6 +36,9 @@ Functions
For more information, see documentation for Zephyr `thread analyzer
`_.
+ Note that the ``cpu`` argument is only used in Zephyr v4.0.0 and
+ newer and ignored otherwise.
+
.. function:: shell_exec(cmd_in)
Executes the given command on an UART backend. This function can only be accessed if ``CONFIG_SHELL_BACKEND_SERIAL``
diff --git a/docs/mimxrt/pinout.rst b/docs/mimxrt/pinout.rst
index 16bb4722734a2..9aeb85401be8d 100644
--- a/docs/mimxrt/pinout.rst
+++ b/docs/mimxrt/pinout.rst
@@ -30,26 +30,28 @@ 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
+Makerdiary RT1011 - D9/D10 D13/A0 D11/D12
================= =========== =========== =========== ===========
|
-================ =========== =========== ======= ======= =====
-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 - - -
-================ =========== =========== ======= ======= =====
+================= =========== =========== ======= ======= =====
+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 - - -
+Makerdiary RT1011 A1/A2 - - - -
+================= =========== =========== ======= ======= =====
.. _mimxrt_pwm_pinout:
@@ -188,7 +190,6 @@ LED_BLUE F1/3/B
========= ===============
Pin Olimex RT1010PY
========= ===============
-D0 -
D1 F1/0/B
D2 F1/0/A
D3 F1/1/B
@@ -197,13 +198,10 @@ 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
@@ -214,6 +212,32 @@ CS0 F1/1/X
SCK F1/0/X
========= ===============
+|
+
+========= =================
+Pin Makerdiary RT1011
+========= =================
+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
+A3 F1/2/B
+A4 F1/2/A
+A5 F1/3/B
+A6 F1/3/A
+A9 F1/3/X
+A10 F1/2/X
+A11 F1/1/X
+SD1 F1/0/B
+SD2 F1/0/A
+LED F1/1/B
+DIO F1/0/X
+========= =================
+
Legend:
* Qm/n: QTMR module m, channel n
@@ -319,9 +343,10 @@ 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 - -
+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
+Makerdiary RT1011 A5/A2/A4/A3/A6 A11/A1/A10/A9/CLK
================= ========================= ======================= ===============
Pins denoted with (*) are by default not wired at the board. The CS0 and CS1 signals
@@ -355,6 +380,7 @@ 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 - -
+Makerdiary RT1011 D1/D2 A7/A8
================= =========== =========== =========== ======= =======
.. _mimxrt_i2s_pinout:
@@ -375,10 +401,11 @@ 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
+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"
+Makerdiary RT1011 1 D8 SD1 D7 D4 D1 D2 D3
================= == ===== ======== ======= ======= ======== ======= =======
Symbolic pin names are provided for the MIMXRT_10xx_DEV boards.
diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst
index 578364c55a4ce..9f1efd4ffcad2 100644
--- a/docs/mimxrt/quickref.rst
+++ b/docs/mimxrt/quickref.rst
@@ -122,10 +122,13 @@ See :ref:`machine.UART `. ::
uart1 = UART(1, baudrate=115200)
uart1.write('hello') # write 5 bytes
uart1.read(5) # read up to 5 bytes
+ uart1 = UART(baudrate=19200) # open UART 1 at 19200 baud
The i.MXRT has up to eight hardware UARTs, but not every board exposes all
TX and RX pins for users. For the assignment of Pins to UART signals,
-refer to the :ref:`UART pinout `.
+refer to the :ref:`UART pinout `. If the UART ID is
+omitted, UART(1) is selected. Then, the keyword
+option for baudrate must be used to change it from the default value.
PWM (pulse width modulation)
----------------------------
@@ -193,7 +196,7 @@ PWM Constructor
- *freq* should be an integer which sets the frequency in Hz for the
PWM cycle. The valid frequency range is 15 Hz resp. 18Hz resp. 24Hz up to > 1 MHz.
- - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65536``.
+ - *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``.
The duty cycle of a X channel can only be changed, if the A and B channel
of the respective submodule is not used. Otherwise the duty_16 value of the
X channel is 32768 (50%).
@@ -231,7 +234,7 @@ is created by dividing the pwm_clk signal by an integral factor, according to th
f = pwm_clk / (2**n * m)
-with n being in the range of 0..7, and m in the range of 2..65536. pmw_clk is 125Mhz
+with n being in the range of 0..7, and m in the range of 2..65535. pmw_clk is 125Mhz
for MIMXRT1010/1015/1020, 150 MHz for MIMXRT1050/1060/1064 and 160MHz for MIMXRT1170.
The lowest frequency is pwm_clk/2**23 (15, 18, 20Hz). The highest frequency with
U16 resolution is pwm_clk/2**16 (1907, 2288, 2441 Hz), the highest frequency
@@ -255,7 +258,7 @@ Use the :ref:`machine.ADC ` class::
from machine import ADC
adc = ADC(Pin('A2')) # create ADC object on ADC pin
- adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
+ adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
value returned by read_u16(). If you need a higher resolution or better accuracy, use
@@ -305,12 +308,15 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
cs_pin(0)
spi.write('Hello World')
cs_pin(1)
+ spi = SPI(baudrate=4_000_000) # Use SPI(0) at a baudrate of 4 MHz
For the assignment of Pins to SPI signals, refer to
:ref:`Hardware SPI pinout `.
The keyword option cs=n can be used to enable the cs pin 0 or 1 for an automatic cs signal. The
-default is cs=-1. Using cs=-1 the automatic cs signal is not created.
+default is cs=-1. Using cs=-1 the automatic cs signal is not created.
In that case, cs has to be set by the script. Clearing that assignment requires a power cycle.
+If the SPI ID is omitted, SPI(0) is selected. Then, the keyword
+option for baudrate must be used to change it from the default value.
Notes:
@@ -355,6 +361,10 @@ has the same methods as software SPI above::
i2c = I2C(0, 400_000)
i2c.writeto(0x76, b"Hello World")
+ i2c = I2C(freq=100_000) # use I2C(0) at 100kHz
+
+If the I2C ID is omitted, I2C(0) is selected. Then, the keyword
+option for freq must be used to change the freq from the default value.
I2S bus
-------
@@ -429,7 +439,9 @@ See :ref:`machine.RTC `::
from machine import RTC
rtc = RTC()
- rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
+ # time, eg. 2017/8/23 1:12:48
+ # the day-of-week value is ignored
rtc.datetime() # get date and time
rtc.now() # return date and time in CPython format.
@@ -438,32 +450,36 @@ The i.MXRT MCU supports battery backup of the RTC. By connecting a battery of
current drawn from the battery is ~20µA, which is rather high. A CR2032 coin
cell will last for about one year.
+Note: In v1.23.0 the support for subseconds was removed. When reading the RTC, 0 will
+be returned as value for subsecond, When setting the RTC time, the subsecond
+field is ignored. The RTC itself does not provide a microsecond value.
+
SD card
-------
See :ref:`machine.SDCard `::
- import machine, os
+ import machine, os, vfs
sd = machine.SDCard()
- fs = os.VfsFat(sd)
- os.mount(fs, "/sd") # mount
+ fs = vfs.VfsFat(sd)
+ vfs.mount(fs, "/sd") # mount
os.listdir('/sd') # list directory contents
- os.umount('/sd') # eject
+ vfs.umount('/sd') # eject
Note: The i.mx-rt 1011 and 1015 based boards do not support the ``machine.SDCard``
class. For these, the SPI based driver ``sdcard.py`` from the MicroPython drivers
can be used. When using it, you have to overdrive the CS pin of the SPI hardware
module. Example::
- import os, sdcard, machine
+ import vfs, sdcard, machine
cs_pin = "D10"
spi = machine.SPI(0) # SPI0 with cs at Pin "D10" used for SDCARD
cs = machine.Pin(cs_pin, machine.Pin.OUT, value=1)
sd = sdcard.SDCard(spi, cs)
- vfs = os.VfsFat(sd)
- os.mount(vfs, "/sdcard")
+ fs = vfs.VfsFat(sd)
+ vfs.mount(fs, "/sdcard")
OneWire driver
--------------
@@ -528,7 +544,7 @@ Ethernet. Example usage::
lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server.
-Otherwise, the IP address can be set with lan.ifconfig(). The default address
+Otherwise, the IP address can be set with lan.ipconfig(addr4="..."). The default address
is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an
diff --git a/docs/pyboard/general.rst b/docs/pyboard/general.rst
index 0fc7332dedf4f..d1bf3829bec18 100644
--- a/docs/pyboard/general.rst
+++ b/docs/pyboard/general.rst
@@ -21,7 +21,7 @@ If needed, you can prevent the use of the SD card by creating an empty file
called ``/flash/SKIPSD``. If this file exists when the pyboard boots
up then the SD card will be skipped and the pyboard will always boot from the
internal filesystem (in this case the SD card won't be mounted but you can still
-mount and use it later in your program using ``os.mount``).
+mount and use it later in your program using ``vfs.mount``).
(Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd``
is called ``1:/``).
diff --git a/docs/pyboard/quickref.rst b/docs/pyboard/quickref.rst
index 62157bff0a472..52ddc29b19340 100644
--- a/docs/pyboard/quickref.rst
+++ b/docs/pyboard/quickref.rst
@@ -138,7 +138,9 @@ See :ref:`pyb.RTC ` ::
from pyb import RTC
rtc = RTC()
- rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime((2017, 8, 23, 0, 1, 12, 48, 0)) # set a specific date and
+ # time, eg. 2017/8/23 1:12:48
+ # the day-of-week value is ignored
rtc.datetime() # get date and time
PWM (pulse width modulation)
diff --git a/docs/pyboard/tutorial/reset.rst b/docs/pyboard/tutorial/reset.rst
index 59a3cd82ae1a7..ad56995c60dd7 100644
--- a/docs/pyboard/tutorial/reset.rst
+++ b/docs/pyboard/tutorial/reset.rst
@@ -10,6 +10,8 @@ execution of ``boot.py`` and ``main.py`` and gives default USB settings.
If you have problems with the filesystem you can do a factory reset,
which restores the filesystem to its original state.
+For more information, see :doc:`/reference/reset_boot`.
+
Safe mode
---------
diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst
index 59c375159b2c6..d9a349aa6bb27 100644
--- a/docs/reference/constrained.rst
+++ b/docs/reference/constrained.rst
@@ -211,7 +211,7 @@ two loops:
spi.readinto(buf)
# process data in buf
-The first creates a buffer on each pass whereas the second re-uses a pre-allocated
+The first creates a buffer on each pass whereas the second reuses a pre-allocated
buffer; this is both faster and more efficient in terms of memory fragmentation.
**Bytes are smaller than ints**
diff --git a/docs/reference/filesystem.rst b/docs/reference/filesystem.rst
index ca9e56344ed4c..48a465856027d 100644
--- a/docs/reference/filesystem.rst
+++ b/docs/reference/filesystem.rst
@@ -40,7 +40,7 @@ Block devices
-------------
A block device is an instance of a class that implements the
-:class:`os.AbstractBlockDev` protocol.
+:class:`vfs.AbstractBlockDev` protocol.
Built-in block devices
~~~~~~~~~~~~~~~~~~~~~~
@@ -108,16 +108,16 @@ RAM using a ``bytearray``::
It can be used as follows::
- import os
+ import vfs
bdev = RAMBlockDev(512, 50)
- os.VfsFat.mkfs(bdev)
- os.mount(bdev, '/ramdisk')
+ vfs.VfsFat.mkfs(bdev)
+ vfs.mount(bdev, '/ramdisk')
An example of a block device that supports both the simple and extended
interface (i.e. both signatures and behaviours of the
-:meth:`os.AbstractBlockDev.readblocks` and
-:meth:`os.AbstractBlockDev.writeblocks` methods) is::
+:meth:`vfs.AbstractBlockDev.readblocks` and
+:meth:`vfs.AbstractBlockDev.writeblocks` methods) is::
class RAMBlockDev:
def __init__(self, block_size, num_blocks):
@@ -148,13 +148,13 @@ interface (i.e. both signatures and behaviours of the
return 0
As it supports the extended interface, it can be used with :class:`littlefs
-`::
+`::
- import os
+ import vfs
bdev = RAMBlockDev(512, 50)
- os.VfsLfs2.mkfs(bdev)
- os.mount(bdev, '/ramdisk')
+ vfs.VfsLfs2.mkfs(bdev)
+ vfs.mount(bdev, '/ramdisk')
Once mounted, the filesystem (regardless of its type) can be used as it
normally would be used from Python code, for example::
@@ -166,8 +166,8 @@ normally would be used from Python code, for example::
Filesystems
-----------
-MicroPython ports can provide implementations of :class:`FAT `,
-:class:`littlefs v1 ` and :class:`littlefs v2 `.
+MicroPython ports can provide implementations of :class:`FAT `,
+:class:`littlefs v1 ` and :class:`littlefs v2 `.
The following table shows which filesystems are included in the firmware by
default for given port/board combinations, however they can be optionally
@@ -197,16 +197,16 @@ recommended to use littlefs instead.
To format the entire flash using FAT::
# ESP8266 and ESP32
- import os
- os.umount('/')
- os.VfsFat.mkfs(bdev)
- os.mount(bdev, '/')
+ import vfs
+ vfs.umount('/')
+ vfs.VfsFat.mkfs(bdev)
+ vfs.mount(bdev, '/')
# STM32
- import os, pyb
- os.umount('/flash')
- os.VfsFat.mkfs(pyb.Flash(start=0))
- os.mount(pyb.Flash(start=0), '/flash')
+ import os, vfs, pyb
+ vfs.umount('/flash')
+ vfs.VfsFat.mkfs(pyb.Flash(start=0))
+ vfs.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash')
Littlefs
@@ -222,16 +222,16 @@ resistant to filesystem corruption.
To format the entire flash using littlefs v2::
# ESP8266 and ESP32
- import os
- os.umount('/')
- os.VfsLfs2.mkfs(bdev)
- os.mount(bdev, '/')
+ import vfs
+ vfs.umount('/')
+ vfs.VfsLfs2.mkfs(bdev)
+ vfs.mount(bdev, '/')
# STM32
- import os, pyb
- os.umount('/flash')
- os.VfsLfs2.mkfs(pyb.Flash(start=0))
- os.mount(pyb.Flash(start=0), '/flash')
+ import os, vfs, pyb
+ vfs.umount('/flash')
+ vfs.VfsLfs2.mkfs(pyb.Flash(start=0))
+ vfs.mount(pyb.Flash(start=0), '/flash')
os.chdir('/flash')
A littlefs filesystem can be still be accessed on a PC over USB MSC using the
@@ -264,14 +264,14 @@ block devices spanning a subset of the flash device.
For example, to configure the first 256kiB as FAT (and available over USB MSC),
and the remainder as littlefs::
- import os, pyb
- os.umount('/flash')
+ import os, vfs, pyb
+ vfs.umount('/flash')
p1 = pyb.Flash(start=0, len=256*1024)
p2 = pyb.Flash(start=256*1024)
- os.VfsFat.mkfs(p1)
- os.VfsLfs2.mkfs(p2)
- os.mount(p1, '/flash')
- os.mount(p2, '/data')
+ vfs.VfsFat.mkfs(p1)
+ vfs.VfsLfs2.mkfs(p2)
+ vfs.mount(p1, '/flash')
+ vfs.mount(p2, '/data')
os.chdir('/flash')
This might be useful to make your Python files, configuration and other
@@ -282,9 +282,9 @@ failure, etc.
The partition at offset ``0`` will be mounted automatically (and the filesystem
type automatically detected), but you can add::
- import os, pyb
+ import vfs, pyb
p2 = pyb.Flash(start=256*1024)
- os.mount(p2, '/data')
+ vfs.mount(p2, '/data')
to ``boot.py`` to mount the data partition.
@@ -297,7 +297,7 @@ define an arbitrary partition layout.
At boot, the partition named "vfs" will be mounted at ``/`` by default, but any
additional partitions can be mounted in your ``boot.py`` using::
- import esp32, os
+ import esp32, vfs
p = esp32.Partition.find(esp32.Partition.TYPE_DATA, label='foo')
- os.mount(p, '/foo')
+ vfs.mount(p, '/foo')
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index 98f6b65737699..1558c0fdfa9b6 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -21,6 +21,7 @@ implementation and the best practices to use them.
glossary.rst
repl.rst
+ reset_boot.rst
mpremote.rst
mpyfiles.rst
isr_rules.rst
diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst
index ea330acad3aaa..5e8d6ad61201a 100644
--- a/docs/reference/isr_rules.rst
+++ b/docs/reference/isr_rules.rst
@@ -170,11 +170,17 @@ is partially updated. When the ISR tries to read the object, a crash results. Be
on rare, random occasions they can be hard to diagnose. There are ways to circumvent this issue, described in
:ref:`Critical Sections ` below.
-It is important to be clear about what constitutes the modification of an object. An alteration to a built-in type
-such as a dictionary is problematic. Altering the contents of an array or bytearray is not. This is because bytes
-or words are written as a single machine code instruction which is not interruptible: in the parlance of real time
-programming the write is atomic. A user defined object might instantiate an integer, array or bytearray. It is valid
-for both the main loop and the ISR to alter the contents of these.
+It is important to be clear about what constitutes the modification of an object. Altering the contents of an array
+or bytearray is safe. This is because bytes or words are written as a single machine code instruction which is not
+interruptible: in the parlance of real time programming the write is atomic. The same is true of updating a
+dictionary item because items are machine words, being integers or pointers to objects. A user defined object might
+instantiate an array or bytearray. It is valid for both the main loop and the ISR to alter the contents of these.
+
+The hazard arises when the structure of an object is altered, notably in the case of dictionaries. Adding or deleting
+keys can trigger a rehash. If a hard ISR runs while a rehash is in progress and attempts to access an item, a crash
+may occur. Internally globals are implemented as a dictionary. Consequently the main program should create all
+necessary globals before starting a process that generates hard interrupts. Application code should also avoid
+deleting globals.
MicroPython supports integers of arbitrary precision. Values between 2**30 -1 and -2**30 will be stored in
a single machine word. Larger values are stored as Python objects. Consequently changes to long integers cannot
@@ -203,7 +209,7 @@ issue a further interrupt. It then schedules a callback to process the data.
Scheduled callbacks should comply with the principles of interrupt handler design outlined below. This is to
avoid problems resulting from I/O activity and the modification of shared data which can arise in any code
-which pre-empts the main program loop.
+which preempts the main program loop.
Execution time needs to be considered in relation to the frequency with which interrupts can occur. If an
interrupt occurs while the previous callback is executing, a further instance of the callback will be queued
diff --git a/docs/reference/manifest.rst b/docs/reference/manifest.rst
index 9bcafd5839cab..dc9d6dd75b2b8 100644
--- a/docs/reference/manifest.rst
+++ b/docs/reference/manifest.rst
@@ -26,7 +26,7 @@ re-flashing the entire firmware. However, it can still be useful to
selectively freeze some rarely-changing dependencies (such as third-party
libraries).
-The way to list the Python files to be be frozen into the firmware is via
+The way to list the Python files to be frozen into the firmware is via
a "manifest", which is a Python file that will be interpreted by the build
process. Typically you would write a manifest file as part of a board
definition, but you can also write a stand-alone manifest file and use it with
@@ -95,6 +95,17 @@ Note: The ``opt`` keyword argument can be set on the various functions, this con
the optimisation level used by the cross-compiler.
See :func:`micropython.opt_level`.
+.. function:: add_library(library, library_path, prepend=False)
+
+ Register the path to an external named *library*.
+
+ The path *library_path* will be automatically searched when using `require`.
+ By default the added library is added to the end of the list of libraries to
+ search. Pass ``True`` to *prepend* to add it to the start of the list.
+
+ Additionally, the added library can be explicitly requested by using
+ ``require("name", library="library")``.
+
.. function:: package(package_path, files=None, base_path=".", opt=None)
This is equivalent to copying the "package_path" directory to the device
@@ -138,11 +149,13 @@ See :func:`micropython.opt_level`.
You can use the variables above, such as ``$(PORT_DIR)`` in ``base_path``.
-.. function:: require(name, unix_ffi=False)
+.. function:: require(name, library=None)
Require a package by name (and its dependencies) from :term:`micropython-lib`.
- Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
+ Optionally specify *library* (a string) to reference a package from a
+ library that has been previously registered with `add_library`. Otherwise
+ the list of library paths will be used.
.. function:: include(manifest_path)
diff --git a/docs/reference/micropython2_migration.rst b/docs/reference/micropython2_migration.rst
index 954488b8cdf4b..3a114711406fd 100644
--- a/docs/reference/micropython2_migration.rst
+++ b/docs/reference/micropython2_migration.rst
@@ -71,4 +71,11 @@ which is useful for development and testing.
Changes
~~~~~~~
-*None yet*
+Introduction of a new module :mod:`vfs`. The following functions and
+classes have moved out of :mod:`os` to :mod:`vfs`:
+- `os.mount`
+- `os.umount`
+- `os.VfsFat`
+- `os.VfsLfs1`
+- `os.VfsLfs2`
+- `os.VfsPosix`
diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst
index 08ef5d31ff572..32ca5c246a7a4 100644
--- a/docs/reference/mpremote.rst
+++ b/docs/reference/mpremote.rst
@@ -78,6 +78,7 @@ The full list of supported commands are:
- `mip `
- `mount `
- `unmount `
+- `romfs `
- `rtc `
- `sleep `
- `reset `
@@ -227,24 +228,45 @@ The full list of supported commands are:
- ``cat `` to show the contents of a file or files on the device
- ``ls`` to list the current directory
- ``ls `` to list the given directories
- - ``cp [-r] `` to copy files
- - ``rm `` to remove files on the device
+ - ``cp [-rf] `` to copy files
+ - ``rm [-r] `` to remove files or folders on the device
- ``mkdir `` to create directories on the device
- ``rmdir `` to remove directories on the device
- ``touch `` to create the files (if they don't already exist)
+ - ``sha256sum `` to calculate the SHA256 sum of files
The ``cp`` command uses a convention where a leading ``:`` represents a remote
path. Without a leading ``:`` means a local path. This is based on the
convention used by the `Secure Copy Protocol (scp) client
- `_. All other commands
- implicitly assume the path is a remote path, but the ``:`` can be optionally
- used for clarity.
+ `_.
So for example, ``mpremote fs cp main.py :main.py`` copies ``main.py`` from
the current local directory to the remote filesystem, whereas
``mpremote fs cp :main.py main.py`` copies ``main.py`` from the device back
to the current directory.
+ The ``mpremote rm -r`` command accepts both relative and absolute paths.
+ Use ``:`` to refer to the current remote working directory (cwd) to allow a
+ directory tree to be removed from the device's default path (eg ``/flash``, ``/``).
+ Use ``-v/--verbose`` to see the files being removed.
+
+ For example:
+
+ - ``mpremote rm -r :libs`` will remove the ``libs`` directory and all its
+ child items from the device.
+ - ``mpremote rm -rv :/sd`` will remove all files from a mounted SDCard and result
+ in a non-blocking warning. The mount will be retained.
+ - ``mpremote rm -rv :/`` will remove all files on the device, including any
+ located in mounted vfs such as ``/sd`` or ``/flash``. After removing all folders
+ and files, this will also return an error to mimic unix ``rm -rf /`` behaviour.
+
+ .. warning::
+ There is no supported way to undelete files removed by ``mpremote rm -r :``.
+ Please use with caution.
+
+ All other commands implicitly assume the path is a remote path, but the ``:``
+ can be optionally used for clarity.
+
All of the filesystem sub-commands take multiple path arguments, so if there
is another command in the sequence, you must use ``+`` to terminate the
arguments, e.g.
@@ -256,6 +278,11 @@ The full list of supported commands are:
This will copy the file to the device then enter the REPL. The ``+`` prevents
``"repl"`` being interpreted as a path.
+ The ``cp`` command supports the ``-r`` option to make a recursive copy. By
+ default ``cp`` will skip copying files to the remote device if the SHA256 hash
+ of the source and destination file matches. To force a copy regardless of the
+ hash use the ``-f`` option.
+
**Note:** For convenience, all of the filesystem sub-commands are also
:ref:`aliased as regular commands `, i.e. you can write
``mpremote cp ...`` instead of ``mpremote fs cp ...``.
@@ -341,6 +368,29 @@ The full list of supported commands are:
This happens automatically when ``mpremote`` terminates, but it can be used
in a sequence to unmount an earlier mount before subsequent command are run.
+.. _mpremote_command_romfs:
+
+- **romfs** -- manage ROMFS partitions on the device:
+
+ .. code-block:: bash
+
+ $ mpremote romfs
+
+ ```` may be:
+
+ - ``romfs query`` to list all the available ROMFS partitions and their size
+ - ``romfs [-o