mirror of
https://github.com/micropython/micropython.git
synced 2025-12-31 17:20:13 +01:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cd15829e2 | ||
|
|
ee3c9ccb54 | ||
|
|
e72d03855e | ||
|
|
02df2b09d4 | ||
|
|
e7ff724a87 | ||
|
|
cc7cfc7e8d | ||
|
|
b979c5a92a | ||
|
|
f53ee9f12b | ||
|
|
2531a15200 | ||
|
|
8b6e89a8ca | ||
|
|
a2e9ab362b | ||
|
|
1e8cc6c503 | ||
|
|
4c7d955a62 | ||
|
|
068aa28fc5 | ||
|
|
d5f3fcd935 | ||
|
|
9b8c64c9ce | ||
|
|
ac5e0b9f62 | ||
|
|
61b8361f5f | ||
|
|
4b4f6011e8 |
@@ -1,12 +1,3 @@
|
||||
# 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
|
||||
|
||||
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -18,7 +18,6 @@
|
||||
# These should also not be modified by git.
|
||||
tests/basics/string_cr_conversion.py -text
|
||||
tests/basics/string_crlf_conversion.py -text
|
||||
tests/micropython/test_normalize_newlines.py.exp -text
|
||||
ports/stm32/pybcdc.inf_template -text
|
||||
ports/stm32/usbhost/** -text
|
||||
ports/cc3200/hal/aes.c -text
|
||||
|
||||
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report an issue
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead.
|
||||
|
||||
* In your issue, please include a clear and concise description of what the bug is, the expected output, and how to replicate it.
|
||||
|
||||
* If this issue involves external hardware, please include links to relevant datasheets and schematics.
|
||||
|
||||
* If you are seeing code being executed incorrectly, please provide a minimal example and expected output (e.g. comparison to CPython).
|
||||
|
||||
* For build issues, please include full details of your environment, compiler versions, command lines, and build output.
|
||||
|
||||
* Please provide as much information as possible about the version of MicroPython you're running, such as:
|
||||
- firmware file name
|
||||
- git commit hash and port/board
|
||||
- version information shown in the REPL (hit Ctrl-B to see the startup message)
|
||||
|
||||
* Remove all placeholder text above before submitting.
|
||||
109
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
109
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,109 +0,0 @@
|
||||
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.
|
||||
16
.github/ISSUE_TEMPLATE/documentation.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/documentation.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Documentation issue
|
||||
about: Report areas of the documentation or examples that need improvement
|
||||
title: 'docs: '
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab instead.
|
||||
|
||||
* Describe what was missing from the documentation and/or what was incorrect/incomplete.
|
||||
|
||||
* If possible, please link to the relevant page on https://docs.micropython.org/
|
||||
|
||||
* Remove all placeholder text above before submitting.
|
||||
46
.github/ISSUE_TEMPLATE/documentation.yml
vendored
46
.github/ISSUE_TEMPLATE/documentation.yml
vendored
@@ -1,46 +0,0 @@
|
||||
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.
|
||||
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Request a feature or improvement
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
* Please search existing issues before raising a new issue. For questions about MicroPython or for help using MicroPython, or any sort of "how do I?" requests, please use the Discussions tab or raise a documentation request instead.
|
||||
|
||||
* Describe the feature you'd like to see added to MicroPython. In particular, what does this feature enable and why is it useful. MicroPython aims to strike a balance between functionality and code size, so please consider whether this feature can be optionally enabled and whether it can be provided in other ways (e.g. pure-Python library).
|
||||
|
||||
* For core Python features, where possible please include a link to the relevant PEP.
|
||||
|
||||
* For new architectures / ports / boards, please provide links to relevant documentation, specifications, and toolchains. Any information about the popularity and unique features about this hardware would also be useful.
|
||||
|
||||
* For features for existing ports (e.g. new peripherals or microcontroller features), please describe which port(s) it applies too, and whether this is could be an extension to the machine API or a port-specific module?
|
||||
|
||||
* For drivers (e.g. for external hardware), please link to datasheets and/or existing drivers from other sources.
|
||||
|
||||
* Who do you expect will implement the feature you are requesting? Would you be willing to sponsor this work?
|
||||
|
||||
* Remove all placeholder text above before submitting.
|
||||
74
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
74
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,74 +0,0 @@
|
||||
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.
|
||||
16
.github/ISSUE_TEMPLATE/security.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/security.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Security report
|
||||
about: Report a security issue or vulnerability in MicroPython
|
||||
title: ''
|
||||
labels: security
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
* If you need to raise this issue privately with the MicroPython team, please email contact@micropython.org instead.
|
||||
|
||||
* Include a clear and concise description of what the security issue is.
|
||||
|
||||
* What does this issue allow an attacker to do?
|
||||
|
||||
* Remove all placeholder text above before submitting.
|
||||
60
.github/ISSUE_TEMPLATE/security.yml
vendored
60
.github/ISSUE_TEMPLATE/security.yml
vendored
@@ -1,60 +0,0 @@
|
||||
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
|
||||
33
.github/pull_request_template.md
vendored
33
.github/pull_request_template.md
vendored
@@ -1,33 +0,0 @@
|
||||
<!-- Thanks for submitting a Pull Request! We appreciate you spending the
|
||||
time to improve MicroPython. Please provide enough information so that
|
||||
others can review your Pull Request.
|
||||
|
||||
Before submitting, please read:
|
||||
https://github.com/micropython/micropython/blob/master/CODEOFCONDUCT.md
|
||||
https://github.com/micropython/micropython/wiki/ContributorGuidelines
|
||||
|
||||
Please check any CI failures that appear after your Pull Request is opened.
|
||||
-->
|
||||
|
||||
### Summary
|
||||
|
||||
<!-- Explain the reason for making this change. What problem does the pull request
|
||||
solve, or what improvement does it add? Add links if relevant. -->
|
||||
|
||||
|
||||
### Testing
|
||||
|
||||
<!-- Explain what testing you did, and on which boards/ports. If there are
|
||||
boards or ports that you couldn't test, please mention this here as well.
|
||||
|
||||
If you leave this empty then your Pull Request may be closed. -->
|
||||
|
||||
|
||||
### Trade-offs and Alternatives
|
||||
|
||||
<!-- If the Pull Request has some negative impact (i.e. increased code size)
|
||||
then please explain why you think the trade-off improvement is worth it.
|
||||
If you can think of alternative ways to do this, please explain that here too.
|
||||
|
||||
Delete this heading if not relevant (i.e. small fixes) -->
|
||||
|
||||
16
.github/workflows/biome.yml
vendored
16
.github/workflows/biome.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: JavaScript code lint and formatting with Biome
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- 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
|
||||
18
.github/workflows/code_formatting.yml
vendored
18
.github/workflows/code_formatting.yml
vendored
@@ -10,11 +10,21 @@ jobs:
|
||||
code-formatting:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install packages
|
||||
run: tools/ci.sh c_code_formatting_setup
|
||||
run: source tools/ci.sh && ci_c_code_formatting_setup
|
||||
- name: Run code formatting
|
||||
run: tools/ci.sh c_code_formatting_run
|
||||
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
|
||||
|
||||
17
.github/workflows/code_size.yml
vendored
17
.github/workflows/code_size.yml
vendored
@@ -1,21 +1,16 @@
|
||||
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 }}
|
||||
@@ -23,17 +18,17 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- name: Install packages
|
||||
run: tools/ci.sh code_size_setup
|
||||
run: source tools/ci.sh && ci_code_size_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh code_size_build
|
||||
run: source tools/ci.sh && ci_code_size_build
|
||||
- name: Compute code size difference
|
||||
run: source tools/ci.sh && ci_code_size_report
|
||||
run: tools/metrics.py diff ~/size0 ~/size1 | tee diff
|
||||
- name: Save PR number
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
|
||||
6
.github/workflows/code_size_comment.yml
vendored
6
.github/workflows/code_size_comment.yml
vendored
@@ -11,11 +11,11 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: 'Download artifact'
|
||||
id: download-artifact
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: unzip code-size-report.zip
|
||||
- name: Post comment to pull request
|
||||
if: steps.download-artifact.outputs.result == 'ok'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
|
||||
13
.github/workflows/codespell.yml
vendored
13
.github/workflows/codespell.yml
vendored
@@ -1,13 +0,0 @@
|
||||
name: Check spelling with codespell
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
# codespell version should be kept in sync with .pre-commit-config.yml
|
||||
- run: pip install --user codespell==2.4.1 tomli
|
||||
- run: codespell
|
||||
|
||||
10
.github/workflows/commit_formatting.yml
vendored
10
.github/workflows/commit_formatting.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Check commit message formatting
|
||||
|
||||
on: [pull_request]
|
||||
on: [push, pull_request]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -10,9 +10,9 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- uses: actions/setup-python@v6
|
||||
fetch-depth: '100'
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Check commit message formatting
|
||||
run: tools/ci.sh commit_formatting_run
|
||||
run: source tools/ci.sh && ci_commit_formatting_run
|
||||
|
||||
8
.github/workflows/docs.yml
vendored
8
.github/workflows/docs.yml
vendored
@@ -5,8 +5,6 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- docs/**
|
||||
- py/**
|
||||
- tests/cpydiff/**
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -17,11 +15,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install Python packages
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: Build unix port
|
||||
run: tools/ci.sh unix_build_helper
|
||||
- name: Build docs
|
||||
run: make -C docs/ html
|
||||
|
||||
2
.github/workflows/examples.yml
vendored
2
.github/workflows/examples.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
embedding:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
|
||||
- name: Run
|
||||
|
||||
4
.github/workflows/mpremote.yml
vendored
4
.github/workflows/mpremote.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Setting this to zero means fetch all history and tags,
|
||||
# which hatch-vcs can use to discover the version tag.
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v6
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Install build tools
|
||||
run: pip install build
|
||||
- name: Build mpremote wheel
|
||||
|
||||
12
.github/workflows/mpy_format.yml
vendored
12
.github/workflows/mpy_format.yml
vendored
@@ -6,8 +6,6 @@ on:
|
||||
paths:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'examples/**'
|
||||
- 'mpy-cross/**'
|
||||
- 'py/**'
|
||||
- 'tests/**'
|
||||
- 'tools/**'
|
||||
|
||||
@@ -17,12 +15,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get python2
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh mpy_format_setup
|
||||
run: source tools/ci.sh && ci_mpy_format_setup
|
||||
- name: Test mpy-tool.py
|
||||
run: tools/ci.sh mpy_format_test
|
||||
- name: Test mpy-cross debug emitter
|
||||
run: tools/ci.sh mpy_cross_debug_emitter
|
||||
run: source tools/ci.sh && ci_mpy_format_test
|
||||
|
||||
2
.github/workflows/ports.yml
vendored
2
.github/workflows/ports.yml
vendored
@@ -17,6 +17,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build ports download metadata
|
||||
run: mkdir boards && ./tools/autobuild/build-downloads.py . ./boards
|
||||
|
||||
33
.github/workflows/ports_alif.yml
vendored
33
.github/workflows/ports_alif.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: alif port
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'tools/**'
|
||||
- 'py/**'
|
||||
- 'extmod/**'
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/alif/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
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@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh alif_setup
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: tools/ci.sh ${{ matrix.ci_func }}
|
||||
6
.github/workflows/ports_cc3200.yml
vendored
6
.github/workflows/ports_cc3200.yml
vendored
@@ -21,8 +21,8 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh cc3200_setup
|
||||
run: source tools/ci.sh && ci_cc3200_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh cc3200_build
|
||||
run: source tools/ci.sh && ci_cc3200_build
|
||||
|
||||
20
.github/workflows/ports_esp32.yml
vendored
20
.github/workflows/ports_esp32.yml
vendored
@@ -12,10 +12,6 @@ on:
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/esp32/**'
|
||||
schedule:
|
||||
# Scheduled run exists to keep master branch ESP-IDF cache entry hot
|
||||
# and prevent creating many redundant per-branch cache entries instead.
|
||||
- cron: "20 0 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -29,19 +25,17 @@ jobs:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- esp32_build_cmod_spiram_s2
|
||||
- esp32_build_s3_c3
|
||||
- esp32_build_c2_c5_c6
|
||||
- esp32_build_p4
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- id: idf_ver
|
||||
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: Read the ESP-IDF version
|
||||
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cached ESP-IDF install
|
||||
id: cache_esp_idf
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./esp-idf/
|
||||
@@ -52,7 +46,7 @@ jobs:
|
||||
|
||||
- name: Install ESP-IDF packages
|
||||
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
|
||||
run: tools/ci.sh esp32_idf_setup
|
||||
run: source tools/ci.sh && ci_esp32_idf_setup
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
@@ -60,4 +54,4 @@ jobs:
|
||||
key: esp32-${{ matrix.ci_func }}
|
||||
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: tools/ci.sh ${{ matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
||||
|
||||
6
.github/workflows/ports_esp8266.yml
vendored
6
.github/workflows/ports_esp8266.yml
vendored
@@ -21,8 +21,8 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh esp8266_setup && tools/ci.sh esp8266_path >> $GITHUB_PATH
|
||||
run: source tools/ci.sh && ci_esp8266_setup && ci_esp8266_path >> $GITHUB_PATH
|
||||
- name: Build
|
||||
run: tools/ci.sh esp8266_build
|
||||
run: source tools/ci.sh && ci_esp8266_build
|
||||
|
||||
13
.github/workflows/ports_mimxrt.yml
vendored
13
.github/workflows/ports_mimxrt.yml
vendored
@@ -19,15 +19,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: 'micropython repo' # test build with space in path
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: 'micropython repo'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh mimxrt_setup
|
||||
run: source tools/ci.sh && ci_mimxrt_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh mimxrt_build
|
||||
run: source tools/ci.sh && ci_mimxrt_build
|
||||
|
||||
8
.github/workflows/ports_nrf.yml
vendored
8
.github/workflows/ports_nrf.yml
vendored
@@ -19,10 +19,10 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh nrf_setup
|
||||
run: source tools/ci.sh && ci_nrf_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh nrf_build
|
||||
run: source tools/ci.sh && ci_nrf_build
|
||||
|
||||
6
.github/workflows/ports_powerpc.yml
vendored
6
.github/workflows/ports_powerpc.yml
vendored
@@ -21,8 +21,8 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh powerpc_setup
|
||||
run: source tools/ci.sh && ci_powerpc_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh powerpc_build
|
||||
run: source tools/ci.sh && ci_powerpc_build
|
||||
|
||||
32
.github/workflows/ports_qemu-arm.yml
vendored
Normal file
32
.github/workflows/ports_qemu-arm.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: qemu-arm port
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/*.yml'
|
||||
- 'tools/**'
|
||||
- 'py/**'
|
||||
- 'extmod/**'
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'drivers/**'
|
||||
- 'ports/qemu-arm/**'
|
||||
- 'tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@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
|
||||
64
.github/workflows/ports_qemu.yml
vendored
64
.github/workflows/ports_qemu.yml
vendored
@@ -1,64 +0,0 @@
|
||||
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:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- bigendian
|
||||
- sabrelite
|
||||
- thumb_softfp
|
||||
- thumb_hardfp
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh qemu_setup_arm
|
||||
- name: Build and run test suite ci_qemu_build_arm_${{ matrix.ci_func }}
|
||||
run: tools/ci.sh qemu_build_arm_${{ matrix.ci_func }}
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
build_and_test_rv32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh qemu_setup_rv32
|
||||
- name: Build and run test suite
|
||||
run: tools/ci.sh qemu_build_rv32
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
build_and_test_rv64:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh qemu_setup_rv64
|
||||
- name: Build and run test suite
|
||||
run: tools/ci.sh qemu_build_rv64
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
8
.github/workflows/ports_renesas-ra.yml
vendored
8
.github/workflows/ports_renesas-ra.yml
vendored
@@ -19,11 +19,11 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build_renesas_ra_board:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh renesas_ra_setup
|
||||
run: source tools/ci.sh && ci_renesas_ra_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh renesas_ra_board_build
|
||||
run: source tools/ci.sh && ci_renesas_ra_board_build
|
||||
|
||||
|
||||
11
.github/workflows/ports_rp2.yml
vendored
11
.github/workflows/ports_rp2.yml
vendored
@@ -20,14 +20,9 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: 'micropython repo' # test build with space in path
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
path: 'micropython repo'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh rp2_setup
|
||||
run: source tools/ci.sh && ci_rp2_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh rp2_build
|
||||
run: source tools/ci.sh && ci_rp2_build
|
||||
|
||||
6
.github/workflows/ports_samd.yml
vendored
6
.github/workflows/ports_samd.yml
vendored
@@ -21,8 +21,8 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh samd_setup
|
||||
run: source tools/ci.sh && ci_samd_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh samd_build
|
||||
run: source tools/ci.sh && ci_samd_build
|
||||
|
||||
9
.github/workflows/ports_stm32.yml
vendored
9
.github/workflows/ports_stm32.yml
vendored
@@ -25,12 +25,11 @@ jobs:
|
||||
ci_func: # names are functions in ci.sh
|
||||
- stm32_pyb_build
|
||||
- stm32_nucleo_build
|
||||
- stm32_misc_build
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh stm32_setup && tools/ci.sh stm32_path >> $GITHUB_PATH
|
||||
run: source tools/ci.sh && ci_stm32_setup
|
||||
- name: Build ci_${{matrix.ci_func }}
|
||||
run: tools/ci.sh ${{ matrix.ci_func }}
|
||||
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
|
||||
|
||||
|
||||
252
.github/workflows/ports_unix.yml
vendored
252
.github/workflows/ports_unix.yml
vendored
@@ -23,11 +23,11 @@ jobs:
|
||||
minimal:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_minimal_build
|
||||
run: source tools/ci.sh && ci_unix_minimal_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_minimal_run_tests
|
||||
run: source tools/ci.sh && ci_unix_minimal_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
@@ -35,9 +35,9 @@ jobs:
|
||||
reproducible:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build with reproducible date
|
||||
run: tools/ci.sh unix_minimal_build
|
||||
run: source tools/ci.sh && ci_unix_minimal_build
|
||||
env:
|
||||
SOURCE_DATE_EPOCH: 1234567890
|
||||
- name: Check reproducible build date
|
||||
@@ -46,11 +46,11 @@ jobs:
|
||||
standard:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_standard_build
|
||||
run: source tools/ci.sh && ci_unix_standard_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_standard_run_tests
|
||||
run: source tools/ci.sh && ci_unix_standard_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
@@ -58,11 +58,11 @@ jobs:
|
||||
standard_v2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_standard_v2_build
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_standard_v2_run_tests
|
||||
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
@@ -70,80 +70,60 @@ jobs:
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
# 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'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_coverage_setup
|
||||
run: source tools/ci.sh && ci_unix_coverage_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_coverage_build
|
||||
run: source tools/ci.sh && ci_unix_coverage_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_coverage_run_tests
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_tests
|
||||
- name: Test merging .mpy files
|
||||
run: tools/ci.sh unix_coverage_run_mpy_merge_tests
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests
|
||||
- name: Build native mpy modules
|
||||
run: tools/ci.sh native_mpy_modules_build
|
||||
run: source tools/ci.sh && ci_native_mpy_modules_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: tools/ci.sh unix_coverage_run_native_mpy_tests
|
||||
run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests
|
||||
- name: Run gcov coverage analysis
|
||||
run: |
|
||||
(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@v5
|
||||
uses: codecov/codecov-action@v3
|
||||
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-22.04 # use 22.04 to get libffi-dev:i386
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_32bit_setup
|
||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_coverage_32bit_build
|
||||
run: source tools/ci.sh && ci_unix_coverage_32bit_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_coverage_32bit_run_tests
|
||||
run: source tools/ci.sh && ci_unix_coverage_32bit_run_tests
|
||||
- name: Build native mpy modules
|
||||
run: tools/ci.sh native_mpy_modules_32bit_build
|
||||
run: source tools/ci.sh && ci_native_mpy_modules_32bit_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: tools/ci.sh unix_coverage_32bit_run_native_mpy_tests
|
||||
run: source tools/ci.sh && ci_unix_coverage_32bit_run_native_mpy_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
nanbox:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get libffi-dev:i386
|
||||
runs-on: ubuntu-20.04 # use 20.04 to get python2, and libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_32bit_setup
|
||||
run: source tools/ci.sh && ci_unix_32bit_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_nanbox_build
|
||||
run: source tools/ci.sh && ci_unix_nanbox_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_nanbox_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
longlong:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_32bit_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_longlong_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_longlong_run_tests
|
||||
run: source tools/ci.sh && ci_unix_nanbox_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
@@ -151,51 +131,51 @@ jobs:
|
||||
float:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_float_build
|
||||
run: source tools/ci.sh && ci_unix_float_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_float_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
gil_enabled:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_gil_enabled_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_gil_enabled_run_tests
|
||||
run: source tools/ci.sh && ci_unix_float_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
stackless_clang:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_clang_setup
|
||||
run: source tools/ci.sh && ci_unix_clang_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_stackless_clang_build
|
||||
run: source tools/ci.sh && ci_unix_stackless_clang_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_stackless_clang_run_tests
|
||||
run: source tools/ci.sh && ci_unix_stackless_clang_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
float_clang:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: source tools/ci.sh && ci_unix_clang_setup
|
||||
- name: Build
|
||||
run: source tools/ci.sh && ci_unix_float_clang_build
|
||||
- name: Run main test suite
|
||||
run: source tools/ci.sh && ci_unix_float_clang_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
settrace:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_clang_setup
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_float_clang_build
|
||||
run: source tools/ci.sh && ci_unix_settrace_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_float_clang_run_tests
|
||||
run: source tools/ci.sh && ci_unix_settrace_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
@@ -203,140 +183,54 @@ jobs:
|
||||
settrace_stackless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
# 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'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_settrace_stackless_build
|
||||
run: source tools/ci.sh && ci_unix_settrace_stackless_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_settrace_stackless_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
repr_b:
|
||||
runs-on: ubuntu-22.04 # use 22.04 to get libffi-dev:i386
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_32bit_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_repr_b_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_repr_b_run_tests
|
||||
run: source tools/ci.sh && ci_unix_settrace_stackless_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
macos:
|
||||
runs-on: macos-26
|
||||
runs-on: macos-11.0
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.8'
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_macos_build
|
||||
run: source tools/ci.sh && ci_unix_macos_build
|
||||
- name: Run tests
|
||||
run: tools/ci.sh unix_macos_run_tests
|
||||
run: source tools/ci.sh && ci_unix_macos_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
qemu_mips:
|
||||
# ubuntu-22.04 is needed for older libffi.
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_qemu_mips_setup
|
||||
run: source tools/ci.sh && ci_unix_qemu_mips_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_qemu_mips_build
|
||||
run: source tools/ci.sh && ci_unix_qemu_mips_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_qemu_mips_run_tests
|
||||
run: source tools/ci.sh && ci_unix_qemu_mips_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
qemu_arm:
|
||||
# ubuntu-22.04 is needed for older libffi.
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_qemu_arm_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_qemu_arm_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_qemu_arm_run_tests
|
||||
- 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@v6
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_qemu_riscv64_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_qemu_riscv64_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_qemu_riscv64_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
sanitize_address:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
# 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'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh unix_coverage_setup
|
||||
run: source tools/ci.sh && ci_unix_qemu_arm_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_sanitize_address_build
|
||||
run: source tools/ci.sh && ci_unix_qemu_arm_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_sanitize_address_run_tests
|
||||
- name: Test merging .mpy files
|
||||
run: tools/ci.sh unix_coverage_run_mpy_merge_tests
|
||||
- name: Build native mpy modules
|
||||
run: tools/ci.sh native_mpy_modules_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: tools/ci.sh unix_coverage_run_native_mpy_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
sanitize_undefined:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
# 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: Install packages
|
||||
run: tools/ci.sh unix_coverage_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh unix_sanitize_undefined_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh unix_sanitize_undefined_run_tests
|
||||
- name: Test merging .mpy files
|
||||
run: tools/ci.sh unix_coverage_run_mpy_merge_tests
|
||||
- name: Build native mpy modules
|
||||
run: tools/ci.sh native_mpy_modules_build
|
||||
- name: Test importing .mpy generated by mpy_ld.py
|
||||
run: tools/ci.sh unix_coverage_run_native_mpy_tests
|
||||
run: source tools/ci.sh && ci_unix_qemu_arm_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
9
.github/workflows/ports_webassembly.yml
vendored
9
.github/workflows/ports_webassembly.yml
vendored
@@ -11,7 +11,6 @@ on:
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'ports/webassembly/**'
|
||||
- 'tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -21,13 +20,13 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh webassembly_setup
|
||||
run: source tools/ci.sh && ci_webassembly_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh webassembly_build
|
||||
run: source tools/ci.sh && ci_webassembly_build
|
||||
- name: Run tests
|
||||
run: tools/ci.sh webassembly_run_tests
|
||||
run: source tools/ci.sh && ci_webassembly_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
||||
131
.github/workflows/ports_windows.yml
vendored
131
.github/workflows/ports_windows.yml
vendored
@@ -18,134 +18,11 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-vs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [x86, x64]
|
||||
configuration: [Debug, Release]
|
||||
variant: [dev, standard]
|
||||
visualstudio: ['2017', '2019', '2022']
|
||||
include:
|
||||
- visualstudio: '2017'
|
||||
vs_version: '[15, 16)'
|
||||
custom_vs_install: true
|
||||
- visualstudio: '2019'
|
||||
vs_version: '[16, 17)'
|
||||
custom_vs_install: true
|
||||
- visualstudio: '2022'
|
||||
vs_version: '[17, 18)'
|
||||
# trim down the number of jobs in the matrix
|
||||
exclude:
|
||||
- variant: standard
|
||||
configuration: Debug
|
||||
- visualstudio: '2019'
|
||||
configuration: Debug
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CI_BUILD_CONFIGURATION: ${{ matrix.configuration }}
|
||||
steps:
|
||||
- name: Install Visual Studio ${{ matrix.visualstudio }}
|
||||
if: matrix.custom_vs_install
|
||||
shell: bash
|
||||
# Shell functions in this block are to retry intermittent corrupt
|
||||
# downloads (with a clean download dir) before failing the job outright
|
||||
run: |
|
||||
try () { ($@) || ($@) || ($@) || ($@) }
|
||||
clean_install () ( rm -rf $TEMP/chocolatey; choco install $1 )
|
||||
try clean_install visualstudio${{ matrix.visualstudio }}buildtools
|
||||
try clean_install visualstudio${{ matrix.visualstudio }}-workload-vctools
|
||||
try clean_install windows-sdk-8.1
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
vs-version: ${{ matrix.vs_version }}
|
||||
- uses: actions/checkout@v6
|
||||
- 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-latest
|
||||
env:
|
||||
CHERE_INVOKING: enabled_from_arguments
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/setup-python@v6
|
||||
# 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@v6
|
||||
- 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:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh windows_setup
|
||||
run: source tools/ci.sh && ci_windows_setup
|
||||
- name: Build
|
||||
run: tools/ci.sh windows_build
|
||||
run: source tools/ci.sh && ci_windows_build
|
||||
|
||||
47
.github/workflows/ports_zephyr.yml
vendored
47
.github/workflows/ports_zephyr.yml
vendored
@@ -11,11 +11,6 @@ on:
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'ports/zephyr/**'
|
||||
- 'tests/**'
|
||||
schedule:
|
||||
# Scheduled run exists to keep master branch Zephyr cache entry hot
|
||||
# and prevent creating many redundant per-branch cache entries instead.
|
||||
- cron: "40 4 * * *"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -25,44 +20,10 @@ 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 would save 9.6GiB, but takes about 13m)
|
||||
# (large-packages would save 4.6GiB, but takes about 3m)
|
||||
android: false
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
tool-cache: true
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v6
|
||||
- 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
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: tools/ci.sh zephyr_setup
|
||||
run: source tools/ci.sh && ci_zephyr_setup
|
||||
- name: Install Zephyr
|
||||
if: steps.cache_workspace.outputs.cache-hit != 'true'
|
||||
run: tools/ci.sh zephyr_install
|
||||
run: source tools/ci.sh && ci_zephyr_install
|
||||
- name: Build
|
||||
run: tools/ci.sh zephyr_build
|
||||
- name: Run main test suite
|
||||
run: tools/ci.sh zephyr_run_tests
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
run: source tools/ci.sh && ci_zephyr_build
|
||||
|
||||
8
.github/workflows/ruff.yml
vendored
8
.github/workflows/ruff.yml
vendored
@@ -1,13 +1,11 @@
|
||||
# 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@v6
|
||||
# ruff version should be kept in sync with .pre-commit-config.yaml & also micropython-lib
|
||||
- run: pipx install ruff==0.11.6
|
||||
- uses: actions/checkout@v4
|
||||
- run: pip install --user ruff==0.1.3
|
||||
- run: ruff check --output-format=github .
|
||||
- run: ruff format --diff .
|
||||
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -11,9 +11,8 @@ build/
|
||||
build-*/
|
||||
docs/genrst/
|
||||
|
||||
# Test failure outputs and intermediate artefacts
|
||||
# Test failure outputs
|
||||
tests/results/*
|
||||
tests/ports/unix/ffi_lib.so
|
||||
|
||||
# Python cache files
|
||||
__pycache__/
|
||||
@@ -24,11 +23,3 @@ user.props
|
||||
|
||||
# MacOS desktop metadata files
|
||||
.DS_Store
|
||||
|
||||
# Created by ci.sh zephyr targets
|
||||
/.ccache
|
||||
/zephyrproject
|
||||
|
||||
# Created by ci.sh esp8266 targets
|
||||
/xtensa-lx106-elf-standalone.tar.gz
|
||||
/xtensa-lx106-elf/
|
||||
|
||||
21
.gitmodules
vendored
21
.gitmodules
vendored
@@ -3,13 +3,13 @@
|
||||
url = https://github.com/micropython/axtls.git
|
||||
[submodule "lib/libffi"]
|
||||
path = lib/libffi
|
||||
url = https://github.com/libffi/libffi
|
||||
url = https://github.com/atgreen/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/micropython/berkeley-db-1.xx
|
||||
url = https://github.com/pfalcon/berkeley-db-1.xx
|
||||
[submodule "lib/stm32lib"]
|
||||
path = lib/stm32lib
|
||||
url = https://github.com/micropython/stm32lib
|
||||
@@ -35,7 +35,7 @@
|
||||
url = https://github.com/bluekitchen/btstack.git
|
||||
[submodule "lib/nxp_driver"]
|
||||
path = lib/nxp_driver
|
||||
url = https://github.com/micropython/nxp_driver.git
|
||||
url = https://github.com/hathach/nxp_driver.git
|
||||
[submodule "lib/libhydrogen"]
|
||||
path = lib/libhydrogen
|
||||
url = https://github.com/jedisct1/libhydrogen.git
|
||||
@@ -59,18 +59,3 @@
|
||||
[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
|
||||
|
||||
@@ -12,16 +12,7 @@ repos:
|
||||
verbose: true
|
||||
stages: [commit-msg]
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Version should be kept in sync with .github/workflows/ruff.yml & also micropython-lib
|
||||
rev: v0.11.6
|
||||
rev: v0.1.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
# Version should be kept in sync with .github/workflows/codespell.yml
|
||||
rev: v2.4.1
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: Spellcheck for changed files (codespell)
|
||||
additional_dependencies:
|
||||
- tomli
|
||||
|
||||
@@ -104,22 +104,6 @@ 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
|
||||
==========================
|
||||
|
||||
@@ -206,21 +190,14 @@ 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.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
@@ -228,43 +205,18 @@ major changes should follow the conventions described here.
|
||||
- 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.
|
||||
|
||||
### 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:
|
||||
|
||||
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
|
||||
@@ -273,13 +225,11 @@ correctly-sized (and signed) integer types. The 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.
|
||||
|
||||
|
||||
6
LICENSE
6
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2025 Damien P. George
|
||||
Copyright (c) 2013-2023 Damien P. George
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -48,17 +48,16 @@ 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)
|
||||
@@ -72,7 +71,6 @@ used during the build process and is not part of the compiled source code.
|
||||
/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)
|
||||
|
||||
99
README.md
99
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. Some ports have support for
|
||||
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
|
||||
`_thread` module (multithreading), `socket` and `ssl` for networking, and
|
||||
`asyncio`. Note that only a subset of Python 3 functionality is implemented
|
||||
for the data types and modules.
|
||||
@@ -35,8 +35,8 @@ DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
See the [online documentation](https://docs.micropython.org/) for the API
|
||||
reference and information about using MicroPython and information about how
|
||||
See the [online documentation](https://docs.micropython.org/) for API
|
||||
references and information about using MicroPython and information about how
|
||||
it is implemented.
|
||||
|
||||
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
|
||||
@@ -80,8 +80,9 @@ This repository contains the following components:
|
||||
- [examples/](examples/) -- a few example Python scripts.
|
||||
|
||||
"make" is used to build the components, or "gmake" on BSD-based systems.
|
||||
You will also need bash, gcc, and Python 3.3+ available as the command `python3`.
|
||||
Some ports (rp2 and esp32) additionally use CMake.
|
||||
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
|
||||
(if your system only has Python 2.7 then invoke make with the additional option
|
||||
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
|
||||
|
||||
Supported platforms & architectures
|
||||
-----------------------------------
|
||||
@@ -98,74 +99,28 @@ development and testing of MicroPython itself, as well as providing
|
||||
lightweight alternative to CPython on these platforms (in particular on
|
||||
embedded Linux systems).
|
||||
|
||||
Over twenty different MicroPython ports are provided in this repository,
|
||||
split across three
|
||||
[MicroPython Support Tiers](https://docs.micropython.org/en/latest/develop/support_tiers.html).
|
||||
The ["minimal"](ports/minimal) port provides an example of a very basic
|
||||
MicroPython port and can be compiled as both a standalone Linux binary as
|
||||
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
|
||||
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
|
||||
is an example of the absolute minimum configuration, and is used to keep
|
||||
track of the code size of the core runtime and VM.
|
||||
|
||||
Tier 1 Ports
|
||||
============
|
||||
|
||||
👑 Ports in [Tier 1](https://docs.micropython.org/en/latest/develop/support_tiers.html)
|
||||
are mature and have the most active development, support and testing:
|
||||
|
||||
| Port | Target | Quick Reference |
|
||||
|--------------------------|----------------------------------------------------------------------------------------|----------------------------------------------------------------------|
|
||||
| [esp32](ports/esp32)* | Espressif ESP32 SoCs (ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C6) | [here](https://docs.micropython.org/en/latest/esp32/quickref.html) |
|
||||
| [mimxrt](ports/mimxrt) | NXP m.iMX RT | [here](https://docs.micropython.org/en/latest/mimxrt/quickref.html) |
|
||||
| [rp2](ports/rp2) | Raspberry Pi RP2040 and RP2350 | [here](https://docs.micropython.org/en/latest/rp2/quickref.html) |
|
||||
| [samd](ports/samd) | Microchip (formerly Atmel) SAMD21 and SAMD51 | [here](https://docs.micropython.org/en/latest/samd/quickref.html) |
|
||||
| [stm32](ports/stm32) | STMicroelectronics STM32 MCUs (F0, F4, F7, G0, G4, H5, H7, L0, L1, L4, N6, WB, WL) | [here](https://docs.micropython.org/en/latest/pyboard/quickref.html) |
|
||||
| [unix](ports/unix) | Linux, BSD, macOS, WSL | [here](https://docs.micropython.org/en/latest/unix/quickref.html) |
|
||||
| [windows](ports/windows) | Microsoft Windows | [here](https://docs.micropython.org/en/latest/unix/quickref.html) |
|
||||
|
||||
An asterisk indicates that the port has ongoing financial support from the vendor.
|
||||
|
||||
Tier 2 Ports
|
||||
============
|
||||
|
||||
✔ Ports in [Tier 2](https://docs.micropython.org/en/latest/develop/support_tiers.html)
|
||||
are less mature and less actively developed and tested than Tier 1, but
|
||||
still fully supported:
|
||||
|
||||
| Port | Target | Quick Reference |
|
||||
|----------------------------------|-------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| [alif](ports/alif) | Alif Semiconductor Ensemble MCUs (E3, E7) | |
|
||||
| [embed](ports/embed) | Generates a set of .c/.h files for embedding into a project | |
|
||||
| [nrf](ports/nrf) | Nordic Semiconductor nRF51 and nRF52 | |
|
||||
| [renesas-ra](ports/renesas-ra) | Renesas RA family | [here](https://docs.micropython.org/en/latest/renesas-ra/quickref.html) |
|
||||
| [webassembly](ports/webassembly) | Emscripten port targeting browsers and NodeJS | |
|
||||
| [zephyr](ports/zephyr) | Zephyr RTOS | [here](https://docs.micropython.org/en/latest/zephyr/quickref.html) |
|
||||
|
||||
Tier 3 Ports
|
||||
============
|
||||
|
||||
Ports in [Tier 3](https://docs.micropython.org/en/latest/develop/support_tiers.html)
|
||||
are built in CI but not regularly tested by the MicroPython maintainers:
|
||||
|
||||
| Port | Target | Quick Reference |
|
||||
|----------------------------|-------------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| [cc3200](ports/cc3200) | Texas Instruments CC3200 | [For WiPy](https://docs.micropython.org/en/latest/wipy/quickref.html) |
|
||||
| [esp8266](ports/esp8266) | Espressif ESP8266 SoC | [here](https://docs.micropython.org/en/latest/esp8266/quickref.html) |
|
||||
| [pic16bit](ports/pic16bit) | Microchip PIC 16-bit | |
|
||||
| [powerpc](ports/powerpc) | IBM PowerPC (including Microwatt) | |
|
||||
|
||||
Additional Ports
|
||||
================
|
||||
|
||||
In addition to the above there is a Tier M containing ports that are used
|
||||
primarily for maintenance, development and testing:
|
||||
|
||||
- The ["bare-arm"](ports/bare-arm) port is an example of the absolute minimum
|
||||
configuration that still includes the compiler, and is used to keep track
|
||||
of the code size of the core runtime and VM.
|
||||
|
||||
- The ["minimal"](ports/minimal) port provides an example of a very basic
|
||||
MicroPython port and can be compiled as both a standalone Linux binary as
|
||||
well as for ARM Cortex-M4. Start with this if you want to port MicroPython
|
||||
to another microcontroller.
|
||||
|
||||
- The [qemu](ports/qemu) port is a QEMU-based emulated target for Cortex-A,
|
||||
Cortex-M, RISC-V 32-bit and RISC-V 64-bit architectures.
|
||||
In addition, the following ports are provided in this repository:
|
||||
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
|
||||
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
|
||||
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
|
||||
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
|
||||
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
|
||||
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
|
||||
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
|
||||
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
|
||||
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
|
||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
|
||||
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
|
||||
- [zephyr](ports/zephyr) -- Zephyr RTOS.
|
||||
|
||||
The MicroPython cross-compiler, mpy-cross
|
||||
-----------------------------------------
|
||||
|
||||
@@ -13,7 +13,8 @@ Building the documentation locally
|
||||
If you're making changes to the documentation, you may want to build the
|
||||
documentation locally so that you can preview your changes.
|
||||
|
||||
Install Sphinx and sphinx_rtd_theme, preferably in a virtualenv:
|
||||
Install Sphinx, and optionally (for the RTD-styling), sphinx_rtd_theme,
|
||||
preferably in a virtualenv:
|
||||
|
||||
pip install sphinx
|
||||
pip install sphinx_rtd_theme
|
||||
@@ -24,21 +25,6 @@ In `micropython/docs`, build the docs:
|
||||
|
||||
You'll find the index page at `micropython/docs/build/html/index.html`.
|
||||
|
||||
Documentation autobuild
|
||||
-----------------------
|
||||
|
||||
For a more convenient development experience, you can use `sphinx-autobuild`
|
||||
to automatically rebuild and serve the documentation when you make changes:
|
||||
|
||||
pip install sphinx-autobuild
|
||||
|
||||
Then run from the `micropython/docs` directory:
|
||||
|
||||
sphinx-autobuild . build/html
|
||||
|
||||
This will start a local web server (typically at `http://127.0.0.1:8000`)
|
||||
and automatically rebuild the documentation whenever you save changes to the source files.
|
||||
|
||||
Having readthedocs.org build the documentation
|
||||
----------------------------------------------
|
||||
|
||||
|
||||
27
docs/conf.py
27
docs/conf.py
@@ -36,9 +36,6 @@ html_context = {
|
||||
"is_release": micropy_version != "latest",
|
||||
}
|
||||
|
||||
# Authors used in various parts of the documentation.
|
||||
micropy_authors = "MicroPython authors and contributors"
|
||||
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
@@ -55,7 +52,6 @@ extensions = [
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinxcontrib.jquery",
|
||||
"sphinx_rtd_theme",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@@ -72,7 +68,7 @@ master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = "MicroPython"
|
||||
copyright = "- The MicroPython Documentation is Copyright © 2014-2025, " + micropy_authors
|
||||
copyright = "- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -129,9 +125,20 @@ rst_epilog = """
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
import sphinx_rtd_theme
|
||||
# on_rtd is whether we are on readthedocs.org
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
||||
except:
|
||||
html_theme = "default"
|
||||
html_theme_path = ["."]
|
||||
else:
|
||||
html_theme_path = ["."]
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -237,7 +244,7 @@ latex_documents = [
|
||||
master_doc,
|
||||
"MicroPython.tex",
|
||||
"MicroPython Documentation",
|
||||
micropy_authors,
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
@@ -274,7 +281,7 @@ man_pages = [
|
||||
"index",
|
||||
"micropython",
|
||||
"MicroPython Documentation",
|
||||
[micropy_authors],
|
||||
["Damien P. George, Paul Sokolovsky, and contributors"],
|
||||
1,
|
||||
),
|
||||
]
|
||||
@@ -293,7 +300,7 @@ texinfo_documents = [
|
||||
master_doc,
|
||||
"MicroPython",
|
||||
"MicroPython Documentation",
|
||||
micropy_authors,
|
||||
"Damien P. George, Paul Sokolovsky, and contributors",
|
||||
"MicroPython",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
|
||||
@@ -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. If you want to include assembly files use ``SRC_USERMOD_LIB_ASM``.
|
||||
source files.
|
||||
|
||||
If you have custom compiler options (like ``-I`` to add directories to search
|
||||
for header files), these should be added to ``CFLAGS_USERMOD`` for C code
|
||||
|
||||
@@ -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_proto_fun(cm.rc, cm.context, NULL);
|
||||
return mp_make_function_from_raw_code(cm.rc, cm.context, NULL);
|
||||
}
|
||||
|
||||
The compiler compiles the code in four passes: scope, stack size, code size and emit.
|
||||
@@ -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) {
|
||||
|
||||
@@ -106,13 +106,13 @@ See the `ARM GCC
|
||||
toolchain <https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads>`_
|
||||
for the latest details.
|
||||
|
||||
Python 3 is also required.
|
||||
Python is also required. Python 2 is supported for now, but we recommend using Python 3.
|
||||
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,86 +278,10 @@ To run a selection of tests on a board/device connected over USB use:
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd tests
|
||||
$ ./run-tests.py -t /dev/ttyACM0
|
||||
$ ./run-tests.py --target minimal --device /dev/ttyACM0
|
||||
|
||||
See also :ref:`writingtests`.
|
||||
|
||||
Additional make targets for developers
|
||||
--------------------------------------
|
||||
|
||||
In all ``make``-based ports, there is a target to print the size of a specific object file.
|
||||
When a change is confined to a single file, this is useful when testing variations to find smaller alternatives.
|
||||
|
||||
For instance, to print the size of ``objstr.o`` in the ``py/`` directory when making a unix standard build:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make build-standard/py/objstr.sz
|
||||
|
||||
Similarly, there is a target to save the preprocessed version of a file:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make build-standard/py/objstr.pp
|
||||
|
||||
In ``ports/unix`` there are additional targets related to running tests:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make test//int # Run all tests matching the pattern "int"
|
||||
$ make test/ports/unix # Run all tests in ports/unix
|
||||
$ make test-failures # Re-run only the failed tests
|
||||
$ make print-failures # print the differences for failed tests
|
||||
$ make clean-failures # delete the .exp and .out files from failed tests
|
||||
|
||||
Using ci.sh locally
|
||||
-------------------
|
||||
|
||||
MicroPython uses GitHub Actions for continuous integration.
|
||||
To reduce dependence on any specific CI system, the actual build steps for Unix-based builds are in the file ``tools/ci.sh``.
|
||||
This can also be used as a script on developer desktops, with caveats:
|
||||
|
||||
* For most steps, An Ubuntu/Debian system similar to the one used during CI is assumed.
|
||||
* Some specific steps assume specific Ubuntu versions.
|
||||
* The setup steps may invoke the system package manager to install packages,
|
||||
download and install software from the internet, etc.
|
||||
|
||||
To get a usage message including the list of commands, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tools/ci.sh --help
|
||||
|
||||
As an example, you can build and test the unix minimal port with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ tools/ci.sh unix_minimal_build unix_minimal_run_tests
|
||||
|
||||
If you use the bash shell, you can add a ``ci`` command with tab completion:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ eval $(tools/ci.sh --bash-completion)
|
||||
|
||||
For the zsh shell, replace ``--bash-completion`` with ``--zsh-completion``.
|
||||
For the fish shell, replace ``--bash-completion`` with ``--fish-completion``.
|
||||
|
||||
Then, typing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ci unix_cov<tab>
|
||||
|
||||
This will complete the ci step name to ``unix_coverage_``.
|
||||
Pressing tab a second time will show the list of matching steps:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ci unix_coverage_<tab>
|
||||
unix_coverage_32bit_build
|
||||
unix_coverage_32bit_run_native_mpy_tests…
|
||||
|
||||
Folder structure
|
||||
----------------
|
||||
|
||||
|
||||
@@ -24,4 +24,3 @@ MicroPython to a new platform and implementing a core MicroPython library.
|
||||
publiccapi.rst
|
||||
extendingmicropython.rst
|
||||
porting.rst
|
||||
support_tiers.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 },
|
||||
|
||||
@@ -39,8 +39,7 @@ 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, ESP32S3)
|
||||
* ``rv32imc`` (RISC-V 32 bits with compressed instructions, eg ESP32C3, ESP32C6)
|
||||
* ``xtensawin`` (windowed with window size 8, eg ESP32)
|
||||
|
||||
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
|
||||
@@ -67,31 +66,14 @@ The known limitations are:
|
||||
|
||||
* static BSS variables are not supported; workaround: use global BSS variables
|
||||
|
||||
* thread-local storage variables are not supported on rv32imc; workaround: use
|
||||
global BSS variables or allocate some space on the heap to store them
|
||||
|
||||
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
|
||||
build time. It is thus not possible to simply call some arbitrary HAL/OS/RTOS/system
|
||||
function, for example, unless that resides at a fixed address. In that case, the path
|
||||
of a linkerscript containing a series of symbol names and their fixed address can be
|
||||
passed to ``mpy_ld.py`` via the ``--externs`` command line argument. That way symbols
|
||||
appearing in the linkerscript will take precedence over what is provided from object
|
||||
files, but at the moment the object files' implementation will still reside in the
|
||||
final MPY file. The linkerscript parser is limited in its capabilities, and is
|
||||
currently used only for parsing the ESP8266 port ROM symbols list (see
|
||||
``ports/esp8266/boards/eagle.rom.addr.v6.ld``).
|
||||
function, for example.
|
||||
|
||||
New symbols can be added to the end of the table and the firmware rebuilt.
|
||||
The symbols also need to be added to ``tools/mpy_ld.py``'s ``fun_table`` dict in the
|
||||
@@ -146,7 +128,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;
|
||||
}
|
||||
@@ -154,7 +136,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
|
||||
@@ -163,7 +145,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) {
|
||||
@@ -190,7 +172,7 @@ The file ``Makefile`` contains:
|
||||
# Source files (.c or .py)
|
||||
SRC = factorial.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin, rv32imc)
|
||||
# Architecture to build for (x86, x64, armv6m, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
# Include to get the rules for compiling and linking the module
|
||||
@@ -228,26 +210,6 @@ other module, for example::
|
||||
print(factorial.factorial(10))
|
||||
# should display 3628800
|
||||
|
||||
Using Picolibc when building modules
|
||||
------------------------------------
|
||||
|
||||
Using `Picolibc <https://github.com/picolibc/picolibc>`_ as your C standard
|
||||
library is not only supported, but in fact it is the default for the rv32imc
|
||||
platform. However, there are a couple of things worth mentioning to make sure
|
||||
you don't run into problems later when building code.
|
||||
|
||||
Some pre-built Picolibc versions (for example, those provided by Ubuntu Linux
|
||||
as the ``picolibc-arm-none-eabi``, ``picolibc-riscv64-unknown-elf``, and
|
||||
``picolibc-xtensa-lx106-elf`` packages) assume thread-local storage (TLS) is
|
||||
available at runtime, but unfortunately MicroPython modules do not support that
|
||||
on some architectures (namely ``rv32imc``). This means that some
|
||||
functionalities provided by Picolibc will default to use TLS, returning an
|
||||
error either during compilation or during linking.
|
||||
|
||||
For an example on how this may affect you, the ``examples/natmod/btree``
|
||||
example module contains a workaround to make sure ``errno`` works (look for
|
||||
``__PICOLIBC_ERRNO_FUNCTION`` in the Makefile and follow the trail from there).
|
||||
|
||||
Further examples
|
||||
----------------
|
||||
|
||||
|
||||
@@ -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 stored on the Python value stack, which may
|
||||
Local variables on the other hand are 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.
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
|
||||
#include "py/compile.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/stackctrl.h"
|
||||
#include "shared/runtime/gchelper.h"
|
||||
#include "shared/runtime/pyexec.h"
|
||||
|
||||
@@ -50,7 +51,7 @@ The basic MicroPython firmware is implemented in the main port file, e.g ``main.
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Initialise the MicroPython runtime.
|
||||
mp_cstack_init_with_sp_here(2048);
|
||||
mp_stack_ctrl_init();
|
||||
gc_init(heap, heap + sizeof(heap));
|
||||
mp_init();
|
||||
|
||||
@@ -82,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(qstr filename) {
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
|
||||
@@ -161,6 +162,8 @@ The following is an example of an ``mpconfigport.h`` file:
|
||||
|
||||
// Type definitions for the specific machine.
|
||||
|
||||
typedef intptr_t mp_int_t; // must be pointer size
|
||||
typedef uintptr_t mp_uint_t; // must be pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
// We need to provide a declaration/definition of alloca().
|
||||
@@ -259,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 },
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
MicroPython Support Tiers
|
||||
=========================
|
||||
|
||||
MicroPython operates with a set of Support Tier levels for the various ports.
|
||||
Tiers 1, 2 and 3 are the main Tier levels with Tier 1 being the most mature and
|
||||
actively maintained. There is also Tier M for additional ports used primarily
|
||||
for maintenance, development and testing. These Tier levels are defined in the
|
||||
table below.
|
||||
|
||||
.. table::
|
||||
:widths: 40 9 9 9 9
|
||||
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| | Tier 1 | Tier 2 | Tier 3 | Tier M |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| builds pass under CI | ✔ | ✔ | ✔ | ✔ |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| tests run under CI (where possible) | ✔ | ✔ | ✔ | ✔ |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| actively maintained | ✔ | ✔ | | ✔ |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| stable Python API | ✔ | ✔ | | |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| new features actively developed | ✔ | ✔ | | |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| tested on hardware for releases | ✔ | ✔ | | |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| prioritized bug reports | ✔ | | | ✔ |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| regressions warrant a patch release | ✔ | | | ✔ |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
| has port-specific documentation | ✔ | | | |
|
||||
+-----------------------------------------------+--------+--------+--------+--------+
|
||||
|
||||
Lower Tiers may tick more boxes, but the above table defines the minimum requirements
|
||||
for a port to belong to a Tier.
|
||||
|
||||
Tier 1 ports:
|
||||
|
||||
- esp32
|
||||
- mimxrt
|
||||
- rp2
|
||||
- samd
|
||||
- stm32
|
||||
- unix
|
||||
- windows
|
||||
|
||||
Tier 2 ports:
|
||||
|
||||
- alif
|
||||
- embed
|
||||
- nrf
|
||||
- renesas-ra
|
||||
- webassembly
|
||||
- zephyr
|
||||
|
||||
Tier 3 ports:
|
||||
|
||||
- cc3200
|
||||
- esp8266
|
||||
- pic16bit
|
||||
- powerpc
|
||||
|
||||
Tier M ports:
|
||||
|
||||
- bare-arm
|
||||
- minimal
|
||||
- qemu
|
||||
@@ -60,7 +60,7 @@ Then to run on a board:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./run-tests.py -t /dev/ttyACM0
|
||||
$ ./run-tests.py --target minimal --device /dev/ttyACM0
|
||||
|
||||
And to run only a certain set of tests (eg a directory):
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
.. 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 <https://peps.python.org/pep-0570/>`_.
|
||||
|
||||
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<socket.socket>` 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)
|
||||
@@ -25,8 +25,7 @@ Python 3.6 beta 1 was released on 12 Sep 2016, and a summary of the new features
|
||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
||||
| `PEP 468 <https://www.python.org/dev/peps/pep-0468/>`_ | Preserving the order of *kwargs* in a function | |
|
||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
||||
| `PEP 487 <https://www.python.org/dev/peps/pep-0487/>`_ | Simpler customization of class creation | Partial |
|
||||
| | | [#setname]_ |
|
||||
| `PEP 487 <https://www.python.org/dev/peps/pep-0487/>`_ | Simpler customization of class creation | |
|
||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
||||
| `PEP 520 <https://www.python.org/dev/peps/pep-0520/>`_ | Preserving Class Attribute Definition Order | |
|
||||
+--------------------------------------------------------+--------------------------------------------------+-----------------+
|
||||
@@ -199,7 +198,3 @@ Changes to built-in modules:
|
||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
||||
| The *compress()* and *decompress()* functions now accept keyword arguments | |
|
||||
+--------------------------------------------------------------------------------------------------------------+----------------+
|
||||
|
||||
.. rubric:: Notes
|
||||
|
||||
.. [#setname] Currently, only :func:`__set_name__` is implemented.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -18,9 +18,6 @@ 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
|
||||
----------------------
|
||||
|
||||
@@ -61,53 +58,47 @@ 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, not on ESP32C3/C6
|
||||
esp32.ULP() # access to the Ultra-Low-Power Co-processor
|
||||
|
||||
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 :class:`network.WLAN` class in the :mod:`network` module::
|
||||
The :mod:`network` module::
|
||||
|
||||
import network
|
||||
|
||||
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 = 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.connect('ssid', 'key') # connect to an AP
|
||||
wlan.config('mac') # get the interface's MAC address
|
||||
wlan.ipconfig('addr4') # get the interface's IPv4 addresses
|
||||
wlan.config('mac') # get the interface's MAC address
|
||||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
A useful function for connecting to your local WiFi network is::
|
||||
|
||||
def do_connect():
|
||||
import machine, network
|
||||
wlan = network.WLAN()
|
||||
import network
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
if not wlan.isconnected():
|
||||
print('connecting to network...')
|
||||
wlan.connect('ssid', 'key')
|
||||
while not wlan.isconnected():
|
||||
machine.idle()
|
||||
print('network config:', wlan.ipconfig('addr4'))
|
||||
pass
|
||||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the :mod:`socket <socket>` module can be used
|
||||
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
|
||||
@@ -121,56 +112,31 @@ 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
|
||||
^^^
|
||||
|
||||
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::
|
||||
To use the wired interfaces one has to specify the pins and mode ::
|
||||
|
||||
import network
|
||||
|
||||
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
|
||||
lan.active(True) # activate the interface
|
||||
lan.ipconfig('addr4') # get the interface's IPv4 addresses
|
||||
lan.ifconfig() # get the interface's IP/netmask/gw/DNS 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_GENERIC``,
|
||||
``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=<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.
|
||||
|
||||
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::
|
||||
These are working configurations for LAN interfaces of popular boards::
|
||||
|
||||
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
|
||||
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
|
||||
@@ -195,66 +161,6 @@ These are working configurations for LAN interfaces of some popular ESP32 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
|
||||
<network.WIZNET5K>`.
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
@@ -271,10 +177,8 @@ Use the :mod:`time <time>` module::
|
||||
Timers
|
||||
------
|
||||
|
||||
The ESP32 port has one, two or four hardware timers, depending on the ESP32 device type.
|
||||
There is 1 timer for ESP32C2, 2 timers for ESP32C4, ESP32C6 and ESP32H4, and
|
||||
4 timers otherwise. Use the :ref:`machine.Timer <machine.Timer>` class
|
||||
with a timer ID of 0, 0 and 1, or from 0 to 3 (inclusive)::
|
||||
The ESP32 port has four hardware timers. Use the :ref:`machine.Timer <machine.Timer>` class
|
||||
with a timer ID from 0 to 3 (inclusive)::
|
||||
|
||||
from machine import Timer
|
||||
|
||||
@@ -284,12 +188,7 @@ with a timer ID of 0, 0 and 1, or from 0 to 3 (inclusive)::
|
||||
tim1 = Timer(1)
|
||||
tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(1))
|
||||
|
||||
The period is in milliseconds. When using UART.IRQ_RXIDLE, timer 0 is needed for
|
||||
the IRQ_RXIDLE mechanism and must not be used otherwise.
|
||||
|
||||
Timer callbacks are scheduled as soft interrupts on this port; hard
|
||||
callbacks are not implemented. Specifying ``hard=True`` will raise
|
||||
a ValueError.
|
||||
The period is in milliseconds.
|
||||
|
||||
Virtual timers are not currently supported on this port.
|
||||
|
||||
@@ -391,7 +290,7 @@ for more details.
|
||||
|
||||
Use the :ref:`machine.PWM <machine.PWM>` class::
|
||||
|
||||
from machine import Pin, PWM, lightsleep
|
||||
from machine import Pin, PWM
|
||||
|
||||
pwm0 = PWM(Pin(0), freq=5000, duty_u16=32768) # create PWM object from a pin
|
||||
freq = pwm0.freq() # get current frequency
|
||||
@@ -401,7 +300,7 @@ Use the :ref:`machine.PWM <machine.PWM>` class::
|
||||
pwm0.duty(256) # set duty cycle from 0 to 1023 as a ratio duty/1023, (now 25%)
|
||||
|
||||
duty_u16 = pwm0.duty_u16() # get current duty cycle, range 0-65535
|
||||
pwm0.duty_u16(65536*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
|
||||
pwm0.duty_u16(2**16*3//4) # set duty cycle from 0 to 65535 as a ratio duty_u16/65535, (now 75%)
|
||||
|
||||
duty_ns = pwm0.duty_ns() # get current pulse width in ns
|
||||
pwm0.duty_ns(250_000) # set pulse width in nanoseconds from 0 to 1_000_000_000/freq, (now 25%)
|
||||
@@ -410,35 +309,19 @@ Use the :ref:`machine.PWM <machine.PWM>` class::
|
||||
|
||||
pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go
|
||||
print(pwm2) # view PWM settings
|
||||
pwm2.deinit() # turn off PWM on the pin
|
||||
|
||||
pwm0 = PWM(Pin(0), duty_u16=16384) # The output is at a high level 25% of the time.
|
||||
pwm2 = PWM(Pin(2), duty_u16=16384, invert=1) # The output is at a low level 25% of the time.
|
||||
|
||||
pwm4 = PWM(Pin(4), lightsleep=True) # Allow PWM during light sleep mode
|
||||
|
||||
lightsleep(10*1000) # pwm0, pwm2 goes off, pwm4 stays on during 10s light sleep
|
||||
# pwm0, pwm2, pwm4 on after 10s light sleep
|
||||
|
||||
ESP chips have different hardware peripherals:
|
||||
|
||||
======================================================= ======== ========= ==========
|
||||
Hardware specification ESP32 ESP32-S2, ESP32-C2,
|
||||
ESP32-S3, ESP32-C3,
|
||||
ESP32-P4 ESP32-C5,
|
||||
ESP32-C6,
|
||||
ESP32-H2
|
||||
------------------------------------------------------- -------- --------- ----------
|
||||
Number of groups (speed modes) 2 1 1
|
||||
Number of timers per group 4 4 4
|
||||
Number of channels per group 8 8 6
|
||||
------------------------------------------------------- -------- --------- ----------
|
||||
Different PWM frequencies = (groups * timers) 8 4 4
|
||||
Total PWM channels (Pins, duties) = (groups * channels) 16 8 6
|
||||
======================================================= ======== ========= ==========
|
||||
|
||||
In light sleep, the ESP32 PWM can only operate in low speed mode, so only 4 timers and
|
||||
8 channels are available.
|
||||
===================================================== ======== ======== ========
|
||||
Hardware specification ESP32 ESP32-S2 ESP32-C3
|
||||
----------------------------------------------------- -------- -------- --------
|
||||
Number of groups (speed modes) 2 1 1
|
||||
Number of timers per group 4 4 4
|
||||
Number of channels per group 8 8 6
|
||||
----------------------------------------------------- -------- -------- --------
|
||||
Different PWM frequencies (groups * timers) 8 4 4
|
||||
Total PWM channels (Pins, duties) (groups * channels) 16 8 6
|
||||
===================================================== ======== ======== ========
|
||||
|
||||
A maximum number of PWM channels (Pins) are available on the ESP32 - 16 channels,
|
||||
but only 8 different PWM frequencies are available, the remaining 8 channels must
|
||||
@@ -548,63 +431,14 @@ Legacy methods:
|
||||
|
||||
Equivalent to ``ADC.block().init(bits=bits)``.
|
||||
|
||||
The only chip that can switch resolution to a lower one is the normal esp32.
|
||||
The C2 & S3 are stuck at 12 bits, while the S2 is at 13 bits.
|
||||
|
||||
For compatibility, the ``ADC`` object also provides constants matching the
|
||||
supported ADC resolutions, per chip:
|
||||
supported ADC resolutions:
|
||||
|
||||
ESP32:
|
||||
- ``ADC.WIDTH_9BIT`` = 9
|
||||
- ``ADC.WIDTH_10BIT`` = 10
|
||||
- ``ADC.WIDTH_11BIT`` = 11
|
||||
- ``ADC.WIDTH_12BIT`` = 12
|
||||
|
||||
ESP32 C3 & S3:
|
||||
- ``ADC.WIDTH_12BIT`` = 12
|
||||
|
||||
ESP32 S2:
|
||||
- ``ADC.WIDTH_13BIT`` = 13
|
||||
|
||||
.. method:: ADC.deinit()
|
||||
|
||||
Provided to deinit the adc driver.
|
||||
|
||||
Pulse Counter (pin pulse/edge counting)
|
||||
---------------------------------------
|
||||
|
||||
The ESP32 provides up to 8 pulse counter peripherals depending on the hardware,
|
||||
with id 0..7. These can be configured to count rising and/or falling edges on
|
||||
any input pin.
|
||||
|
||||
Use the :ref:`esp32.PCNT <esp32.PCNT>` class::
|
||||
|
||||
from machine import Pin
|
||||
from esp32 import PCNT
|
||||
|
||||
counter = PCNT(0, pin=Pin(2), rising=PCNT.INCREMENT) # create counter
|
||||
counter.start() # start counter
|
||||
count = counter.value() # read count, -32768..32767
|
||||
counter.value(0) # reset counter
|
||||
count = counter.value(0) # read and reset
|
||||
|
||||
The PCNT hardware supports monitoring multiple pins in a single unit to
|
||||
implement quadrature decoding or up/down signal counters.
|
||||
|
||||
See the :ref:`machine.Counter <machine.Counter>` and
|
||||
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
|
||||
common pulse counting applications::
|
||||
|
||||
from machine import Pin, Counter
|
||||
|
||||
counter = Counter(0, Pin(2)) # create a counter as above and start it
|
||||
count = counter.value() # read the count as an arbitrary precision signed integer
|
||||
|
||||
encoder = Encoder(0, Pin(12), Pin(14)) # create an encoder and begin counting
|
||||
count = encoder.value() # read the count as an arbitrary precision signed integer
|
||||
|
||||
Note that the id passed to these ``Counter()`` and ``Encoder()`` objects must be
|
||||
a PCNT id.
|
||||
|
||||
Software SPI bus
|
||||
----------------
|
||||
@@ -732,9 +566,7 @@ See :ref:`machine.RTC <machine.RTC>` ::
|
||||
from machine import RTC
|
||||
|
||||
rtc = RTC()
|
||||
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((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
|
||||
rtc.datetime() # get date and time
|
||||
|
||||
WDT (Watchdog timer)
|
||||
@@ -818,15 +650,15 @@ SD card
|
||||
|
||||
See :ref:`machine.SDCard <machine.SDCard>`. ::
|
||||
|
||||
import machine, os, vfs
|
||||
import machine, os
|
||||
|
||||
# On original ESP32, slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
|
||||
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
|
||||
sd = machine.SDCard(slot=2)
|
||||
vfs.mount(sd, '/sd') # mount
|
||||
os.mount(sd, '/sd') # mount
|
||||
|
||||
os.listdir('/sd') # list directory contents
|
||||
|
||||
vfs.umount('/sd') # eject
|
||||
os.umount('/sd') # eject
|
||||
|
||||
RMT
|
||||
---
|
||||
@@ -837,14 +669,11 @@ The RMT is ESP32-specific and allows generation of accurate digital pulses with
|
||||
import esp32
|
||||
from machine import Pin
|
||||
|
||||
r = esp32.RMT(pin=Pin(18), resolution_hz=10000000)
|
||||
r # RMT(pin=18, source_freq=80000000, resolution_hz=10000000)
|
||||
# The channel resolution is based on resolution_hz, i.e. 100ns for 10000000
|
||||
r = esp32.RMT(0, pin=Pin(18), clock_div=8)
|
||||
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8)
|
||||
# The channel resolution is 100ns (1/(source_freq/clock_div)).
|
||||
r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
|
||||
|
||||
The ESP32-C2 family does not include any RMT peripheral, so this class is
|
||||
unavailable on those SoCs.
|
||||
|
||||
OneWire driver
|
||||
--------------
|
||||
|
||||
@@ -903,40 +732,28 @@ The APA106 driver extends NeoPixel, but internally uses a different colour order
|
||||
``NeoPixel`` object.
|
||||
|
||||
For low-level driving of a NeoPixel see `machine.bitstream`.
|
||||
This low-level driver uses an RMT channel by default.
|
||||
This low-level driver uses an RMT channel by default. To configure this see
|
||||
`RMT.bitstream_channel`.
|
||||
|
||||
APA102 (DotStar) uses a different driver as it has an additional clock pin.
|
||||
|
||||
Capacitive touch
|
||||
----------------
|
||||
|
||||
ESP32, ESP32-S2 and ESP32-S3 support capacitive touch via the ``TouchPad`` class
|
||||
in the ``machine`` module::
|
||||
Use 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 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.
|
||||
``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.
|
||||
|
||||
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``.
|
||||
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``.
|
||||
|
||||
Note that TouchPads can be used to wake an ESP32 from sleep::
|
||||
|
||||
|
||||
@@ -21,4 +21,3 @@ to `<https://www.python.org>`__.
|
||||
intro.rst
|
||||
pwm.rst
|
||||
peripheral_access.rst
|
||||
reset.rst
|
||||
|
||||
@@ -36,95 +36,104 @@ 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 download page`_. Search for your particular board on this page.
|
||||
`MicroPython downloads page <https://micropython.org/download#esp32>`_.
|
||||
From here, you have 3 main choices:
|
||||
|
||||
.. 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).
|
||||
* Stable firmware builds
|
||||
* Daily firmware builds
|
||||
* Daily firmware builds with SPIRAM support
|
||||
|
||||
However, you may need to double check with the vendor you purchased
|
||||
the board from.
|
||||
|
||||
From here, you have a choice to make:
|
||||
|
||||
* Download a stable firmware release.
|
||||
* Download a daily firmware "Preview" build.
|
||||
|
||||
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.
|
||||
|
||||
.. _esp32_flashing:
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
For best results it is recommended to first erase the entire flash of your
|
||||
device before putting on new MicroPython firmware.
|
||||
|
||||
Currently we only support esptool.py to copy across the firmware. You can find
|
||||
this tool here: `<https://github.com/espressif/esptool/>`__, or install it
|
||||
using pip::
|
||||
|
||||
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::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 erase_flash
|
||||
|
||||
And then deploy the new firmware using::
|
||||
|
||||
esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 esp32-20180511-v1.9.4.bin
|
||||
|
||||
Notes:
|
||||
|
||||
* 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
|
||||
|
||||
If the above commands run without error then MicroPython should be installed on
|
||||
your board! Skip ahead to :ref:`esp32_serial_prompt`.
|
||||
|
||||
.. _esp32_troubleshooting_install:
|
||||
|
||||
Troubleshooting installation problems
|
||||
-------------------------------------
|
||||
|
||||
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
|
||||
<rest of line>`` for Linux or ``esptool --port COM4 <rest of line>`` 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:
|
||||
your board!
|
||||
|
||||
Serial prompt
|
||||
-------------
|
||||
|
||||
Once you have the firmware on the device you can access the REPL (Python prompt)
|
||||
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.
|
||||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
||||
converter, depending on your board. The baudrate is 115200.
|
||||
|
||||
From here you can now follow the ESP8266 tutorial, because these two Espressif chips
|
||||
are very similar when it comes to using MicroPython on them. The ESP8266 tutorial
|
||||
is found at :ref:`esp8266_tutorial` (but skip the Introduction section).
|
||||
|
||||
.. _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
|
||||
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.
|
||||
|
||||
@@ -32,18 +32,6 @@ 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:
|
||||
|
||||
@@ -11,20 +11,16 @@ compared with the length of a single period (low plus high time). Maximum
|
||||
duty cycle is when the pin is high all of the time, and minimum is when it is
|
||||
low all of the time.
|
||||
|
||||
* More comprehensive example with all **16 PWM channels and 8 timers**::
|
||||
* More comprehensive example with all 16 PWM channels and 8 timers::
|
||||
|
||||
from time import sleep
|
||||
from machine import Pin, PWM
|
||||
try:
|
||||
F = 10000 # Hz
|
||||
D = 65536 // 16 # 6.25%
|
||||
pins = (2, 4, 12, 13, 14, 15, 16, 18, 19, 22, 23, 25, 26, 27, 32, 33)
|
||||
f = 100 # Hz
|
||||
d = 1024 // 16 # 6.25%
|
||||
pins = (15, 2, 4, 16, 18, 19, 22, 23, 25, 26, 27, 14 , 12, 13, 32, 33)
|
||||
pwms = []
|
||||
for i, pin in enumerate(pins):
|
||||
f = F * (i // 2 + 1)
|
||||
d = min(65535, D * (i + 1))
|
||||
pwms.append(PWM(pin, freq=f, duty_u16=d))
|
||||
sleep(2 / f)
|
||||
pwms.append(PWM(Pin(pin), freq=f * (i // 2 + 1), duty= 1023 if i==15 else d * (i + 1)))
|
||||
print(pwms[i])
|
||||
finally:
|
||||
for pwm in pwms:
|
||||
@@ -35,100 +31,65 @@ low all of the time.
|
||||
|
||||
Output is::
|
||||
|
||||
PWM(Pin(2), freq=10000, duty_u16=4096)
|
||||
PWM(Pin(4), freq=10000, duty_u16=8192)
|
||||
PWM(Pin(12), freq=20000, duty_u16=12288)
|
||||
PWM(Pin(13), freq=20000, duty_u16=16384)
|
||||
PWM(Pin(14), freq=30030, duty_u16=20480)
|
||||
PWM(Pin(15), freq=30030, duty_u16=24576)
|
||||
PWM(Pin(16), freq=40000, duty_u16=28672)
|
||||
PWM(Pin(18), freq=40000, duty_u16=32768)
|
||||
PWM(Pin(19), freq=50000, duty_u16=36864)
|
||||
PWM(Pin(22), freq=50000, duty_u16=40960)
|
||||
PWM(Pin(23), freq=60060, duty_u16=45056)
|
||||
PWM(Pin(25), freq=60060, duty_u16=49152)
|
||||
PWM(Pin(26), freq=69930, duty_u16=53248)
|
||||
PWM(Pin(27), freq=69930, duty_u16=57344)
|
||||
PWM(Pin(32), freq=80000, duty_u16=61440)
|
||||
PWM(Pin(33), freq=80000, duty_u16=65535)
|
||||
PWM(Pin(15), freq=100, duty=64, resolution=10, mode=0, channel=0, timer=0)
|
||||
PWM(Pin(2), freq=100, duty=128, resolution=10, mode=0, channel=1, timer=0)
|
||||
PWM(Pin(4), freq=200, duty=192, resolution=10, mode=0, channel=2, timer=1)
|
||||
PWM(Pin(16), freq=200, duty=256, resolution=10, mode=0, channel=3, timer=1)
|
||||
PWM(Pin(18), freq=300, duty=320, resolution=10, mode=0, channel=4, timer=2)
|
||||
PWM(Pin(19), freq=300, duty=384, resolution=10, mode=0, channel=5, timer=2)
|
||||
PWM(Pin(22), freq=400, duty=448, resolution=10, mode=0, channel=6, timer=3)
|
||||
PWM(Pin(23), freq=400, duty=512, resolution=10, mode=0, channel=7, timer=3)
|
||||
PWM(Pin(25), freq=500, duty=576, resolution=10, mode=1, channel=0, timer=0)
|
||||
PWM(Pin(26), freq=500, duty=640, resolution=10, mode=1, channel=1, timer=0)
|
||||
PWM(Pin(27), freq=600, duty=704, resolution=10, mode=1, channel=2, timer=1)
|
||||
PWM(Pin(14), freq=600, duty=768, resolution=10, mode=1, channel=3, timer=1)
|
||||
PWM(Pin(12), freq=700, duty=832, resolution=10, mode=1, channel=4, timer=2)
|
||||
PWM(Pin(13), freq=700, duty=896, resolution=10, mode=1, channel=5, timer=2)
|
||||
PWM(Pin(32), freq=800, duty=960, resolution=10, mode=1, channel=6, timer=3)
|
||||
PWM(Pin(33), freq=800, duty=1023, resolution=10, mode=1, channel=7, timer=3)
|
||||
|
||||
|
||||
* Example of a **smooth frequency change**::
|
||||
* Example of a smooth frequency change::
|
||||
|
||||
from time import sleep
|
||||
from machine import Pin, PWM
|
||||
|
||||
F_MIN = 1000
|
||||
F_MAX = 10000
|
||||
F_MIN = 500
|
||||
F_MAX = 1000
|
||||
|
||||
f = F_MIN
|
||||
delta_f = F_MAX // 50
|
||||
delta_f = 1
|
||||
|
||||
pwm = PWM(Pin(27), f)
|
||||
p = PWM(Pin(5), f)
|
||||
print(p)
|
||||
|
||||
while True:
|
||||
pwm.freq(f)
|
||||
sleep(1 / f)
|
||||
sleep(0.1)
|
||||
print(pwm)
|
||||
p.freq(f)
|
||||
|
||||
sleep(10 / F_MIN)
|
||||
|
||||
f += delta_f
|
||||
if f > F_MAX or f < F_MIN:
|
||||
if f >= F_MAX or f <= F_MIN:
|
||||
delta_f = -delta_f
|
||||
print()
|
||||
if f > F_MAX:
|
||||
f = F_MAX
|
||||
elif f < F_MIN:
|
||||
f = F_MIN
|
||||
|
||||
See PWM wave on Pin(27) with an oscilloscope.
|
||||
See PWM wave at Pin(5) with an oscilloscope.
|
||||
|
||||
Output is::
|
||||
|
||||
PWM(Pin(27), freq=998, duty_u16=32768)
|
||||
PWM(Pin(27), freq=1202, duty_u16=32768)
|
||||
PWM(Pin(27), freq=1401, duty_u16=32768)
|
||||
PWM(Pin(27), freq=1598, duty_u16=32768)
|
||||
...
|
||||
PWM(Pin(27), freq=9398, duty_u16=32768)
|
||||
PWM(Pin(27), freq=9615, duty_u16=32768)
|
||||
PWM(Pin(27), freq=9804, duty_u16=32768)
|
||||
PWM(Pin(27), freq=10000, duty_u16=32768)
|
||||
|
||||
PWM(Pin(27), freq=10000, duty_u16=32768)
|
||||
PWM(Pin(27), freq=9804, duty_u16=32768)
|
||||
PWM(Pin(27), freq=9615, duty_u16=32768)
|
||||
PWM(Pin(27), freq=9398, duty_u16=32768)
|
||||
...
|
||||
PWM(Pin(27), freq=1598, duty_u16=32768)
|
||||
PWM(Pin(27), freq=1401, duty_u16=32768)
|
||||
PWM(Pin(27), freq=1202, duty_u16=32768)
|
||||
PWM(Pin(27), freq=998, duty_u16=32768)
|
||||
|
||||
|
||||
* Example of a **smooth duty change**::
|
||||
* Example of a smooth duty change::
|
||||
|
||||
from time import sleep
|
||||
from machine import Pin, PWM
|
||||
|
||||
DUTY_MAX = 65535
|
||||
DUTY_MAX = 2**16 - 1
|
||||
|
||||
duty_u16 = 0
|
||||
delta_d = 256
|
||||
delta_d = 16
|
||||
|
||||
pwm = PWM(Pin(27), freq=1000, duty_u16=duty_u16)
|
||||
p = PWM(Pin(5), 1000, duty_u16=duty_u16)
|
||||
print(p)
|
||||
|
||||
while True:
|
||||
pwm.duty_u16(duty_u16)
|
||||
sleep(2 / pwm.freq())
|
||||
print(pwm)
|
||||
p.duty_u16(duty_u16)
|
||||
|
||||
if duty_u16 >= DUTY_MAX:
|
||||
print()
|
||||
sleep(2)
|
||||
elif duty_u16 <= 0:
|
||||
print()
|
||||
sleep(2)
|
||||
sleep(1 / 1000)
|
||||
|
||||
duty_u16 += delta_d
|
||||
if duty_u16 >= DUTY_MAX:
|
||||
@@ -138,106 +99,9 @@ low all of the time.
|
||||
duty_u16 = 0
|
||||
delta_d = -delta_d
|
||||
|
||||
PWM wave on Pin(27) with an oscilloscope.
|
||||
See PWM wave at Pin(5) with an oscilloscope.
|
||||
|
||||
Output is::
|
||||
|
||||
PWM(Pin(27), freq=998, duty_u16=0)
|
||||
PWM(Pin(27), freq=998, duty_u16=256)
|
||||
PWM(Pin(27), freq=998, duty_u16=512)
|
||||
PWM(Pin(27), freq=998, duty_u16=768)
|
||||
PWM(Pin(27), freq=998, duty_u16=1024)
|
||||
...
|
||||
PWM(Pin(27), freq=998, duty_u16=64512)
|
||||
PWM(Pin(27), freq=998, duty_u16=64768)
|
||||
PWM(Pin(27), freq=998, duty_u16=65024)
|
||||
PWM(Pin(27), freq=998, duty_u16=65280)
|
||||
PWM(Pin(27), freq=998, duty_u16=65535)
|
||||
|
||||
PWM(Pin(27), freq=998, duty_u16=65279)
|
||||
PWM(Pin(27), freq=998, duty_u16=65023)
|
||||
PWM(Pin(27), freq=998, duty_u16=64767)
|
||||
PWM(Pin(27), freq=998, duty_u16=64511)
|
||||
...
|
||||
PWM(Pin(27), freq=998, duty_u16=1023)
|
||||
PWM(Pin(27), freq=998, duty_u16=767)
|
||||
PWM(Pin(27), freq=998, duty_u16=511)
|
||||
PWM(Pin(27), freq=998, duty_u16=255)
|
||||
PWM(Pin(27), freq=998, duty_u16=0)
|
||||
|
||||
|
||||
* Example of a **smooth duty change and PWM output inversion**::
|
||||
|
||||
from utime import sleep
|
||||
from machine import Pin, PWM
|
||||
|
||||
try:
|
||||
DUTY_MAX = 65535
|
||||
|
||||
duty_u16 = 0
|
||||
delta_d = 65536 // 32
|
||||
|
||||
pwm = PWM(Pin(27))
|
||||
pwmi = PWM(Pin(32), invert=1)
|
||||
|
||||
while True:
|
||||
pwm.duty_u16(duty_u16)
|
||||
pwmi.duty_u16(duty_u16)
|
||||
|
||||
duty_u16 += delta_d
|
||||
if duty_u16 >= DUTY_MAX:
|
||||
duty_u16 = DUTY_MAX
|
||||
delta_d = -delta_d
|
||||
elif duty_u16 <= 0:
|
||||
duty_u16 = 0
|
||||
delta_d = -delta_d
|
||||
|
||||
sleep(.01)
|
||||
print(pwm)
|
||||
print(pwmi)
|
||||
|
||||
finally:
|
||||
try:
|
||||
pwm.deinit()
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
pwmi.deinit()
|
||||
except:
|
||||
pass
|
||||
|
||||
Output is::
|
||||
|
||||
PWM(Pin(27), freq=5000, duty_u16=0)
|
||||
PWM(Pin(32), freq=5000, duty_u16=32768, invert=1)
|
||||
PWM(Pin(27), freq=5000, duty_u16=2048)
|
||||
PWM(Pin(32), freq=5000, duty_u16=2048, invert=1)
|
||||
PWM(Pin(27), freq=5000, duty_u16=4096)
|
||||
PWM(Pin(32), freq=5000, duty_u16=4096, invert=1)
|
||||
PWM(Pin(27), freq=5000, duty_u16=6144)
|
||||
PWM(Pin(32), freq=5000, duty_u16=6144, invert=1)
|
||||
PWM(Pin(27), freq=5000, duty_u16=8192)
|
||||
PWM(Pin(32), freq=5000, duty_u16=8192, invert=1)
|
||||
...
|
||||
|
||||
|
||||
See PWM waves on Pin(27) and Pin(32) with an oscilloscope.
|
||||
|
||||
Note: New PWM parameters take effect in the next PWM cycle.
|
||||
|
||||
pwm = PWM(2, duty=512)
|
||||
print(pwm)
|
||||
>>> PWM(Pin(2), freq=5000, duty=1023) # the duty is not relevant
|
||||
pwm.init(freq=2, duty=64)
|
||||
print(pwm)
|
||||
>>> PWM(Pin(2), freq=2, duty=16) # the duty is not relevant
|
||||
time.sleep(1 / 2) # wait one PWM period
|
||||
print(pwm)
|
||||
>>> PWM(Pin(2), freq=2, duty=64) # the duty is actual
|
||||
|
||||
Note: machine.freq(20_000_000) reduces the highest PWM frequency to 10 MHz.
|
||||
|
||||
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
|
||||
Note: the Pin.OUT mode does not need to be specified. The channel is initialized
|
||||
to PWM mode internally once for each Pin that is passed to the PWM constructor.
|
||||
|
||||
The following code is wrong::
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
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 <esp32_flashing>`).
|
||||
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
|
||||
@@ -74,7 +74,40 @@ as possible after use.
|
||||
Boot process
|
||||
------------
|
||||
|
||||
See :doc:`/reference/reset_boot`.
|
||||
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.
|
||||
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
@@ -49,19 +49,19 @@ The :mod:`esp` module::
|
||||
Networking
|
||||
----------
|
||||
|
||||
The :class:`network.WLAN` class in the :mod:`network` module::
|
||||
The :mod:`network` module::
|
||||
|
||||
import network
|
||||
|
||||
wlan = network.WLAN(network.WLAN.IF_STA) # create station interface
|
||||
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.connect('ssid', 'key') # connect to an AP
|
||||
wlan.config('mac') # get the interface's MAC address
|
||||
wlan.ipconfig('addr4') # get the interface's IPv4 addresses
|
||||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
|
||||
|
||||
ap = network.WLAN(network.WLAN.IF_AP) # create access-point interface
|
||||
ap = network.WLAN(network.AP_IF) # 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.WLAN.IF_STA)
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
if not wlan.isconnected():
|
||||
print('connecting to network...')
|
||||
wlan.connect('ssid', 'key')
|
||||
while not wlan.isconnected():
|
||||
pass
|
||||
print('network config:', wlan.ipconfig('addr4'))
|
||||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the :mod:`socket <socket>` module can be used
|
||||
to create and use TCP/UDP sockets as usual.
|
||||
@@ -108,9 +108,6 @@ with timer ID of -1::
|
||||
|
||||
The period is in milliseconds.
|
||||
|
||||
By default, timer callbacks are scheduled as soft interrupts on this port.
|
||||
Specify ``hard=True`` to run them in hard interrupt context instead.
|
||||
|
||||
Pins and GPIO
|
||||
-------------
|
||||
|
||||
@@ -166,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
|
||||
:doc:`hard or soft reset </reference/reset_boot>`) 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 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::
|
||||
@@ -287,9 +284,7 @@ See :ref:`machine.RTC <machine.RTC>` ::
|
||||
from machine import RTC
|
||||
|
||||
rtc = RTC()
|
||||
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((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
|
||||
rtc.datetime() # get date and time
|
||||
|
||||
# synchronize with ntp
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
Network basics
|
||||
==============
|
||||
|
||||
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
|
||||
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
|
||||
instances of these objects using::
|
||||
|
||||
>>> import network
|
||||
>>> sta_if = network.WLAN(network.WLAN.IF_STA)
|
||||
>>> ap_if = network.WLAN(network.WLAN.IF_AP)
|
||||
>>> sta_if = network.WLAN(network.STA_IF)
|
||||
>>> ap_if = network.WLAN(network.AP_IF)
|
||||
|
||||
You can check if the interfaces are active by::
|
||||
|
||||
@@ -20,10 +19,10 @@ You can check if the interfaces are active by::
|
||||
|
||||
You can also check the network settings of the interface by::
|
||||
|
||||
>>> ap_if.ipconfig('addr4')
|
||||
('192.168.4.1', '255.255.255.0')
|
||||
>>> ap_if.ifconfig()
|
||||
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
|
||||
|
||||
The returned values are: IP address and netmask.
|
||||
The returned values are: IP address, netmask, gateway, DNS.
|
||||
|
||||
Configuration of the WiFi
|
||||
-------------------------
|
||||
@@ -46,8 +45,8 @@ To check if the connection is established use::
|
||||
|
||||
Once established you can check the IP address::
|
||||
|
||||
>>> sta_if.ipconfig('addr4')
|
||||
('192.168.0.2', '255.255.255.0')
|
||||
>>> sta_if.ifconfig()
|
||||
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
|
||||
|
||||
You can then disable the access-point interface if you no longer need it::
|
||||
|
||||
@@ -58,14 +57,14 @@ connect to your WiFi network::
|
||||
|
||||
def do_connect():
|
||||
import network
|
||||
sta_if = network.WLAN(network.WLAN.IF_STA)
|
||||
sta_if = network.WLAN(network.STA_IF)
|
||||
if not sta_if.isconnected():
|
||||
print('connecting to network...')
|
||||
sta_if.active(True)
|
||||
sta_if.connect('<ssid>', '<key>')
|
||||
while not sta_if.isconnected():
|
||||
pass
|
||||
print('network config:', sta_if.ipconfig('addr4'))
|
||||
print('network config:', sta_if.ifconfig())
|
||||
|
||||
Sockets
|
||||
-------
|
||||
|
||||
@@ -38,7 +38,7 @@ browser. The latest versions of Firefox and Chrome are supported.
|
||||
|
||||
For your convenience, WebREPL client is hosted at
|
||||
`<http://micropython.org/webrepl>`__. Alternatively, you can install it
|
||||
locally from the GitHub repository
|
||||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__.
|
||||
|
||||
Before connecting to WebREPL, you should set a password and enable it via
|
||||
|
||||
@@ -19,10 +19,6 @@ 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.
|
||||
|
||||
@@ -149,7 +149,8 @@ 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.
|
||||
callbacks. Flags start in the cleared state. The class does not currently
|
||||
work under the Unix build of MicroPython.
|
||||
|
||||
.. method:: ThreadSafeFlag.set()
|
||||
|
||||
|
||||
@@ -36,9 +36,3 @@ Functions
|
||||
Encode binary data in base64 format, as in `RFC 3548
|
||||
<https://tools.ietf.org/html/rfc3548.html>`_. 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.
|
||||
|
||||
@@ -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 reused. This allows a
|
||||
to the previous call to ``gap_advertise`` will be re-used. 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 ``_IRQ_L2CAP_CONNECT`` event will be
|
||||
On successful connection, the 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
|
||||
ESP32, STM32 and Unix.
|
||||
STM32 and Unix (not ESP32).
|
||||
|
||||
.. method:: BLE.gap_pair(conn_handle, /)
|
||||
|
||||
@@ -764,5 +764,4 @@ Constructor
|
||||
The **value** can be either:
|
||||
|
||||
- A 16-bit integer. e.g. ``0x2908``.
|
||||
- An object with the buffer protocol and that is 2, 4 or 16 bytes long, e.g. ``b'\x08\x29'``.
|
||||
- A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``.
|
||||
|
||||
@@ -151,10 +151,10 @@ Constants
|
||||
|
||||
.. data:: INCL
|
||||
|
||||
A flag for :meth:`btree.keys`, :meth:`btree.values`, :meth:`btree.items` methods to specify that
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be inclusive of the end key.
|
||||
|
||||
.. data:: DESC
|
||||
|
||||
A flag for :meth:`btree.keys`, :meth:`btree.values`, :meth:`btree.items` methods to specify that
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be in descending direction of keys.
|
||||
|
||||
@@ -19,8 +19,6 @@ Functions and types
|
||||
|
||||
.. class:: bytearray()
|
||||
|
||||
|see_cpython| `python:bytearray`.
|
||||
|
||||
.. class:: bytes()
|
||||
|
||||
|see_cpython| `python:bytes`.
|
||||
@@ -84,10 +82,6 @@ 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 <cpydiff_types_int_to_bytes>`.)
|
||||
|
||||
.. function:: isinstance()
|
||||
|
||||
.. function:: issubclass()
|
||||
@@ -106,8 +100,6 @@ Functions and types
|
||||
|
||||
.. class:: memoryview()
|
||||
|
||||
|see_cpython| `python:memoryview`.
|
||||
|
||||
.. function:: min()
|
||||
|
||||
.. function:: next()
|
||||
@@ -174,10 +166,6 @@ Exceptions
|
||||
|
||||
.. exception:: KeyboardInterrupt
|
||||
|
||||
|see_cpython| `python:KeyboardInterrupt`.
|
||||
|
||||
See also in the context of :ref:`soft_bricking`.
|
||||
|
||||
.. exception:: KeyError
|
||||
|
||||
.. exception:: MemoryError
|
||||
@@ -198,12 +186,6 @@ 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`.
|
||||
|
||||
@@ -18,9 +18,7 @@ Classes
|
||||
appends and pops from either side of the deque. New deques are created
|
||||
using the following arguments:
|
||||
|
||||
- *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.
|
||||
- *iterable* must be the empty tuple, and the new deque is created 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
|
||||
@@ -28,37 +26,18 @@ Classes
|
||||
|
||||
- The optional *flags* can be 1 to check for overflow when adding items.
|
||||
|
||||
Deque objects support `bool`, `len`, iteration and subscript load and store.
|
||||
They also have the following methods:
|
||||
As well as supporting `bool` and `len`, deque objects 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 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.
|
||||
Raises IndexError if overflow checking is enabled and there is no more room left.
|
||||
|
||||
.. method:: deque.popleft()
|
||||
|
||||
Remove and return an item from the left side of the deque.
|
||||
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.
|
||||
Raises IndexError if no items are present.
|
||||
|
||||
.. function:: namedtuple(name, fields)
|
||||
|
||||
@@ -101,19 +80,3 @@ Classes
|
||||
a 2
|
||||
w 5
|
||||
b 3
|
||||
|
||||
.. method:: OrderedDict.popitem()
|
||||
|
||||
Remove and return a (key, value) pair from the dictionary.
|
||||
Pairs are returned in LIFO order.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
``OrderedDict.popitem()`` does not support the ``last=False`` argument and
|
||||
will always remove and return the last item if present.
|
||||
|
||||
A workaround for this is to use ``pop(<first_key>)`` to remove the first item::
|
||||
|
||||
first_key = next(iter(d))
|
||||
d.pop(first_key)
|
||||
|
||||
@@ -18,40 +18,23 @@ Functions
|
||||
Configure whether or not a touch will wake the device from sleep.
|
||||
*wake* should be a boolean value.
|
||||
|
||||
.. note:: This is only available for boards that have touch sensor support.
|
||||
|
||||
.. function:: wake_on_ulp(wake)
|
||||
|
||||
Configure whether or not the Ultra-Low-Power co-processor can wake the
|
||||
device from sleep. *wake* should be a boolean value.
|
||||
|
||||
.. note:: This is only available for boards that have ULP coprocessor support.
|
||||
|
||||
.. function:: wake_on_ext0(pin, level)
|
||||
|
||||
Configure how EXT0 wakes the device from sleep. *pin* can be ``None``
|
||||
or a valid Pin object. *level* should be ``esp32.WAKEUP_ALL_LOW`` or
|
||||
``esp32.WAKEUP_ANY_HIGH``.
|
||||
|
||||
.. note:: This is only available for boards that have ext0 support.
|
||||
|
||||
.. function:: wake_on_ext1(pins, level)
|
||||
|
||||
Configure how EXT1 wakes the device from sleep. *pins* can be ``None``
|
||||
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
|
||||
or ``esp32.WAKEUP_ANY_HIGH``.
|
||||
|
||||
.. note:: This is only available for boards that have ext1 support.
|
||||
|
||||
.. function:: wake_on_gpio(pins, level)
|
||||
|
||||
Configure how GPIO wakes the device from sleep. *pins* can be ``None``
|
||||
or a tuple/list of valid Pin objects. *level* should be ``esp32.WAKEUP_ALL_LOW``
|
||||
or ``esp32.WAKEUP_ANY_HIGH``.
|
||||
|
||||
.. note:: Some boards don't support waking on GPIO from deep sleep,
|
||||
on those boards, the pins set here can only be used to wake from light sleep.
|
||||
|
||||
.. function:: gpio_deep_sleep_hold(enable)
|
||||
|
||||
Configure whether non-RTC GPIO pin configuration is retained during
|
||||
@@ -97,29 +80,6 @@ Functions
|
||||
The result of :func:`gc.mem_free()` is the total of the current "free"
|
||||
and "max new split" values printed by :func:`micropython.mem_info()`.
|
||||
|
||||
.. function:: idf_task_info()
|
||||
|
||||
Returns information about running ESP-IDF/FreeRTOS tasks, which include
|
||||
MicroPython threads. This data is useful to gain insight into how much time
|
||||
tasks spend running or if they are blocked for significant parts of time,
|
||||
and to determine if allocated stacks are fully utilized or might be reduced.
|
||||
|
||||
``CONFIG_FREERTOS_USE_TRACE_FACILITY=y`` must be set in the board
|
||||
configuration to make this method available. Additionally configuring
|
||||
``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` and
|
||||
``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` is recommended to be able to
|
||||
retrieve the total and per-task runtime and the core ID respectively.
|
||||
|
||||
The return value is a 2-tuple where the first value is the total runtime,
|
||||
and the second a list of tasks. Each task is a 7-tuple containing: the task
|
||||
ID, name, current state, priority, runtime, stack high water mark, and the
|
||||
ID of the core it is running on. Runtime and core ID will be None when the
|
||||
respective FreeRTOS configuration option is not enabled.
|
||||
|
||||
.. note:: For an easier to use output based on this function you can use the
|
||||
`utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`_,
|
||||
which implements a live overview similar to the Unix ``top`` command.
|
||||
|
||||
|
||||
Flash partitions
|
||||
----------------
|
||||
@@ -154,7 +114,7 @@ methods to enable over-the-air (OTA) updates.
|
||||
|
||||
These methods implement the simple and :ref:`extended
|
||||
<block-device-interface>` block protocol defined by
|
||||
:class:`vfs.AbstractBlockDev`.
|
||||
:class:`os.AbstractBlockDev`.
|
||||
|
||||
.. method:: Partition.set_boot()
|
||||
|
||||
@@ -204,151 +164,6 @@ Constants
|
||||
|
||||
Used in `idf_heap_info`.
|
||||
|
||||
|
||||
.. _esp32.PCNT:
|
||||
|
||||
PCNT
|
||||
----
|
||||
|
||||
This class provides access to the ESP32 hardware support for pulse counting.
|
||||
There are 8 pulse counter units, with id 0..7.
|
||||
|
||||
See the :ref:`machine.Counter <machine.Counter>` and
|
||||
:ref:`machine.Encoder <machine.Encoder>` classes for simpler and portable
|
||||
abstractions of common pulse counting applications. These classes are
|
||||
implemented as thin Python shims around :class:`PCNT`.
|
||||
|
||||
.. class:: PCNT(id, *, ...)
|
||||
|
||||
Returns the singleton PCNT instance for the given unit ``id``.
|
||||
|
||||
Keyword arguments are passed to the ``init()`` method as described
|
||||
below.
|
||||
|
||||
.. method:: PCNT.init(*, ...)
|
||||
|
||||
(Re-)initialise a pulse counter unit. Supported keyword arguments are:
|
||||
|
||||
- ``channel``: see description below
|
||||
- ``pin``: the input Pin to monitor for pulses
|
||||
- ``rising``: an action to take on a rising edge - one of
|
||||
``PCNT.INCREMENT``, ``PCNT.DECREMENT`` or ``PCNT.IGNORE`` (the default)
|
||||
- ``falling``: an action to take on a falling edge (takes the save values
|
||||
as the ``rising`` argument).
|
||||
- ``mode_pin``: ESP32 pulse counters support monitoring a second pin and
|
||||
altering the behaviour of the counter based on its level - set this
|
||||
keyword to any input Pin
|
||||
- ``mode_low``: set to either ``PCNT.HOLD`` or ``PCNT.REVERSE`` to
|
||||
either suspend counting or reverse the direction of the counter (i.e.,
|
||||
``PCNT.INCREMENT`` behaves as ``PCNT.DECREMENT`` and vice versa)
|
||||
when ``mode_pin`` is low
|
||||
- ``mode_high``: as ``mode_low`` but for the behaviour when ``mode_pin``
|
||||
is high
|
||||
- ``filter``: set to a value 1..1023, in ticks of the 80MHz clock, to
|
||||
enable the pulse width filter
|
||||
- ``min``: set to the minimum level of the counter value when
|
||||
decrementing (-32768..-1) or 0 to disable
|
||||
- ``max``: set to the maximum level of the counter value when
|
||||
incrementing (1..32767) or 0 to disable
|
||||
- ``threshold0``: sets the counter value for the
|
||||
``PCNT.IRQ_THRESHOLD0`` event (see ``irq`` method)
|
||||
- ``threshold1``: sets the counter value for the
|
||||
``PCNT.IRQ_THRESHOLD1`` event (see ``irq`` method)
|
||||
- ``value``: can be set to ``0`` to reset the counter value
|
||||
|
||||
The hardware initialisation is done in stages and so some of the keyword
|
||||
arguments can be used in groups or in isolation to partially reconfigure a
|
||||
unit:
|
||||
|
||||
- the ``pin`` keyword (optionally combined with ``mode_pin``) can be used
|
||||
to change just the bound pin(s)
|
||||
- ``rising``, ``falling``, ``mode_low`` and ``mode_high`` can be used
|
||||
(singly or together) to change the counting logic - omitted keywords
|
||||
use their default (``PCNT.IGNORE`` or ``PCNT.NORMAL``)
|
||||
- ``filter`` can be used to change only the pulse width filter (with 0
|
||||
disabling it)
|
||||
- each of ``min``, ``max``, ``threshold0`` and ``threshold1`` can
|
||||
be used to change these limit/event values individually; however,
|
||||
setting any will reset the counter to zero (i.e., they imply
|
||||
``value=0``)
|
||||
|
||||
Each pulse counter unit supports two channels, 0 and 1, each able to
|
||||
monitor different pins with different counting logic but updating the same
|
||||
counter value. Use ``channel=1`` with the ``pin``, ``rising``, ``falling``,
|
||||
``mode_pin``, ``mode_low`` and ``mode_high`` keywords to configure the
|
||||
second channel.
|
||||
|
||||
The second channel can be used to configure 4X quadrature decoding with a
|
||||
single counter unit::
|
||||
|
||||
pin_a = Pin(2, Pin.INPUT, pull=Pin.PULL_UP)
|
||||
pin_b = Pin(3, Pin.INPUT, pull=Pin.PULL_UP)
|
||||
rotary = PCNT(0, min=-32000, max=32000)
|
||||
rotary.init(channel=0, pin=pin_a, falling=PCNT.INCREMENT, rising=PCNT.DECREMENT, mode_pin=pin_b, mode_low=PCNT.REVERSE)
|
||||
rotary.init(channel=1, pin=pin_b, falling=PCNT.DECREMENT, rising=PCNT.INCREMENT, mode_pin=pin_a, mode_low=PCNT.REVERSE)
|
||||
rotary.start()
|
||||
|
||||
.. method:: PCNT.value([value])
|
||||
|
||||
Call this method with no arguments to return the current counter value.
|
||||
|
||||
If the optional *value* argument is set to ``0`` then the counter is
|
||||
reset (but the previous value is returned). Read and reset is not atomic and
|
||||
so it is possible for a pulse to be missed. Any value other than ``0`` will
|
||||
raise an error.
|
||||
|
||||
.. method:: PCNT.irq(handler=None, trigger=PCNT.IRQ_ZERO)
|
||||
|
||||
ESP32 pulse counters support interrupts on these counter events:
|
||||
|
||||
- ``PCNT.IRQ_ZERO``: the counter has reset to zero
|
||||
- ``PCNT.IRQ_MIN``: the counter has hit the ``min`` value
|
||||
- ``PCNT.IRQ_MAX``: the counter has hit the ``max`` value
|
||||
- ``PCNT.IRQ_THRESHOLD0``: the counter has hit the ``threshold0`` value
|
||||
- ``PCNT.IRQ_THRESHOLD1``: the counter has hit the ``threshold1`` value
|
||||
|
||||
``trigger`` should be a bit-mask of the desired events OR'ed together. The
|
||||
``handler`` function should take a single argument which is the
|
||||
:class:`PCNT` instance that raised the event.
|
||||
|
||||
This method returns a callback object. The callback object can be used to
|
||||
access the bit-mask of events that are outstanding on the PCNT unit.::
|
||||
|
||||
def pcnt_irq(pcnt):
|
||||
flags = pcnt.irq().flags()
|
||||
if flags & PCNT.IRQ_ZERO:
|
||||
# reset
|
||||
if flags & PCNT.IRQ_MAX:
|
||||
# overflow...
|
||||
... etc
|
||||
|
||||
pcnt.irq(handler=pcnt_irq, trigger=PCNT.IRQ_ZERO | PCNT.IRQ_MAX | ...)
|
||||
|
||||
**Note:** Accessing ``irq.flags()`` will clear the flags, so only call it
|
||||
once per invocation of the handler.
|
||||
|
||||
The handler is called with the MicroPython scheduler and so will run at a
|
||||
point after the interrupt. If another interrupt occurs before the handler
|
||||
has been called then the events will be coalesced together into a single
|
||||
call and the bit mask will indicate all events that have occurred.
|
||||
|
||||
To avoid race conditions between a handler being called and retrieving the
|
||||
current counter value, the ``value()`` method will force execution of any
|
||||
pending events before returning the current counter value (and potentially
|
||||
resetting the value).
|
||||
|
||||
Only one handler can be in place per-unit. Set ``handler`` to ``None`` to
|
||||
disable the event interrupt.
|
||||
|
||||
.. Note::
|
||||
ESP32 pulse counters reset to *zero* when reaching the minimum or maximum
|
||||
value. Thus the ``IRQ_ZERO`` event will also trigger when either of these
|
||||
events occurs.
|
||||
|
||||
See the :ref:`machine.Counter <machine.Counter>` and
|
||||
:ref:`machine.Encoder <machine.Encoder>` classes for simpler abstractions of
|
||||
common pulse counting applications.
|
||||
|
||||
.. _esp32.RMT:
|
||||
|
||||
RMT
|
||||
@@ -362,24 +177,29 @@ used to transmit or receive many other types of digital signals::
|
||||
import esp32
|
||||
from machine import Pin
|
||||
|
||||
r = esp32.RMT(pin=Pin(18), resolution_hz=10000000)
|
||||
r # RMT(pin=18, source_freq=80000000, resolution_hz=10000000, idle_level=0)
|
||||
r = esp32.RMT(0, pin=Pin(18), clock_div=8)
|
||||
r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8, idle_level=0)
|
||||
|
||||
# To apply a carrier frequency to the high output
|
||||
r = esp32.RMT(pin=Pin(18), resolution_hz=10000000, tx_carrier=(38000, 50, 1))
|
||||
r = esp32.RMT(0, pin=Pin(18), clock_div=8, tx_carrier=(38000, 50, 1))
|
||||
|
||||
# The channel resolution is 100ns (1/resolution_hz)
|
||||
# The channel resolution is 100ns (1/(source_freq/clock_div)).
|
||||
r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
|
||||
|
||||
The input to the RMT module is an 80MHz clock (in the future it may be able to
|
||||
configure the input clock but, for now, it's fixed). ``resolution_hz`` determines
|
||||
the resolution of the RMT channel. The numbers specified in ``write_pulses`` are
|
||||
multiplied by the resolution to
|
||||
configure the input clock but, for now, it's fixed). ``clock_div`` *divides*
|
||||
the clock input which determines the resolution of the RMT channel. The
|
||||
numbers specified in ``write_pulses`` are multiplied by the resolution to
|
||||
define the pulses.
|
||||
|
||||
So, in the example above, the resolution is resolution is (1/10Mhz) = 100ns.
|
||||
Since the ``start`` level is 0 and toggles with each number, the bitstream is
|
||||
``0101`` with durations of [100ns, 2000ns, 100ns, 4000ns].
|
||||
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
|
||||
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
|
||||
channels (0-7) and each can have a different clock divider.
|
||||
|
||||
So, in the example above, the 80MHz clock is divided by 8. Thus the
|
||||
resolution is (1/(80Mhz/8)) 100ns. Since the ``start`` level is 0 and toggles
|
||||
with each number, the bitstream is ``0101`` with durations of [100ns, 2000ns,
|
||||
100ns, 4000ns].
|
||||
|
||||
For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
<https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html>`_.
|
||||
@@ -390,24 +210,13 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
*beta feature* and the interface may change in the future.
|
||||
|
||||
|
||||
.. class:: RMT(channel, *, pin=None, resolution_hz=10000000, clock_div=None, idle_level=False, num_symbols=48|64, tx_carrier=None)
|
||||
.. class:: RMT(channel, *, pin=None, clock_div=8, idle_level=False, tx_carrier=None)
|
||||
|
||||
This class provides access to one of the eight RMT channels. *channel* is
|
||||
optional and a dummy parameter for backward compatibility. *pin* is required
|
||||
and configures which Pin is bound to the RMT channel.
|
||||
*resolution_hz* defines the resolution/unit of the samples.
|
||||
For example, 1,000,000 means the unit is microsecond. The pulse widths can
|
||||
assume values up to *RMT.PULSE_MAX*, so the resolution should be selected
|
||||
accordingly to the signal to be transmitted.
|
||||
*clock_div* (deprecated) is equivalent to *resolution_hz*, but expressed as
|
||||
a clock divider that divides the source clock (80MHz) to the RMT
|
||||
channel allowing the resolution to be specified. Either *clock_div* and
|
||||
*resolution_hz* may be supplied, but not both.
|
||||
*num_symbols* specifies the
|
||||
RMT buffer allocated for this channel (minimum 48 or 64, depending on chip), from a small pool of
|
||||
symbols (192 to 512, depending on chip) that are shared by all channels. This buffer does not limit the
|
||||
size of the pulse train that you can send, but bigger buffers reduce the
|
||||
CPU load and the potential of glitches/imprecise pulse lengths. *idle_level* specifies
|
||||
required and identifies which RMT channel (0-7) will be configured. *pin*,
|
||||
also required, configures which Pin is bound to the RMT channel. *clock_div*
|
||||
is an 8-bit clock divider that divides the source clock (80MHz) to the RMT
|
||||
channel allowing the resolution to be specified. *idle_level* specifies
|
||||
what level the output will be when no transmission is in progress and can
|
||||
be any value that converts to a boolean, with ``True`` representing high
|
||||
voltage and ``False`` representing low.
|
||||
@@ -425,52 +234,21 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
.. method:: RMT.clock_div()
|
||||
|
||||
Return the clock divider. Note that the channel resolution is
|
||||
``1 / (source_freq / clock_div)``. (Method deprecated. The value may
|
||||
not be faithful if resolution was supplied as *resolution_hz*.)
|
||||
``1 / (source_freq / clock_div)``.
|
||||
|
||||
.. method:: RMT.wait_done(*, timeout=0)
|
||||
|
||||
Returns ``True`` if the channel is idle or ``False`` if a sequence of
|
||||
pulses started with `RMT.write_pulses` is being transmitted. If the
|
||||
*timeout* keyword argument is given then block for up to this many
|
||||
milliseconds for transmission to complete. Timeout of -1 blocks until
|
||||
transmission is complete (and blocks forever if loop is enabled).
|
||||
milliseconds for transmission to complete.
|
||||
|
||||
.. method:: RMT.loop(enable_loop)
|
||||
|
||||
Configure looping on the channel. *enable_loop* is bool, set to ``True`` to
|
||||
enable looping on the *next* call to `RMT.write_pulses`. If called with
|
||||
``False`` while a looping sequence is currently being transmitted then the
|
||||
transmission will stop. (Method deprecated by `RMT.loop_count`.)
|
||||
|
||||
.. method:: RMT.loop_count(n)
|
||||
|
||||
Configure looping on the channel. *n* is int. Affects the *next* call to
|
||||
`RMT.write_pulses`. Set to ``0`` to disable looping, ``-1`` to enable
|
||||
infinite looping, or a positive number to loop for a given number of times.
|
||||
If *n* is changed, the current transmission is stopped.
|
||||
|
||||
Note: looping for a finite number of times is not supported by all flavors
|
||||
of ESP32.
|
||||
|
||||
.. method:: RMT.active([boolean])
|
||||
|
||||
If called without parameters, returns *True* if there is an ongoing transmission.
|
||||
|
||||
If called with parameter *False*, stops the ongoing transmission.
|
||||
This is useful to stop an infinite transmission loop.
|
||||
The current loop is finished and transmission stops.
|
||||
The object is not invalidated, and the RMT channel is again enabled when a new
|
||||
transmission is started.
|
||||
|
||||
Calling with parameter *True* does not restart transmission. A new transmission
|
||||
should always be initiated by *write_pulses()*.
|
||||
|
||||
.. method:: RMT.deinit()
|
||||
|
||||
Release all RMT resources and invalidate the object. All subsequent method
|
||||
calls will raise OSError. Useful to free RMT resources without having to wait
|
||||
for the object to be garbage-collected.
|
||||
current loop iteration will be completed and then transmission will stop.
|
||||
|
||||
.. method:: RMT.write_pulses(duration, data=True)
|
||||
|
||||
@@ -500,28 +278,17 @@ For more details see Espressif's `ESP-IDF RMT documentation.
|
||||
new sequence of pulses. Looping sequences longer than 126 pulses is not
|
||||
supported by the hardware.
|
||||
|
||||
.. staticmethod:: RMT.bitstream_rmt([value])
|
||||
|
||||
Configure RMT usage in the `machine.bitstream` implementation.
|
||||
|
||||
If *value* is ``True``, bitstream tries to use RMT if possible. If *value*
|
||||
is ``False``, bitstream sticks to the bit-banging implementation.
|
||||
|
||||
If no parameter is supplied, it returns the current state. The default state
|
||||
is ``True``.
|
||||
|
||||
.. staticmethod:: RMT.bitstream_channel([value])
|
||||
|
||||
*This function is deprecated and will be replaced by `RMT.bitstream_rmt()`.*
|
||||
Select which RMT channel is used by the `machine.bitstream` implementation.
|
||||
*value* can be ``None`` or a valid RMT channel number. The default RMT
|
||||
channel is the highest numbered one.
|
||||
|
||||
Passing in no argument will return ``1`` if RMT was enabled for the `machine.bitstream`
|
||||
feature, and ``None`` otherwise.
|
||||
Passing in ``None`` disables the use of RMT and instead selects a bit-banging
|
||||
implementation for `machine.bitstream`.
|
||||
|
||||
Passing any non-negative integer argument is equivalent to calling ``RMT.bitstream_rmt(True)``.
|
||||
|
||||
.. note:: In previous versions of MicroPython it was necessary to use this function to assign
|
||||
a specific RMT channel number for the bitstream, but the channel number is now assigned
|
||||
dynamically.
|
||||
Passing in no argument will not change the channel. This function returns
|
||||
the current channel number.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
@@ -56,7 +56,7 @@ A simple example would be:
|
||||
import espnow
|
||||
|
||||
# A WLAN interface must be active to send()/recv()
|
||||
sta = network.WLAN(network.WLAN.IF_STA) # Or network.WLAN.IF_AP
|
||||
sta = network.WLAN(network.STA_IF) # Or network.AP_IF
|
||||
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.WLAN.IF_STA)
|
||||
sta = network.WLAN(network.STA_IF)
|
||||
sta.active(True)
|
||||
sta.disconnect() # Because ESP8266 auto-connects to last Access Point
|
||||
|
||||
@@ -164,15 +164,11 @@ Configuration
|
||||
wait forever. The timeout can also be provided as arg to
|
||||
`recv()`/`irecv()`/`recvinto()`.
|
||||
|
||||
*rate*: (ESP32 only) Set the transmission data rate for ESPNow packets.
|
||||
The default setting is `espnow.RATE_1M`. It's recommended to use one of
|
||||
the other ``espnow.RATE_nnn`` constants to set this, but it's also
|
||||
possible to pass an integer corresponding to the `enum wifi_phy_rate_t
|
||||
<https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32/
|
||||
api-reference/network/esp_wifi.html#_CPPv415wifi_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.
|
||||
See also `espnow-long-range`. This API currently doesn't work on ESP32-C6.
|
||||
*rate*: (ESP32 only, IDF>=4.3.0 only) Set the transmission speed for
|
||||
ESPNow packets. Must be set to a number from the allowed numeric values
|
||||
in `enum wifi_phy_rate_t
|
||||
<https://docs.espressif.com/projects/esp-idf/en/v4.4.1/esp32/
|
||||
api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t>`_.
|
||||
|
||||
.. data:: Returns:
|
||||
|
||||
@@ -186,14 +182,14 @@ Configuration
|
||||
Sending and Receiving Data
|
||||
--------------------------
|
||||
|
||||
A wifi interface (``network.WLAN.IF_STA`` or ``network.WLAN.IF_AP``) must be
|
||||
A wifi interface (``network.STA_IF`` or ``network.AP_IF``) must be
|
||||
`active()<network.WLAN.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.WLAN.IF_STA)
|
||||
sta = network.WLAN(network.STA_IF)
|
||||
sta.active(True)
|
||||
sta.disconnect() # For ESP8266
|
||||
|
||||
@@ -445,14 +441,12 @@ 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, if channel is set to another
|
||||
value then this must match the channel currently configured on the
|
||||
interface (see :func:`WLAN.config`). (default=0)
|
||||
channel of the wifi device will be used. (default=0)
|
||||
|
||||
- *ifidx*: (ESP32 only) Index of the wifi interface which will be
|
||||
used to send data to this peer. Must be an integer set to
|
||||
``network.WLAN.IF_STA`` (=0) or ``network.WLAN.IF_AP`` (=1).
|
||||
(default=0/``network.WLAN.IF_STA``). See `ESPNow and Wifi Operation`_
|
||||
``network.STA_IF`` (=0) or ``network.AP_IF`` (=1).
|
||||
(default=0/``network.STA_IF``). See `ESPNow and Wifi Operation`_
|
||||
below for more information.
|
||||
|
||||
- *encrypt*: (ESP32 only) If set to ``True`` data exchanged with
|
||||
@@ -476,9 +470,6 @@ 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)
|
||||
@@ -576,45 +567,6 @@ Constants
|
||||
espnow.MAX_TOTAL_PEER_NUM(=20)
|
||||
espnow.MAX_ENCRYPT_PEER_NUM(=6)
|
||||
|
||||
The following constants correspond to different transmit data rates on ESP32
|
||||
only. Lower data rates are generally more reliable over long distances:
|
||||
|
||||
.. data:: espnow.RATE_LORA_250K
|
||||
espnow.RATE_LORA_500K
|
||||
|
||||
See `espnow-long-range`.
|
||||
|
||||
.. data:: espnow.RATE_1M
|
||||
espnow.RATE_2M
|
||||
espnow.RATE_5M
|
||||
espnow.RATE_6M
|
||||
espnow.RATE_11M
|
||||
espnow.RATE_12M
|
||||
espnow.RATE_24M
|
||||
espnow.RATE_54M
|
||||
|
||||
Unless using the two proprietary long range data rates, only the sender must
|
||||
configure the data rate.
|
||||
|
||||
.. _espnow-long-range:
|
||||
|
||||
Long Range Mode
|
||||
---------------
|
||||
|
||||
(ESP32 Only, except ESP32-C2)
|
||||
|
||||
To use the `espnow.RATE_LORA_250K` and `espnow.RATE_LORA_500K` data rates,
|
||||
first set the `WLAN` interface object to long-range mode, i.e.::
|
||||
|
||||
import network, espnow
|
||||
sta = network.WLAN(network.WLAN.IF_STA)
|
||||
sta.active(True)
|
||||
sta.config(channel=6, protocol=WLAN.PROTOCOL_LR) # Set on sender & receiver
|
||||
e = espnow.ESPNow()
|
||||
e.config(rate=espnow.RATE_LORA_250K) # Needed on sender only
|
||||
|
||||
For more information about the limitations of long-range mode, see `WLAN.PROTOCOL_LR`.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
@@ -636,7 +588,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.WLAN.IF_STA).active(True)
|
||||
network.WLAN(network.STA_IF).active(True)
|
||||
else:
|
||||
raise err
|
||||
|
||||
@@ -693,7 +645,7 @@ A small async server example::
|
||||
import asyncio
|
||||
|
||||
# A WLAN interface must be active to send()/recv()
|
||||
network.WLAN(network.WLAN.IF_STA).active(True)
|
||||
network.WLAN(network.STA_IF).active(True)
|
||||
|
||||
e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support
|
||||
e.active(True)
|
||||
@@ -795,8 +747,8 @@ ESPNow and Wifi Operation
|
||||
-------------------------
|
||||
|
||||
ESPNow messages may be sent and received on any `active()<network.WLAN.active>`
|
||||
`WLAN<network.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
|
||||
`WLAN<network.WLAN()>` interface (``network.STA_IF`` or ``network.AP_IF``), even
|
||||
if that interface is also connected to a wifi network or configured as an access
|
||||
point. When an ESP32 or ESP8266 device connects to a Wifi Access Point (see
|
||||
`ESP32 Quickref <../esp32/quickref.html#networking>`__) the following things
|
||||
happen which affect ESPNow communications:
|
||||
@@ -880,8 +832,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.WLAN.IF_STA); sta.active(False)
|
||||
ap = network.WLAN(network.WLAN.IF_AP); ap.active(False)
|
||||
sta = network.WLAN(network.STA_IF); sta.active(False)
|
||||
ap = network.WLAN(network.AP_IF); ap.active(False)
|
||||
sta.active(True)
|
||||
while not sta.active():
|
||||
time.sleep(0.1)
|
||||
|
||||
@@ -114,7 +114,7 @@ Drawing text
|
||||
|
||||
.. method:: FrameBuffer.text(s, x, y[, c])
|
||||
|
||||
Write text to the FrameBuffer using the coordinates as the upper-left
|
||||
Write text to the FrameBuffer using the 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.
|
||||
@@ -137,18 +137,6 @@ Other methods
|
||||
is compared to the value from *palette*, not to the value directly from
|
||||
*fbuf*.)
|
||||
|
||||
*fbuf* can be another FrameBuffer instance, or a tuple or list of the form::
|
||||
|
||||
(buffer, width, height, format)
|
||||
|
||||
or::
|
||||
|
||||
(buffer, width, height, format, stride)
|
||||
|
||||
This matches the signature of the FrameBuffer constructor, and the elements
|
||||
of the tuple/list are the same as the arguments to the constructor except that
|
||||
the *buffer* here can be read-only.
|
||||
|
||||
The *palette* argument enables blitting between FrameBuffers with differing
|
||||
formats. Typical usage is to render a monochrome or grayscale glyph/icon to
|
||||
a color display. The *palette* is a FrameBuffer instance whose format is
|
||||
|
||||
@@ -69,7 +69,6 @@ library.
|
||||
heapq.rst
|
||||
io.rst
|
||||
json.rst
|
||||
marshal.rst
|
||||
math.rst
|
||||
os.rst
|
||||
platform.rst
|
||||
@@ -104,9 +103,7 @@ the following libraries.
|
||||
micropython.rst
|
||||
neopixel.rst
|
||||
network.rst
|
||||
openamp.rst
|
||||
uctypes.rst
|
||||
vfs.rst
|
||||
|
||||
The following libraries provide drivers for hardware components.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
.. currentmodule:: machine
|
||||
.. _machine.Counter:
|
||||
|
||||
class Counter -- pulse counter
|
||||
==============================
|
||||
|
||||
Counter implements pulse counting by monitoring an input signal and counting
|
||||
rising or falling edges.
|
||||
|
||||
Minimal example usage::
|
||||
|
||||
from machine import Pin, Counter
|
||||
|
||||
counter = Counter(0, Pin(0, Pin.IN)) # create Counter for pin 0 and begin counting
|
||||
value = counter.value() # retrieve current pulse count
|
||||
|
||||
Availability: **ESP32**
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Counter(id, ...)
|
||||
|
||||
Returns the singleton Counter object for the the given *id*. Values of *id*
|
||||
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
|
||||
used to select hardware block #0, #1, etc.
|
||||
|
||||
Additional arguments are passed to the :meth:`init` method described below,
|
||||
and will cause the Counter instance to be re-initialised and reset.
|
||||
|
||||
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: Counter.init(src, *, ...)
|
||||
|
||||
Initialise and reset the Counter with the given parameters:
|
||||
|
||||
- *src* specifies the input pin as a :ref:`machine.Pin <machine.Pin>` object.
|
||||
May be omitted on ports that have a predefined pin for a given hardware
|
||||
block.
|
||||
|
||||
Additional keyword-only parameters that may be supported by a port are:
|
||||
|
||||
- *edge* specifies the edge to count. Either ``Counter.RISING`` (the default)
|
||||
or ``Counter.FALLING``. *(Supported on ESP32)*
|
||||
|
||||
- *direction* specifies the direction to count. Either ``Counter.UP`` (the
|
||||
default) or ``Counter.DOWN``. *(Supported on ESP32)*
|
||||
|
||||
- *filter_ns* specifies a minimum period of time in nanoseconds that the
|
||||
source signal needs to be stable for a pulse to be counted. Implementations
|
||||
should use the longest filter supported by the hardware that is less than
|
||||
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
|
||||
|
||||
.. method:: Counter.deinit()
|
||||
|
||||
Stops the Counter, disabling any interrupts and releasing hardware resources.
|
||||
A Soft Reset should deinitialize all Counter objects.
|
||||
|
||||
.. method:: Counter.value([value])
|
||||
|
||||
Get, and optionally set, the counter value as a signed integer.
|
||||
Implementations must aim to do the get and set atomically (i.e. without
|
||||
leading to skipped counts).
|
||||
|
||||
This counter value could exceed the range of a :term:`small integer`, which
|
||||
means that calling :meth:`Counter.value` could cause a heap allocation, but
|
||||
implementations should aim to ensure that internal state only uses small
|
||||
integers and therefore will not allocate until the user calls
|
||||
:meth:`Counter.value`.
|
||||
|
||||
For example, on ESP32, the internal state counts overflows of the hardware
|
||||
counter (every 32000 counts), which means that it will not exceed the small
|
||||
integer range until ``2**30 * 32000`` counts (slightly over 1 year at 1MHz).
|
||||
|
||||
In general, it is recommended that you should use ``Counter.value(0)`` to reset
|
||||
the counter (i.e. to measure the counts since the last call), and this will
|
||||
avoid this problem.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: Counter.RISING
|
||||
Counter.FALLING
|
||||
|
||||
Select the pulse edge.
|
||||
|
||||
.. data:: Counter.UP
|
||||
Counter.DOWN
|
||||
|
||||
Select the counting direction.
|
||||
@@ -1,68 +0,0 @@
|
||||
.. currentmodule:: machine
|
||||
.. _machine.DAC:
|
||||
|
||||
class DAC -- digital to analog conversion
|
||||
=========================================
|
||||
|
||||
The DAC is used to output an analog voltage based on a digital value.
|
||||
|
||||
The output voltage will be between 0 and 3.3V.
|
||||
|
||||
DAC is currently supported on ESP32 [#esp32_dac]_, SAMD and Renesas RA.
|
||||
|
||||
.. note::
|
||||
The STM32 port has similar functionality to ``machine.DAC``. See
|
||||
:ref:`pyb.DAC <pyb.DAC>` for details.
|
||||
|
||||
Example usage (ESP32)::
|
||||
|
||||
from machine import DAC
|
||||
|
||||
dac = DAC(pin) # create a DAC object acting on a pin
|
||||
dac.write(128) # write a value to the DAC
|
||||
dac.write(255) # output maximum value, 3.3V
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: DAC(id)
|
||||
|
||||
Construct a new DAC object.
|
||||
|
||||
``id`` is a pin object (ESP32 and Renesas RA) or an index to a DAC resource (SAMD).
|
||||
|
||||
.. note::
|
||||
On the ESP32, DAC functionality is available on pins 25 and 26. On the
|
||||
ESP32-S2, pins 17 and 18. See :ref:`ESP32 Quickref <esp32_quickref>`
|
||||
for more details.
|
||||
|
||||
.. note::
|
||||
SAMD21 has one DAC resource, SAMD51 has two. See :ref:`SAMD Quickref <samd_quickref>`
|
||||
for more details.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: DAC.write(value)
|
||||
|
||||
Output an analog voltage to the pin connected to the DAC.
|
||||
|
||||
``value`` is a representation of the desired output; a linear interpolation of
|
||||
0-3.3V, though the range differs depending on the port and micro, see below:
|
||||
|
||||
+--------------+------+--------+
|
||||
| *Port/micro* | Bits | Range |
|
||||
+==============+======+========+
|
||||
| ESP32 | 8 | 0-255 |
|
||||
+--------------+------+--------+
|
||||
| SAMD21 | 10 | 0-1023 |
|
||||
+--------------+------+--------+
|
||||
| SAMD51 | 12 | 0-4095 |
|
||||
+--------------+------+--------+
|
||||
| Renesas RA | 12 | 0-4095 |
|
||||
+--------------+------+--------+
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [#esp32_dac] The original ESP32 and ESP32-S2 *only*, since DAC hardware is
|
||||
not present on other microcontrollers in the family.
|
||||
@@ -1,72 +0,0 @@
|
||||
.. currentmodule:: machine
|
||||
.. _machine.Encoder:
|
||||
|
||||
class Encoder -- quadrature decoding
|
||||
====================================
|
||||
|
||||
Encoder implements decoding of quadrature signals as commonly output from
|
||||
rotary encoders, by counting either up or down depending on the order of two
|
||||
input pulses.
|
||||
|
||||
Minimal example usage::
|
||||
|
||||
from machine import Pin, Encoder
|
||||
|
||||
counter = Counter(0, Pin(0, Pin.IN), Pin(1, Pin.IN)) # create Encoder for pins 0, 1 and begin counting
|
||||
value = counter.value() # retrieve current count
|
||||
|
||||
Availability: **ESP32**
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Encoder(id, ...)
|
||||
|
||||
Returns the singleton Encoder object for the the given *id*. Values of *id*
|
||||
depend on a particular port and its hardware. Values 0, 1, etc. are commonly
|
||||
used to select hardware block #0, #1, etc.
|
||||
|
||||
Additional arguments are passed to the :meth:`init` method described below,
|
||||
and will cause the Encoder instance to be re-initialised and reset.
|
||||
|
||||
On ESP32, the *id* corresponds to a :ref:`PCNT unit <esp32.PCNT>`.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: Encoder.init(phase_a, phase_b, *, ...)
|
||||
|
||||
Initialise and reset the Encoder with the given parameters:
|
||||
|
||||
- *phase_a* specifies the first input pin as a
|
||||
:ref:`machine.Pin <machine.Pin>` object.
|
||||
|
||||
- *phase_b* specifies the second input pin as a
|
||||
:ref:`machine.Pin <machine.Pin>` object.
|
||||
|
||||
These pins may be omitted on ports that have predefined pins for a given
|
||||
hardware block.
|
||||
|
||||
Additional keyword-only parameters that may be supported by a port are:
|
||||
|
||||
- *filter_ns* specifies a minimum period of time in nanoseconds that the
|
||||
source signal needs to be stable for a pulse to be counted. Implementations
|
||||
should use the longest filter supported by the hardware that is less than
|
||||
or equal to this value. The default is 0 (no filter). *(Supported on ESP32)*
|
||||
|
||||
- *phases* specifies the number of signal edges to count and thus the
|
||||
granularity of the decoding. e.g. 4 phases corresponds to "4x quadrature
|
||||
decoding", and will result in four counts per pulse. Ports may support
|
||||
either 1, 2, or 4 phases and the default is 1 phase. *(Supported on ESP32)*
|
||||
|
||||
.. method:: Encoder.deinit()
|
||||
|
||||
Stops the Encoder, disabling any interrupts and releasing hardware resources.
|
||||
A Soft Reset should deinitialize all Encoder objects.
|
||||
|
||||
.. method:: Encoder.value([value])
|
||||
|
||||
Get, and optionally set, the encoder value as a signed integer.
|
||||
Implementations should aim to do the get and set atomically.
|
||||
|
||||
See :meth:`machine.Counter.value` for details about overflow of this value.
|
||||
@@ -1,174 +0,0 @@
|
||||
.. currentmodule:: machine
|
||||
.. _machine.I2CTarget:
|
||||
|
||||
class I2CTarget -- an I2C target device
|
||||
=======================================
|
||||
|
||||
An I2C target is a device which connects to an I2C bus and is controlled by an
|
||||
I2C controller. I2C targets can take many forms. The :class:`machine.I2CTarget`
|
||||
class implements an I2C target that can be configured as a memory/register device,
|
||||
or as an arbitrary I2C device by using callbacks (if supported by the port).
|
||||
|
||||
Example usage for the case of a memory device::
|
||||
|
||||
from machine import I2CTarget
|
||||
|
||||
# Create the backing memory for the I2C target.
|
||||
mem = bytearray(8)
|
||||
|
||||
# Create an I2C target. Depending on the port, extra parameters
|
||||
# may be required to select the peripheral and/or pins to use.
|
||||
i2c = I2CTarget(addr=67, mem=mem)
|
||||
|
||||
# At this point an I2C controller can read and write `mem`.
|
||||
...
|
||||
|
||||
# Deinitialise the I2C target.
|
||||
i2c.deinit()
|
||||
|
||||
Note that some ports require an ``id``, and maybe ``scl`` and ``sda`` pins, to be
|
||||
passed to the `I2CTarget` constructor, to select the hardware I2C instance and
|
||||
pins that it connects to.
|
||||
|
||||
When configured as a memory device, it's also possible to register to receive events.
|
||||
For example to be notified when the memory is read/written::
|
||||
|
||||
from machine import I2CTarget
|
||||
|
||||
# Define an IRQ handler, for I2C events.
|
||||
def irq_handler(i2c_target):
|
||||
flags = i2c_target.irq().flags()
|
||||
if flags & I2CTarget.IRQ_END_READ:
|
||||
print("controller read target at addr", i2c_target.memaddr)
|
||||
if flags & I2CTarget.IRQ_END_WRITE:
|
||||
print("controller wrote target at addr", i2c_target.memaddr)
|
||||
|
||||
# Create the I2C target and register to receive default events.
|
||||
mem = bytearray(8)
|
||||
i2c = I2CTarget(addr=67, mem=mem)
|
||||
i2c.irq(irq_handler)
|
||||
|
||||
More complicated I2C devices can be implemented using the full set of events. For
|
||||
example, to see the raw events as they are triggered::
|
||||
|
||||
from machine import I2CTarget
|
||||
|
||||
# Define an IRQ handler that prints the event id and responds to reads/writes.
|
||||
def irq_handler(i2c_target, buf=bytearray(1)):
|
||||
flags = i2c_target.irq().flags()
|
||||
print(flags)
|
||||
if flags & I2CTarget.IRQ_READ_REQ:
|
||||
i2c_target.write(buf)
|
||||
if flags & I2CTarget.IRQ_WRITE_REQ:
|
||||
i2c_target.readinto(buf)
|
||||
|
||||
# Create the I2C target and register to receive all events.
|
||||
i2c = I2CTarget(addr=67)
|
||||
all_triggers = (
|
||||
I2CTarget.IRQ_ADDR_MATCH_READ
|
||||
| I2CTarget.IRQ_ADDR_MATCH_WRITE
|
||||
| I2CTarget.IRQ_READ_REQ
|
||||
| I2CTarget.IRQ_WRITE_REQ
|
||||
| I2CTarget.IRQ_END_READ
|
||||
| I2CTarget.IRQ_END_WRITE
|
||||
)
|
||||
i2c.irq(irq_handler, trigger=all_triggers, hard=True)
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: I2CTarget(id, addr, *, addrsize=7, mem=None, mem_addrsize=8, scl=None, sda=None)
|
||||
|
||||
Construct and return a new I2CTarget object using the following parameters:
|
||||
|
||||
- *id* identifies a particular I2C peripheral. Allowed values depend on the
|
||||
particular port/board. Some ports have a default in which case this parameter
|
||||
can be omitted.
|
||||
- *addr* is the I2C address of the target.
|
||||
- *addrsize* is the number of bits in the I2C target address. Valid values
|
||||
are 7 and 10.
|
||||
- *mem* is an object with the buffer protocol that is writable. If not
|
||||
specified then there is no backing memory and data must be read/written
|
||||
using the :meth:`I2CTarget.readinto` and :meth:`I2CTarget.write` methods.
|
||||
- *mem_addrsize* is the number of bits in the memory address. Valid values
|
||||
are 0, 8, 16, 24 and 32.
|
||||
- *scl* is a pin object specifying the pin to use for SCL.
|
||||
- *sda* is a pin object specifying the pin to use for SDA.
|
||||
|
||||
Note that some ports/boards will have default values of *scl* and *sda*
|
||||
that can be changed in this constructor. Others will have fixed values
|
||||
of *scl* and *sda* that cannot be changed.
|
||||
|
||||
General Methods
|
||||
---------------
|
||||
|
||||
.. method:: I2CTarget.deinit()
|
||||
|
||||
Deinitialise the I2C target. After this method is called the hardware will no
|
||||
longer respond to requests on the I2C bus, and no other methods can be called.
|
||||
|
||||
.. method:: I2CTarget.readinto(buf)
|
||||
|
||||
Read into the given buffer any pending bytes written by the I2C controller.
|
||||
Returns the number of bytes read.
|
||||
|
||||
.. method:: I2CTarget.write(buf)
|
||||
|
||||
Write out the bytes from the given buffer, to be passed to the I2C controller
|
||||
after it sends a read request. Returns the number of bytes written. Most ports
|
||||
only accept one byte at a time to this method.
|
||||
|
||||
.. method:: I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE, hard=False)
|
||||
|
||||
Configure an IRQ *handler* to be called when an event occurs. The possible events are
|
||||
given by the following constants, which can be or'd together and passed to the *trigger*
|
||||
argument:
|
||||
|
||||
- ``IRQ_ADDR_MATCH_READ`` indicates that the target was addressed by a
|
||||
controller for a read transaction.
|
||||
- ``IRQ_ADDR_MATCH_WRITE`` indicates that the target was addressed by a
|
||||
controller for a write transaction.
|
||||
- ``IRQ_READ_REQ`` indicates that the controller is requesting data, and this
|
||||
request must be satisfied by calling `I2CTarget.write` with the data to be
|
||||
passed back to the controller.
|
||||
- ``IRQ_WRITE_REQ`` indicates that the controller has written data, and the
|
||||
data must be read by calling `I2CTarget.readinto`.
|
||||
- ``IRQ_END_READ`` indicates that the controller has finished a read transaction.
|
||||
- ``IRQ_END_WRITE`` indicates that the controller has finished a write transaction.
|
||||
|
||||
Not all triggers are available on all ports. If a port has the constant then that
|
||||
event is available.
|
||||
|
||||
Note the following restrictions:
|
||||
|
||||
- ``IRQ_ADDR_MATCH_READ``, ``IRQ_ADDR_MATCH_WRITE``, ``IRQ_READ_REQ`` and
|
||||
``IRQ_WRITE_REQ`` must be handled by a hard IRQ callback (with the *hard* argument
|
||||
set to ``True``). This is because these events have very strict timing requirements
|
||||
and must usually be satisfied synchronously with the hardware event.
|
||||
|
||||
- ``IRQ_END_READ`` and ``IRQ_END_WRITE`` may be handled by either a soft or hard
|
||||
IRQ callback (although note that all events must be registered with the same handler,
|
||||
so if any events need a hard callback then all events must be hard).
|
||||
|
||||
- If a memory buffer has been supplied in the constructor then ``IRQ_END_WRITE``
|
||||
is not emitted for the transaction that writes the memory address. This is to
|
||||
allow ``IRQ_END_READ`` and ``IRQ_END_WRITE`` to function correctly as soft IRQ
|
||||
callbacks, where the IRQ handler may be called quite some time after the actual
|
||||
hardware event.
|
||||
|
||||
.. attribute:: I2CTarget.memaddr
|
||||
|
||||
The integer value of the most recent memory address that was selected by the I2C
|
||||
controller (only valid if ``mem`` was specified in the constructor).
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: I2CTarget.IRQ_ADDR_MATCH_READ
|
||||
I2CTarget.IRQ_ADDR_MATCH_WRITE
|
||||
I2CTarget.IRQ_READ_REQ
|
||||
I2CTarget.IRQ_WRITE_REQ
|
||||
I2CTarget.IRQ_END_READ
|
||||
I2CTarget.IRQ_END_WRITE
|
||||
|
||||
IRQ trigger sources.
|
||||
@@ -11,20 +11,20 @@ Example usage::
|
||||
from machine import PWM
|
||||
|
||||
pwm = PWM(pin, freq=50, duty_u16=8192) # create a PWM object on a pin
|
||||
# and set freq 50 Hz and duty 12.5%
|
||||
pwm.duty_u16(32768) # set duty to 50%
|
||||
# and set freq and duty
|
||||
pwm.duty_u16(32768) # set duty to 50%
|
||||
|
||||
# reinitialise with a period of 200us, duty of 5us
|
||||
pwm.init(freq=5000, duty_ns=5000)
|
||||
|
||||
pwm.duty_ns(3000) # set pulse width to 3us
|
||||
pwm.duty_ns(3000) # set pulse width to 3us
|
||||
|
||||
pwm.deinit()
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert=False)
|
||||
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert)
|
||||
|
||||
Construct and return a new PWM object using the following parameters:
|
||||
|
||||
@@ -40,7 +40,7 @@ Constructors
|
||||
Setting *freq* may affect other PWM objects if the objects share the same
|
||||
underlying PWM generator (this is hardware specific).
|
||||
Only one of *duty_u16* and *duty_ns* should be specified at a time.
|
||||
*invert* is available only on the esp32, mimxrt, nrf, rp2, samd and zephyr ports.
|
||||
*invert* is not available at all ports.
|
||||
|
||||
Methods
|
||||
-------
|
||||
@@ -86,7 +86,7 @@ Specific PWM class implementations
|
||||
|
||||
The following concrete class(es) implement enhancements to the PWM class.
|
||||
|
||||
| :ref:`pyb.Timer for PyBoard <pyb.Timer>`
|
||||
| :ref:`pyb.Timer for PyBoard <pyb.Timer>`
|
||||
|
||||
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
|
||||
@@ -116,10 +116,10 @@ Limitations of PWM
|
||||
resolution of 8 bit, not 16-bit as may be expected. In this case, the lowest
|
||||
8 bits of *duty_u16* are insignificant. So::
|
||||
|
||||
pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2)
|
||||
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2)
|
||||
|
||||
and::
|
||||
|
||||
pwm=PWM(Pin(13), freq=300_000, duty_u16=65536//2 + 255)
|
||||
pwm=PWM(Pin(13), freq=300_000, duty_u16=2**16//2 + 255)
|
||||
|
||||
will generate PWM with the same 50% duty cycle.
|
||||
|
||||
@@ -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: mimxrt, nrf, renesas-ra, rp2, samd, stm32 ports.
|
||||
Availability: nrf, rp2, stm32 ports.
|
||||
|
||||
.. method:: Pin.high()
|
||||
|
||||
Set pin to "1" output level.
|
||||
|
||||
Availability: mimxrt, nrf, renesas-ra, rp2, samd, stm32 ports.
|
||||
Availability: nrf, rp2, stm32 ports.
|
||||
|
||||
.. method:: Pin.mode([mode])
|
||||
|
||||
@@ -238,12 +238,6 @@ 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
|
||||
---------
|
||||
|
||||
|
||||
@@ -42,21 +42,12 @@ Methods
|
||||
|
||||
Initialise the RTC. Datetime is a tuple of the form:
|
||||
|
||||
``(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.
|
||||
``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])``
|
||||
|
||||
.. 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.
|
||||
@@ -71,13 +62,10 @@ Methods
|
||||
|
||||
Get the number of milliseconds left before the alarm expires.
|
||||
|
||||
.. method:: RTC.alarm_cancel(alarm_id=0)
|
||||
.. method:: RTC.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.
|
||||
@@ -87,21 +75,6 @@ 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
|
||||
---------
|
||||
|
||||
|
||||
@@ -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 vfs
|
||||
import os
|
||||
# clk cmd and dat0 pins must be passed along with
|
||||
# their respective alternate functions
|
||||
sd = machine.SD(pins=('GP10', 'GP11', 'GP15'))
|
||||
vfs.mount(sd, '/sd')
|
||||
os.mount(sd, '/sd')
|
||||
# do normal file operations
|
||||
|
||||
Constructors
|
||||
|
||||
@@ -23,23 +23,21 @@ 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, cmd=None, data=None, freq=20000000)
|
||||
.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=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:`vfs.AbstractBlockDev`.
|
||||
The class implements the block protocol defined by :class:`os.AbstractBlockDev`.
|
||||
This allows the mounting of an SD card to be as simple as::
|
||||
|
||||
vfs.mount(machine.SDCard(), "/sd")
|
||||
os.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. This many data
|
||||
pins must be connected to the SD card.
|
||||
- *width* selects the bus width for the SD/MMC interface.
|
||||
|
||||
- *cd* can be used to specify a card-detect pin.
|
||||
|
||||
@@ -53,14 +51,7 @@ vary from platform to platform.
|
||||
|
||||
- *cs* can be used to specify an SPI chip select pin.
|
||||
|
||||
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.
|
||||
- *freq* selects the SD/MMC interface frequency in Hz (only supported on the ESP32).
|
||||
|
||||
Implementation-specific details
|
||||
-------------------------------
|
||||
@@ -76,130 +67,52 @@ The standard PyBoard has just one slot. No arguments are necessary or supported.
|
||||
ESP32
|
||||
`````
|
||||
|
||||
SD cards support access in both SD/MMC mode and the simpler (but slower) SPI
|
||||
mode.
|
||||
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.
|
||||
|
||||
SPI mode makes use of a `SPI` host peripheral, which cannot concurrently be used
|
||||
for other SPI interactions.
|
||||
.. note:: Slot 0 is used to communicate with on-board flash memory
|
||||
on most ESP32 modules and so will be unavailable to the
|
||||
user.
|
||||
|
||||
The ``slot`` argument determines which mode is used. Different values are
|
||||
supported on different chips:
|
||||
.. 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.
|
||||
|
||||
========== ======== ======== ============ ============
|
||||
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)
|
||||
========== ======== ======== ============ ============
|
||||
The pins used by the dedicated SD/MMC hardware are fixed. The pins
|
||||
used by the SPI hardware can be reassigned.
|
||||
|
||||
Different slots support different data bus widths (number of data pins):
|
||||
.. 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.
|
||||
|
||||
========== ========== =====================
|
||||
Slot Type Supported data widths
|
||||
========== ========== =====================
|
||||
0 SD/MMC 1, 4, 8
|
||||
1 SD/MMC 1, 4
|
||||
2 SPI 1
|
||||
3 SPI 1
|
||||
========== ========== =====================
|
||||
The default (and preferred) pin assignment are as follows:
|
||||
|
||||
.. 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`.
|
||||
====== ====== ====== ====== ======
|
||||
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
|
||||
====== ====== ====== ====== ======
|
||||
|
||||
cc3200
|
||||
``````
|
||||
|
||||
@@ -4,52 +4,41 @@
|
||||
class Timer -- control hardware timers
|
||||
======================================
|
||||
|
||||
Timer class provides the ability to trigger a Python callback function after an
|
||||
expiry time, or periodically at a regular interval.
|
||||
Hardware timers deal with timing of periods and events. Timers are perhaps
|
||||
the most flexible and heterogeneous kind of hardware in MCUs and SoCs,
|
||||
differently greatly from a model to a model. MicroPython's Timer class
|
||||
defines a baseline operation of executing a callback with a given period
|
||||
(or once after some delay), and allow specific boards to define more
|
||||
non-standard behaviour (which thus won't be portable to other boards).
|
||||
|
||||
The available features and restrictions of Timer objects vary depending on the
|
||||
MicroPython board and port.
|
||||
See discussion of :ref:`important constraints <machine_callbacks>` on
|
||||
Timer callbacks.
|
||||
|
||||
.. note::
|
||||
|
||||
Memory can't be allocated inside irq handlers (an interrupt) and so
|
||||
exceptions raised within a handler don't give much information. See
|
||||
:func:`micropython.alloc_emergency_exception_buf` for how to get around this
|
||||
limitation.
|
||||
|
||||
If you are using a WiPy board please refer to :ref:`machine.TimerWiPy <machine.TimerWiPy>`
|
||||
instead of this class.
|
||||
|
||||
Timer Types
|
||||
-----------
|
||||
|
||||
There are two types of Timer in MicroPython, but not all ports support both:
|
||||
|
||||
- Virtual timers. These are managed in software, and are generally more
|
||||
flexible. Multiple virtual timers can be constructed and active at once. The
|
||||
``id`` of a virtual timer is ``-1``. Not all ports support virtual timers, but
|
||||
it's recommended to use them when available.
|
||||
- Hardware timers. Hardware timers have integer ``id`` values starting at ``0``.
|
||||
The number of available ``id`` values is determined by the hardware. Hardware
|
||||
timers may be more accurate for very fine sub-millisecond timing (especially
|
||||
when ``hard=True`` is supported and set, see :ref:`isr_rules`.) Most
|
||||
microcontroller ports support hardware timers, except Zephyr and RP2 which
|
||||
only support virtual timers.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Timer(id, /, ...)
|
||||
|
||||
Construct a new Timer object with the given ``id``.
|
||||
|
||||
On ports which support virtual timers the ``id`` parameter is optional - the
|
||||
default value is ``-1`` which constructs a virtual timer.
|
||||
|
||||
On ports which support hardware timers, setting the ``id`` parameter to a
|
||||
non-negative integer determines which timer to use.
|
||||
|
||||
Construct a new timer object of the given ``id``. ``id`` of -1 constructs a
|
||||
virtual timer (if supported by a board).
|
||||
``id`` shall not be passed as a keyword argument.
|
||||
|
||||
Any additional parameters are handled the same as :func:`Timer.init()`.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None, hard=True)
|
||||
.. method:: Timer.init(*, mode=Timer.PERIODIC, freq=-1, period=-1, callback=None)
|
||||
|
||||
Initialise the timer. Example::
|
||||
|
||||
@@ -83,23 +72,10 @@ Methods
|
||||
|
||||
- ``callback`` - The callable to call upon expiration of the timer period.
|
||||
The callback must take one argument, which is passed the Timer object.
|
||||
|
||||
The ``callback`` argument shall be specified. Otherwise an exception
|
||||
will occur upon timer expiration:
|
||||
``TypeError: 'NoneType' object isn't callable``
|
||||
|
||||
- ``hard`` can be one of:
|
||||
|
||||
- ``True`` - The callback will be executed in hard interrupt context,
|
||||
which minimises delay and jitter but is subject to the limitations
|
||||
described in :ref:`isr_rules`. Not all ports support hard interrupts,
|
||||
see the port documentation for more information.
|
||||
- ``False`` - The callback will be scheduled as a soft interrupt,
|
||||
allowing it to allocate but possibly also introducing
|
||||
garbage-collection delays and jitter.
|
||||
|
||||
The default value of this parameter is port-specific for historical reasons.
|
||||
|
||||
.. method:: Timer.deinit()
|
||||
|
||||
Deinitialises the timer. Stops the timer, and disables the timer peripheral.
|
||||
|
||||
@@ -18,6 +18,16 @@ defines a baseline operation of executing a callback with a given period
|
||||
(or once after some delay), and allow specific boards to define more
|
||||
non-standard behaviour (which thus won't be portable to other boards).
|
||||
|
||||
See discussion of :ref:`important constraints <machine_callbacks>` on
|
||||
Timer callbacks.
|
||||
|
||||
.. note::
|
||||
|
||||
Memory can't be allocated inside irq handlers (an interrupt) and so
|
||||
exceptions raised within a handler don't give much information. See
|
||||
:func:`micropython.alloc_emergency_exception_buf` for how to get around this
|
||||
limitation.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
@@ -61,7 +71,7 @@ Methods
|
||||
|
||||
Otherwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
The operating mode is the one configured to the Timer object that was used to
|
||||
The operating mode is is the one configured to the Timer object that was used to
|
||||
create the channel.
|
||||
|
||||
- ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``.
|
||||
@@ -124,9 +134,6 @@ Methods
|
||||
``TimerWiPy.ONE_SHOT``. In the case that mode is ``TimerWiPy.PWM`` then trigger must be equal to
|
||||
``TimerWiPy.MATCH``.
|
||||
|
||||
Note that callback handlers are hard interrupts, and the constraints described in :ref:`isr_rules`
|
||||
apply when they are executed.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. method:: timerchannel.freq([value])
|
||||
|
||||
@@ -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 RX pin must be given as well. The same applies to CTS.
|
||||
If the RTS pin is given the 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,6 +152,31 @@ 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
|
||||
@@ -160,7 +185,7 @@ Methods
|
||||
|
||||
.. note::
|
||||
|
||||
For the esp8266 and nrf ports the call returns while the last byte is sent.
|
||||
For the rp2, esp8266 and nrf ports the call returns while the last byte is sent.
|
||||
If required, a one character wait time has to be added in the calling script.
|
||||
|
||||
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
|
||||
@@ -172,92 +197,17 @@ Methods
|
||||
|
||||
.. note::
|
||||
|
||||
For the esp8266 and nrf ports the call may return ``True`` even if the last byte
|
||||
For the rp2, esp8266 and nrf ports the call may return ``True`` even if the last byte
|
||||
of a transfer is still being sent. If required, a one character wait time has to be
|
||||
added in the calling script.
|
||||
|
||||
Availability: rp2, esp32, esp8266, mimxrt, cc3200, stm32, nrf ports, renesas-ra
|
||||
|
||||
.. 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. It uses Timer(0)
|
||||
for UART.IRQ_RXIDLE, so this timer cannot be used for other means.
|
||||
|
||||
- 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.RTS
|
||||
UART.CTS
|
||||
.. data:: UART.RX_ANY
|
||||
|
||||
Flow control options.
|
||||
IRQ trigger sources
|
||||
|
||||
Availability: esp32, mimxrt, renesas-ra, rp2, stm32.
|
||||
|
||||
.. data:: UART.IRQ_RXIDLE
|
||||
UART.IRQ_RX
|
||||
UART.IRQ_TXIDLE
|
||||
UART.IRQ_BREAK
|
||||
|
||||
IRQ trigger sources.
|
||||
|
||||
Availability: renesas-ra, stm32, esp32, rp2040, mimxrt, samd, cc3200.
|
||||
Availability: WiPy.
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
.. 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 <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
|
||||
<filesystem>`. 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
|
||||
@@ -11,6 +11,14 @@ and unrestricted access to and control of hardware blocks on a system
|
||||
malfunction, lockups, crashes of your board, and in extreme cases, hardware
|
||||
damage.
|
||||
|
||||
.. _machine_callbacks:
|
||||
|
||||
A note of callbacks used by functions and class methods of :mod:`machine` module:
|
||||
all these callbacks should be considered as executing in an interrupt context.
|
||||
This is true for both physical devices with IDs >= 0 and "virtual" devices
|
||||
with negative IDs like -1 (these "virtual" devices are still thin shims on
|
||||
top of real hardware and real hardware interrupts). See :ref:`isr_rules`.
|
||||
|
||||
Memory access
|
||||
-------------
|
||||
|
||||
@@ -54,13 +62,14 @@ Reset related functions
|
||||
|
||||
.. function:: reset()
|
||||
|
||||
:ref:`Hard resets <hard_reset>` the device in a manner similar to pushing the
|
||||
external RESET button.
|
||||
Resets the device in a manner similar to pushing the external RESET
|
||||
button.
|
||||
|
||||
.. function:: soft_reset()
|
||||
|
||||
Performs a :ref:`soft reset <soft_reset>` of the interpreter, deleting all
|
||||
Python objects and resetting the Python heap.
|
||||
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).
|
||||
|
||||
.. function:: reset_cause()
|
||||
|
||||
@@ -118,20 +127,14 @@ 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, 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.
|
||||
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).
|
||||
|
||||
.. function:: sleep()
|
||||
|
||||
.. note:: This function is deprecated, use :func:`lightsleep()` instead with no arguments.
|
||||
.. note:: This function is deprecated, use `lightsleep()` instead with no arguments.
|
||||
|
||||
.. function:: lightsleep([time_ms])
|
||||
deepsleep([time_ms])
|
||||
@@ -252,18 +255,13 @@ Classes
|
||||
machine.Signal.rst
|
||||
machine.ADC.rst
|
||||
machine.ADCBlock.rst
|
||||
machine.DAC.rst
|
||||
machine.PWM.rst
|
||||
machine.UART.rst
|
||||
machine.SPI.rst
|
||||
machine.I2C.rst
|
||||
machine.I2CTarget.rst
|
||||
machine.I2S.rst
|
||||
machine.RTC.rst
|
||||
machine.Timer.rst
|
||||
machine.Counter.rst
|
||||
machine.Encoder.rst
|
||||
machine.WDT.rst
|
||||
machine.SD.rst
|
||||
machine.SDCard.rst
|
||||
machine.USBDevice.rst
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
: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.
|
||||
@@ -125,11 +125,8 @@ Functions
|
||||
Return the natural logarithm of the gamma function of ``x``.
|
||||
|
||||
.. function:: log(x)
|
||||
log(x, base)
|
||||
|
||||
With one argument, return the natural logarithm of *x*.
|
||||
|
||||
With two arguments, return the logarithm of *x* to the given *base*.
|
||||
Return the natural logarithm of ``x``.
|
||||
|
||||
.. function:: log10(x)
|
||||
|
||||
|
||||
@@ -136,14 +136,6 @@ 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
|
||||
@@ -155,71 +147,3 @@ 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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user